Mercurial > audlegacy-plugins
comparison src/Input/cdaudio/http.c @ 0:13389e613d67 trunk
[svn] - initial import of audacious-plugins tree (lots to do)
| author | nenolod |
|---|---|
| date | Mon, 18 Sep 2006 01:11:49 -0700 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| -1:000000000000 | 0:13389e613d67 |
|---|---|
| 1 /* | |
| 2 * http.c | |
| 3 * Some simple routines for connecting to a remote tcp socket | |
| 4 * Copyright 1999 Håvard Kvålen <havardk@sol.no> | |
| 5 * | |
| 6 * This program is free software; you can redistribute it and/or modify | |
| 7 * it under the terms of the GNU General Public License as published by | |
| 8 * the Free Software Foundation; either version 2 of the License, or | |
| 9 * (at your option) any later version. | |
| 10 * | |
| 11 * This program is distributed in the hope that it will be useful, | |
| 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 14 * GNU General Public License for more details. | |
| 15 * | |
| 16 * You should have received a copy of the GNU General Public License | |
| 17 * along with this program; if not, write to the Free Software | |
| 18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |
| 19 */ | |
| 20 | |
| 21 /* FIXME: We need to have *one* place in xmms where you configure proxies */ | |
| 22 | |
| 23 #include "http.h" | |
| 24 | |
| 25 gint | |
| 26 http_open_connection(const gchar * server, gint port) | |
| 27 { | |
| 28 gint sock; | |
| 29 #ifdef USE_IPV6 | |
| 30 struct addrinfo hints, *res, *res0; | |
| 31 char service[6]; | |
| 32 #else | |
| 33 struct hostent *host; | |
| 34 struct sockaddr_in address; | |
| 35 #endif | |
| 36 | |
| 37 #ifdef USE_IPV6 | |
| 38 snprintf(service, 6, "%d", port); | |
| 39 memset(&hints, 0, sizeof(hints)); | |
| 40 hints.ai_socktype = SOCK_STREAM; | |
| 41 | |
| 42 if (getaddrinfo(server, service, &hints, &res0)) | |
| 43 return 0; | |
| 44 | |
| 45 for (res = res0; res; res = res->ai_next) { | |
| 46 sock = socket (res->ai_family, res->ai_socktype, res->ai_protocol); | |
| 47 if (sock < 0) { | |
| 48 if (res->ai_next) | |
| 49 continue; | |
| 50 else { | |
| 51 freeaddrinfo(res0); | |
| 52 return 0; | |
| 53 } | |
| 54 } | |
| 55 if (connect(sock, res->ai_addr, res->ai_addrlen) < 0) { | |
| 56 if (res->ai_next) { | |
| 57 close(sock); | |
| 58 continue; | |
| 59 } else { | |
| 60 freeaddrinfo(res0); | |
| 61 return 0; | |
| 62 } | |
| 63 } | |
| 64 freeaddrinfo(res0); | |
| 65 return sock; | |
| 66 } | |
| 67 #else | |
| 68 sock = socket(AF_INET, SOCK_STREAM, 0); | |
| 69 address.sin_family = AF_INET; | |
| 70 | |
| 71 if (!(host = gethostbyname(server))) | |
| 72 return 0; | |
| 73 | |
| 74 memcpy(&address.sin_addr.s_addr, *(host->h_addr_list), | |
| 75 sizeof(address.sin_addr.s_addr)); | |
| 76 address.sin_port = g_htons(port); | |
| 77 | |
| 78 if (connect | |
| 79 (sock, (struct sockaddr *) &address, | |
| 80 sizeof(struct sockaddr_in)) == -1) | |
| 81 return 0; | |
| 82 #endif | |
| 83 | |
| 84 return sock; | |
| 85 } | |
| 86 | |
| 87 void | |
| 88 http_close_connection(gint sock) | |
| 89 { | |
| 90 shutdown(sock, 2); | |
| 91 close(sock); | |
| 92 } | |
| 93 | |
| 94 gint | |
| 95 http_read_line(gint sock, gchar * buf, gint size) | |
| 96 { | |
| 97 gint i = 0; | |
| 98 | |
| 99 while (i < size - 1) { | |
| 100 if (read(sock, buf + i, 1) <= 0) { | |
| 101 if (i == 0) | |
| 102 return -1; | |
| 103 else | |
| 104 break; | |
| 105 } | |
| 106 if (buf[i] == '\n') | |
| 107 break; | |
| 108 if (buf[i] != '\r') | |
| 109 i++; | |
| 110 } | |
| 111 buf[i] = '\0'; | |
| 112 return i; | |
| 113 } | |
| 114 | |
| 115 gint | |
| 116 http_read_first_line(gint sock, gchar * buf, gint size) | |
| 117 { | |
| 118 /* Skips the HTTP-header, if there is one, and reads the first line into buf. | |
| 119 Returns number of bytes read. */ | |
| 120 | |
| 121 gint i; | |
| 122 /* Skip the HTTP-header */ | |
| 123 if ((i = http_read_line(sock, buf, size)) < 0) | |
| 124 return -1; | |
| 125 if (!strncmp(buf, "HTTP", 4)) { /* Check to make sure its not HTTP/0.9 */ | |
| 126 while (http_read_line(sock, buf, size) > 0) | |
| 127 /* nothing */ ; | |
| 128 if ((i = http_read_line(sock, buf, size)) < 0) | |
| 129 return -1; | |
| 130 } | |
| 131 | |
| 132 return i; | |
| 133 } | |
| 134 | |
| 135 gchar * | |
| 136 http_get(gchar * url) | |
| 137 { | |
| 138 gchar *server, *getstr, *buf = NULL, *bptr; | |
| 139 gchar *gs, *gc, *turl = url; | |
| 140 gint sock, n, bsize, port = 0; | |
| 141 | |
| 142 /* Skip past ``http://'' part of URL */ | |
| 143 if (!strncmp(turl, "http:", 5)) { | |
| 144 turl += 5; | |
| 145 if (!strncmp(turl, "//", 2)) | |
| 146 turl += 2; | |
| 147 } | |
| 148 | |
| 149 /* If path starts with a '/', we are referring to localhost */ | |
| 150 if (turl[0] == '/') | |
| 151 server = "localhost"; | |
| 152 else | |
| 153 server = turl; | |
| 154 | |
| 155 /* Check if URL contains port specification */ | |
| 156 gc = strchr(turl, ':'); | |
| 157 gs = strchr(turl, '/'); | |
| 158 | |
| 159 if (gc != NULL && gc < gs) { | |
| 160 port = atoi(gc + 1); | |
| 161 *gc = '\0'; | |
| 162 } | |
| 163 if (port == 0) | |
| 164 port = 80; | |
| 165 | |
| 166 /* Make sure that server string is null terminated. */ | |
| 167 if (gs) | |
| 168 *gs = '\0'; | |
| 169 | |
| 170 | |
| 171 /* | |
| 172 * Now, open connection to server. | |
| 173 */ | |
| 174 sock = http_open_connection(server, port); | |
| 175 | |
| 176 /* Repair the URL string that we broke earlier on */ | |
| 177 if (gs) | |
| 178 *gs = '/'; | |
| 179 if (gc && gc == '\0') | |
| 180 *gc = ':'; | |
| 181 | |
| 182 if (sock == 0) | |
| 183 return NULL; | |
| 184 | |
| 185 /* | |
| 186 * Send query to socket. | |
| 187 */ | |
| 188 getstr = g_strdup_printf("GET %s HTTP/1.0\r\n\r\n", gs ? gs : "/"); | |
| 189 /* getstr = g_strdup_printf("GET %s HTTP/1.0\r\n\r\n", url ? url : "/"); */ | |
| 190 | |
| 191 if (write(sock, getstr, strlen(getstr)) == -1) { | |
| 192 http_close_connection(sock); | |
| 193 return NULL; | |
| 194 } | |
| 195 | |
| 196 /* | |
| 197 * Start receiving result. | |
| 198 */ | |
| 199 bsize = 4096; | |
| 200 bptr = buf = g_malloc(bsize); | |
| 201 | |
| 202 if ((n = http_read_first_line(sock, bptr, bsize)) == -1) { | |
| 203 g_free(buf); | |
| 204 buf = NULL; | |
| 205 goto Done; | |
| 206 } | |
| 207 | |
| 208 bsize -= n; | |
| 209 bptr += n; | |
| 210 | |
| 211 while (bsize > 0 && (n = http_read_line(sock, bptr, bsize)) != -1) { | |
| 212 bptr += n; | |
| 213 bsize -= n; | |
| 214 } | |
| 215 | |
| 216 Done: | |
| 217 http_close_connection(sock); | |
| 218 | |
| 219 /* | |
| 220 * Return result buffer to caller. | |
| 221 */ | |
| 222 return buf; | |
| 223 } |
