aboutsummaryrefslogtreecommitdiff
path: root/src/inputStream_http.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/inputStream_http.c')
-rw-r--r--src/inputStream_http.c1148
1 files changed, 589 insertions, 559 deletions
diff --git a/src/inputStream_http.c b/src/inputStream_http.c
index 3eefdf51..f3f284d5 100644
--- a/src/inputStream_http.c
+++ b/src/inputStream_http.c
@@ -47,173 +47,173 @@
#define HTTP_REDIRECT_MAX 10
-static char * proxyHost = NULL;
-static char * proxyPort = NULL;
-static char * proxyUser = NULL;
-static char * proxyPassword = NULL;
+static char *proxyHost = NULL;
+static char *proxyPort = NULL;
+static char *proxyUser = NULL;
+static char *proxyPassword = NULL;
static int bufferSize = HTTP_BUFFER_SIZE_DEFAULT;
static int prebufferSize = HTTP_PREBUFFER_SIZE_DEFAULT;
typedef struct _InputStreemHTTPData {
- char * host;
- char * path;
+ char *host;
+ char *path;
char *port;
- int sock;
- int connState;
- char * buffer;
- size_t buflen;
- int timesRedirected;
- int icyMetaint;
+ int sock;
+ int connState;
+ char *buffer;
+ size_t buflen;
+ int timesRedirected;
+ int icyMetaint;
int prebuffer;
int icyOffset;
- char * proxyAuth;
- char * httpAuth;
+ char *proxyAuth;
+ char *httpAuth;
} InputStreamHTTPData;
-void inputStream_initHttp(void) {
- ConfigParam * param = getConfigParam(CONF_HTTP_PROXY_HOST);
- char * test;
+void inputStream_initHttp(void)
+{
+ ConfigParam *param = getConfigParam(CONF_HTTP_PROXY_HOST);
+ char *test;
- if(param) {
+ if (param) {
proxyHost = param->value;
param = getConfigParam(CONF_HTTP_PROXY_PORT);
- if(!param) {
+ if (!param) {
ERROR("%s specified but not %s", CONF_HTTP_PROXY_HOST,
- CONF_HTTP_PROXY_PORT);
+ CONF_HTTP_PROXY_PORT);
exit(EXIT_FAILURE);
}
proxyPort = param->value;
param = getConfigParam(CONF_HTTP_PROXY_USER);
- if(param) {
+ if (param) {
proxyUser = param->value;
-
+
param = getConfigParam(CONF_HTTP_PROXY_PASSWORD);
- if(!param) {
+ if (!param) {
ERROR("%s specified but not %s\n",
- CONF_HTTP_PROXY_USER,
- CONF_HTTP_PROXY_PASSWORD);
+ CONF_HTTP_PROXY_USER,
+ CONF_HTTP_PROXY_PASSWORD);
exit(EXIT_FAILURE);
}
- proxyPassword = param->value;
+ proxyPassword = param->value;
}
param = getConfigParam(CONF_HTTP_PROXY_PASSWORD);
- if(param) {
+ if (param) {
ERROR("%s specified but not %s\n",
- CONF_HTTP_PROXY_PASSWORD, CONF_HTTP_PROXY_USER);
+ CONF_HTTP_PROXY_PASSWORD, CONF_HTTP_PROXY_USER);
exit(EXIT_FAILURE);
}
- }
- else if((param = getConfigParam(CONF_HTTP_PROXY_PORT))) {
- ERROR("%s specified but not %s, line %i\n",
- CONF_HTTP_PROXY_PORT, CONF_HTTP_PROXY_HOST,
- param->line);
+ } else if ((param = getConfigParam(CONF_HTTP_PROXY_PORT))) {
+ ERROR("%s specified but not %s, line %i\n",
+ CONF_HTTP_PROXY_PORT, CONF_HTTP_PROXY_HOST, param->line);
exit(EXIT_FAILURE);
- }
- else if((param = getConfigParam(CONF_HTTP_PROXY_USER))) {
- ERROR("%s specified but not %s, line %i\n",
- CONF_HTTP_PROXY_USER, CONF_HTTP_PROXY_HOST,
- param->line);
+ } else if ((param = getConfigParam(CONF_HTTP_PROXY_USER))) {
+ ERROR("%s specified but not %s, line %i\n",
+ CONF_HTTP_PROXY_USER, CONF_HTTP_PROXY_HOST, param->line);
exit(EXIT_FAILURE);
- }
- else if((param = getConfigParam(CONF_HTTP_PROXY_PASSWORD))) {
- ERROR("%s specified but not %s, line %i\n",
- CONF_HTTP_PROXY_PASSWORD, CONF_HTTP_PROXY_HOST,
- param->line);
+ } else if ((param = getConfigParam(CONF_HTTP_PROXY_PASSWORD))) {
+ ERROR("%s specified but not %s, line %i\n",
+ CONF_HTTP_PROXY_PASSWORD, CONF_HTTP_PROXY_HOST,
+ param->line);
exit(EXIT_FAILURE);
}
param = getConfigParam(CONF_HTTP_BUFFER_SIZE);
- if(param) {
+ if (param) {
bufferSize = strtol(param->value, &test, 10);
-
- if(bufferSize <= 0 || *test != '\0') {
+
+ if (bufferSize <= 0 || *test != '\0') {
ERROR("\"%s\" specified for %s at line %i is not a "
- "positive integer\n",
- param->value, CONF_HTTP_BUFFER_SIZE,
- param->line);
+ "positive integer\n",
+ param->value, CONF_HTTP_BUFFER_SIZE, param->line);
exit(EXIT_FAILURE);
}
bufferSize *= 1024;
- if(prebufferSize > bufferSize) prebufferSize = bufferSize;
+ if (prebufferSize > bufferSize)
+ prebufferSize = bufferSize;
}
param = getConfigParam(CONF_HTTP_PREBUFFER_SIZE);
- if(param) {
+ if (param) {
prebufferSize = strtol(param->value, &test, 10);
-
- if(prebufferSize <= 0 || *test != '\0') {
+
+ if (prebufferSize <= 0 || *test != '\0') {
ERROR("\"%s\" specified for %s at line %i is not a "
- "positive integer\n",
- param->value, CONF_HTTP_PREBUFFER_SIZE,
- param->line);
+ "positive integer\n",
+ param->value, CONF_HTTP_PREBUFFER_SIZE,
+ param->line);
exit(EXIT_FAILURE);
}
prebufferSize *= 1024;
}
- if(prebufferSize > bufferSize) prebufferSize = bufferSize;
+ if (prebufferSize > bufferSize)
+ prebufferSize = bufferSize;
}
/* base64 code taken from xmms */
#define BASE64_LENGTH(len) (4 * (((len) + 2) / 3))
-static char * base64Dup(char * s) {
+static char *base64Dup(char *s)
+{
int i;
int len = strlen(s);
- char * ret = calloc(BASE64_LENGTH(len)+1, 1);
- unsigned char * p = (unsigned char *)ret;
+ char *ret = calloc(BASE64_LENGTH(len) + 1, 1);
+ unsigned char *p = (unsigned char *)ret;
char tbl[64] = {
- 'A','B','C','D','E','F','G','H',
- 'I','J','K','L','M','N','O','P',
- 'Q','R','S','T','U','V','W','X',
- 'Y','Z','a','b','c','d','e','f',
- 'g','h','i','j','k','l','m','n',
- 'o','p','q','r','s','t','u','v',
- 'w','x','y','z','0','1','2','3',
- '4','5','6','7','8','9','+','/'
+ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
+ 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
+ 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
+ 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
+ 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
+ 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
+ 'w', 'x', 'y', 'z', '0', '1', '2', '3',
+ '4', '5', '6', '7', '8', '9', '+', '/'
};
/* Transform the 3x8 bits to 4x6 bits, as required by base64. */
- for(i = 0; i < len; i += 3) {
+ for (i = 0; i < len; i += 3) {
*p++ = tbl[s[0] >> 2];
- *p++ = tbl[((s[0] & 3) << 4) + (s[1] >> 4)];
- *p++ = tbl[((s[1] & 0xf) << 2) + (s[2] >> 6)];
- *p++ = tbl[s[2] & 0x3f];
- s += 3;
+ *p++ = tbl[((s[0] & 3) << 4) + (s[1] >> 4)];
+ *p++ = tbl[((s[1] & 0xf) << 2) + (s[2] >> 6)];
+ *p++ = tbl[s[2] & 0x3f];
+ s += 3;
}
/* Pad the result if necessary... */
- if (i == len + 1)
- *(p - 1) = '=';
- else if (i == len + 2)
- *(p - 1) = *(p - 2) = '=';
- /* ...and zero-terminate it. */
- *p = '\0';
+ if (i == len + 1)
+ *(p - 1) = '=';
+ else if (i == len + 2)
+ *(p - 1) = *(p - 2) = '=';
+ /* ...and zero-terminate it. */
+ *p = '\0';
return ret;
}
-static char * authString(char * header, char * user, char * password) {
- char * ret = NULL;
+static char *authString(char *header, char *user, char *password)
+{
+ char *ret = NULL;
int templen;
- char * temp;
- char * temp64;
+ char *temp;
+ char *temp64;
- if(!user || !password) return NULL;
+ if (!user || !password)
+ return NULL;
templen = strlen(user) + strlen(password) + 2;
temp = malloc(templen);
@@ -223,7 +223,7 @@ static char * authString(char * header, char * user, char * password) {
temp64 = base64Dup(temp);
free(temp);
- ret = malloc(strlen(temp64)+strlen(header)+3);
+ ret = malloc(strlen(temp64) + strlen(header) + 3);
strcpy(ret, header);
strcat(ret, temp64);
strcat(ret, "\r\n");
@@ -238,76 +238,84 @@ static char * authString(char * header, char * user, char * password) {
#define proxyAuthString(x, y) authString(PROXY_AUTH_HEADER, x, y)
#define httpAuthString(x, y) authString(HTTP_AUTH_HEADER, x, y)
-static InputStreamHTTPData * newInputStreamHTTPData(void) {
- InputStreamHTTPData * ret = malloc(sizeof(InputStreamHTTPData));
+static InputStreamHTTPData *newInputStreamHTTPData(void)
+{
+ InputStreamHTTPData *ret = malloc(sizeof(InputStreamHTTPData));
- if(proxyHost) {
+ if (proxyHost) {
ret->proxyAuth = proxyAuthString(proxyUser, proxyPassword);
- }
- else ret->proxyAuth = NULL;
+ } else
+ ret->proxyAuth = NULL;
ret->httpAuth = NULL;
ret->host = NULL;
- ret->path = NULL;
+ ret->path = NULL;
ret->port = NULL;
- ret->connState = HTTP_CONN_STATE_CLOSED;
- ret->timesRedirected = 0;
- ret->icyMetaint = 0;
+ ret->connState = HTTP_CONN_STATE_CLOSED;
+ ret->timesRedirected = 0;
+ ret->icyMetaint = 0;
ret->prebuffer = 0;
ret->icyOffset = 0;
ret->buffer = malloc(bufferSize);
- return ret;
+ return ret;
}
-static void freeInputStreamHTTPData(InputStreamHTTPData * data) {
- if(data->host) free(data->host);
- if(data->path) free(data->path);
- if(data->port) free(data->port);
- if(data->proxyAuth) free(data->proxyAuth);
- if(data->httpAuth) free(data->httpAuth);
+static void freeInputStreamHTTPData(InputStreamHTTPData * data)
+{
+ if (data->host)
+ free(data->host);
+ if (data->path)
+ free(data->path);
+ if (data->port)
+ free(data->port);
+ if (data->proxyAuth)
+ free(data->proxyAuth);
+ if (data->httpAuth)
+ free(data->httpAuth);
free(data->buffer);
- free(data);
+ free(data);
}
-static int parseUrl(InputStreamHTTPData * data, char * url) {
- char * temp;
- char * colon;
- char * slash;
- char * at;
- int len;
+static int parseUrl(InputStreamHTTPData * data, char *url)
+{
+ char *temp;
+ char *colon;
+ char *slash;
+ char *at;
+ int len;
- if(strncmp("http://",url,strlen("http://"))!=0) return -1;
+ if (strncmp("http://", url, strlen("http://")) != 0)
+ return -1;
- temp = url+strlen("http://");
+ temp = url + strlen("http://");
- colon = strchr(temp, ':');
+ colon = strchr(temp, ':');
at = strchr(temp, '@');
- if(data->httpAuth) {
+ if (data->httpAuth) {
free(data->httpAuth);
data->httpAuth = NULL;
}
-
- if(at) {
- char * user;
- char * passwd;
- if(colon && colon < at) {
- user = malloc(colon-temp+1);
- strncpy(user, temp, colon-temp);
- user[colon-temp] = '\0';
+ if (at) {
+ char *user;
+ char *passwd;
- passwd = malloc(at-colon);
- strncpy(passwd, colon+1, at-colon-1);
- passwd[at-colon-1] = '\0';
- }
- else {
- user = malloc(at-temp+1);
- strncpy(user, temp, at-temp);
- user[at-temp] = '\0';
+ if (colon && colon < at) {
+ user = malloc(colon - temp + 1);
+ strncpy(user, temp, colon - temp);
+ user[colon - temp] = '\0';
+
+ passwd = malloc(at - colon);
+ strncpy(passwd, colon + 1, at - colon - 1);
+ passwd[at - colon - 1] = '\0';
+ } else {
+ user = malloc(at - temp + 1);
+ strncpy(user, temp, at - temp);
+ user[at - temp] = '\0';
passwd = strdup("");
}
@@ -317,565 +325,587 @@ static int parseUrl(InputStreamHTTPData * data, char * url) {
free(user);
free(passwd);
- temp = at+1;
- colon = strchr(temp, ':');
+ temp = at + 1;
+ colon = strchr(temp, ':');
}
- slash = strchr(temp, '/');
+ slash = strchr(temp, '/');
- if(slash && colon && slash <= colon) return -1;
+ if (slash && colon && slash <= colon)
+ return -1;
- /* fetch the host portion */
- if(colon) len = colon-temp+1;
- else if(slash) len = slash-temp+1;
- else len = strlen(temp)+1;
+ /* fetch the host portion */
+ if (colon)
+ len = colon - temp + 1;
+ else if (slash)
+ len = slash - temp + 1;
+ else
+ len = strlen(temp) + 1;
- if(len<=1) return -1;
+ if (len <= 1)
+ return -1;
- data->host = malloc(len);
- strncpy(data->host,temp,len-1);
- data->host[len-1] = '\0';
- /* fetch the port */
- if(colon && (!slash || slash != colon+1)) {
- len = strlen(colon)-1;
- if(slash) len -= strlen(slash);
- data->port = malloc(len+1);
- strncpy(data->port, colon+1, len);
- data->port[len] = '\0';
+ data->host = malloc(len);
+ strncpy(data->host, temp, len - 1);
+ data->host[len - 1] = '\0';
+ /* fetch the port */
+ if (colon && (!slash || slash != colon + 1)) {
+ len = strlen(colon) - 1;
+ if (slash)
+ len -= strlen(slash);
+ data->port = malloc(len + 1);
+ strncpy(data->port, colon + 1, len);
+ data->port[len] = '\0';
DEBUG(__FILE__ ": Port: %s\n", data->port);
- }
- else {
+ } else {
data->port = strdup("80");
}
-
- /* fetch the path */
- if(proxyHost) data->path = strdup(url);
- else data->path = strdup(slash ? slash : "/");
- return 0;
+ /* fetch the path */
+ if (proxyHost)
+ data->path = strdup(url);
+ else
+ data->path = strdup(slash ? slash : "/");
+
+ return 0;
}
-static int initHTTPConnection(InputStream * inStream) {
+static int initHTTPConnection(InputStream * inStream)
+{
char *connHost;
char *connPort;
struct addrinfo *ans = NULL;
struct addrinfo *ap = NULL;
struct addrinfo hints;
int error, flags;
- InputStreamHTTPData * data = (InputStreamHTTPData *)inStream->data;
+ InputStreamHTTPData *data = (InputStreamHTTPData *) inStream->data;
/**
* Setup hints
*/
- hints.ai_flags = 0;
- hints.ai_family = PF_UNSPEC;
- hints.ai_socktype = SOCK_STREAM;
- hints.ai_protocol = IPPROTO_TCP;
- hints.ai_addrlen = 0;
- hints.ai_addr = NULL;
- hints.ai_canonname = NULL;
- hints.ai_next = NULL;
-
-
-
-
- if(proxyHost) {
+ hints.ai_flags = 0;
+ hints.ai_family = PF_UNSPEC;
+ hints.ai_socktype = SOCK_STREAM;
+ hints.ai_protocol = IPPROTO_TCP;
+ hints.ai_addrlen = 0;
+ hints.ai_addr = NULL;
+ hints.ai_canonname = NULL;
+ hints.ai_next = NULL;
+
+ if (proxyHost) {
connHost = proxyHost;
connPort = proxyPort;
- }
- else {
+ } else {
connHost = data->host;
connPort = data->port;
}
error = getaddrinfo(connHost, connPort, &hints, &ans);
- if(error) {
- DEBUG(__FILE__ ": Error getting address info: %s\n", gai_strerror(error));
+ if (error) {
+ DEBUG(__FILE__ ": Error getting address info: %s\n",
+ gai_strerror(error));
return -1;
}
-
+
/* loop through possible addresses */
- for(ap = ans; ap != NULL; ap = ap->ai_next) {
- if((data->sock = socket(ap->ai_family, ap->ai_socktype,
- ap->ai_protocol)) < 0) {
- DEBUG(__FILE__ ": unable to connect: %s\n", strerror(errno));
+ for (ap = ans; ap != NULL; ap = ap->ai_next) {
+ if ((data->sock = socket(ap->ai_family, ap->ai_socktype,
+ ap->ai_protocol)) < 0) {
+ DEBUG(__FILE__ ": unable to connect: %s\n",
+ strerror(errno));
freeaddrinfo(ans);
return -1;
}
-
+
flags = fcntl(data->sock, F_GETFL, 0);
fcntl(data->sock, F_SETFL, flags | O_NONBLOCK);
-
- if(connect(data->sock, ap->ai_addr, ap->ai_addrlen) >= 0
- || errno == EINPROGRESS
- ) {
+
+ if (connect(data->sock, ap->ai_addr, ap->ai_addrlen) >= 0
+ || errno == EINPROGRESS) {
data->connState = HTTP_CONN_STATE_INIT;
data->buflen = 0;
freeaddrinfo(ans);
- return 0; /* success */
+ return 0; /* success */
}
-
+
/* failed, get the next one */
-
+
DEBUG(__FILE__ ": unable to connect: %s\n", strerror(errno));
- close(data->sock);
- }
+ close(data->sock);
+ }
freeaddrinfo(ans);
- return -1; /* failed */
+ return -1; /* failed */
}
-static int finishHTTPInit(InputStream * inStream) {
- InputStreamHTTPData * data = (InputStreamHTTPData *)inStream->data;
- struct timeval tv;
- fd_set writeSet;
- fd_set errorSet;
- int error;
- socklen_t error_len = sizeof(int);
- int ret;
- char request[2049];
-
- tv.tv_sec = 0;
- tv.tv_usec = 0;
-
- FD_ZERO(&writeSet);
- FD_ZERO(&errorSet);
- FD_SET(data->sock, &writeSet);
- FD_SET(data->sock, &errorSet);
-
- ret = select(data->sock+1, NULL, &writeSet, &errorSet, &tv);
-
- if(ret == 0 || (ret < 0 && errno==EINTR)) return 0;
-
- if(ret < 0) {
- DEBUG(__FILE__ ": problem select'ing: %s\n",strerror(errno));
- close(data->sock);
- data->connState = HTTP_CONN_STATE_CLOSED;
- return -1;
- }
-
- getsockopt(data->sock, SOL_SOCKET, SO_ERROR, &error, &error_len);
- if(error) {
- close(data->sock);
- data->connState = HTTP_CONN_STATE_CLOSED;
- return -1;
- }
-
- memset(request, 0, 2049);
+static int finishHTTPInit(InputStream * inStream)
+{
+ InputStreamHTTPData *data = (InputStreamHTTPData *) inStream->data;
+ struct timeval tv;
+ fd_set writeSet;
+ fd_set errorSet;
+ int error;
+ socklen_t error_len = sizeof(int);
+ int ret;
+ char request[2049];
+
+ tv.tv_sec = 0;
+ tv.tv_usec = 0;
+
+ FD_ZERO(&writeSet);
+ FD_ZERO(&errorSet);
+ FD_SET(data->sock, &writeSet);
+ FD_SET(data->sock, &errorSet);
+
+ ret = select(data->sock + 1, NULL, &writeSet, &errorSet, &tv);
+
+ if (ret == 0 || (ret < 0 && errno == EINTR))
+ return 0;
+
+ if (ret < 0) {
+ DEBUG(__FILE__ ": problem select'ing: %s\n", strerror(errno));
+ close(data->sock);
+ data->connState = HTTP_CONN_STATE_CLOSED;
+ return -1;
+ }
+
+ getsockopt(data->sock, SOL_SOCKET, SO_ERROR, &error, &error_len);
+ if (error) {
+ close(data->sock);
+ data->connState = HTTP_CONN_STATE_CLOSED;
+ return -1;
+ }
+
+ memset(request, 0, 2049);
/* deal with ICY metadata later, for now its fucking up stuff! */
- snprintf(request, 2048, "GET %s HTTP/1.0\r\n"
- "Host: %s\r\n"
- /*"Connection: close\r\n"*/
- "User-Agent: %s/%s\r\n"
- /*"Range: bytes=%ld-\r\n"*/
- "%s" /* authorization */
- "Icy-Metadata:1\r\n"
- "\r\n",
- data->path,
- data->host,
- PACKAGE_NAME,
- PACKAGE_VERSION,
-
- /*inStream->offset,*/
- data->proxyAuth ? data->proxyAuth :
- (data->httpAuth ? data->httpAuth : "")
- );
-
- ret = write(data->sock, request, strlen(request));
- if(ret!=strlen(request)) {
- close(data->sock);
- data->connState = HTTP_CONN_STATE_CLOSED;
- return -1;
- }
-
- data->connState = HTTP_CONN_STATE_HELLO;
-
- return 0;
+ snprintf(request, 2048, "GET %s HTTP/1.0\r\n" "Host: %s\r\n"
+ /*"Connection: close\r\n" */
+ "User-Agent: %s/%s\r\n"
+ /*"Range: bytes=%ld-\r\n" */
+ "%s" /* authorization */
+ "Icy-Metadata:1\r\n"
+ "\r\n", data->path, data->host, PACKAGE_NAME, PACKAGE_VERSION,
+ /*inStream->offset, */
+ data->proxyAuth ? data->proxyAuth :
+ (data->httpAuth ? data->httpAuth : "")
+ );
+
+ ret = write(data->sock, request, strlen(request));
+ if (ret != strlen(request)) {
+ close(data->sock);
+ data->connState = HTTP_CONN_STATE_CLOSED;
+ return -1;
+ }
+
+ data->connState = HTTP_CONN_STATE_HELLO;
+
+ return 0;
}
-static int getHTTPHello(InputStream * inStream) {
- InputStreamHTTPData * data = (InputStreamHTTPData *)inStream->data;
- fd_set readSet;
- struct timeval tv;
- int ret;
- char * needle;
- char * cur = data->buffer;
- int rc;
- long readed;
-
- FD_ZERO(&readSet);
- FD_SET(data->sock, &readSet);
-
- tv.tv_sec = 0;
- tv.tv_usec = 0;
-
- ret = select(data->sock+1,&readSet,NULL,NULL,&tv);
-
- if(ret == 0 || (ret < 0 && errno==EINTR)) return 0;
-
- if(ret < 0) {
- data->connState = HTTP_CONN_STATE_CLOSED;
- close(data->sock);
- data->buflen = 0;
- return -1;
- }
-
- if(data->buflen >= bufferSize-1) {
- data->connState = HTTP_CONN_STATE_CLOSED;
- close(data->sock);
- return -1;
- }
-
- readed = recv(data->sock, data->buffer+data->buflen,
- bufferSize-1-data->buflen, 0);
-
- if(readed < 0 && (errno == EAGAIN || errno == EINTR)) return 0;
-
- if(readed <= 0) {
- data->connState = HTTP_CONN_STATE_CLOSED;
- close(data->sock);
- data->buflen = 0;
- return -1;
- }
-
- data->buffer[data->buflen+readed] = '\0';
- data->buflen += readed;
-
- needle = strstr(data->buffer,"\r\n\r\n");
-
- if(!needle) return 0;
-
- if(0 == strncmp(cur, "HTTP/1.0 ", 9)) {
- inStream->seekable = 0;
- rc = atoi(cur+9);
- }
- else if(0 == strncmp(cur, "HTTP/1.1 ", 9)) {
- inStream->seekable = 1;
- rc = atoi(cur+9);
- }
- else if(0 == strncmp(cur, "ICY 200 OK", 10)) {
- inStream->seekable = 0;
- rc = 200;
- }
- else if(0 == strncmp(cur, "ICY 400 Server Full", 19)) rc = 400;
- else if(0 == strncmp(cur, "ICY 404", 7)) rc = 404;
- else {
- close(data->sock);
- data->connState = HTTP_CONN_STATE_CLOSED;
- return -1;
- }
-
- switch(rc) {
- case 200:
- case 206:
- break;
- case 301:
- case 302:
- cur = strstr(cur, "Location: ");
- if(cur) {
- char * url;
- int curlen = 0;
- cur+= strlen("Location: ");
- while(*(cur+curlen)!='\0' && *(cur+curlen)!='\r') {
- curlen++;
- }
- url = malloc(curlen+1);
- memcpy(url,cur,curlen);
- url[curlen] = '\0';
- ret = parseUrl(data,url);
- free(url);
- if(ret == 0 && data->timesRedirected <
- HTTP_REDIRECT_MAX)
- {
- data->timesRedirected++;
- close(data->sock);
- data->connState = HTTP_CONN_STATE_REOPEN;
- data->buflen = 0;
- return 0;
- }
- }
- case 400:
- case 401:
+static int getHTTPHello(InputStream * inStream)
+{
+ InputStreamHTTPData *data = (InputStreamHTTPData *) inStream->data;
+ fd_set readSet;
+ struct timeval tv;
+ int ret;
+ char *needle;
+ char *cur = data->buffer;
+ int rc;
+ long readed;
+
+ FD_ZERO(&readSet);
+ FD_SET(data->sock, &readSet);
+
+ tv.tv_sec = 0;
+ tv.tv_usec = 0;
+
+ ret = select(data->sock + 1, &readSet, NULL, NULL, &tv);
+
+ if (ret == 0 || (ret < 0 && errno == EINTR))
+ return 0;
+
+ if (ret < 0) {
+ data->connState = HTTP_CONN_STATE_CLOSED;
+ close(data->sock);
+ data->buflen = 0;
+ return -1;
+ }
+
+ if (data->buflen >= bufferSize - 1) {
+ data->connState = HTTP_CONN_STATE_CLOSED;
+ close(data->sock);
+ return -1;
+ }
+
+ readed = recv(data->sock, data->buffer + data->buflen,
+ bufferSize - 1 - data->buflen, 0);
+
+ if (readed < 0 && (errno == EAGAIN || errno == EINTR))
+ return 0;
+
+ if (readed <= 0) {
+ data->connState = HTTP_CONN_STATE_CLOSED;
+ close(data->sock);
+ data->buflen = 0;
+ return -1;
+ }
+
+ data->buffer[data->buflen + readed] = '\0';
+ data->buflen += readed;
+
+ needle = strstr(data->buffer, "\r\n\r\n");
+
+ if (!needle)
+ return 0;
+
+ if (0 == strncmp(cur, "HTTP/1.0 ", 9)) {
+ inStream->seekable = 0;
+ rc = atoi(cur + 9);
+ } else if (0 == strncmp(cur, "HTTP/1.1 ", 9)) {
+ inStream->seekable = 1;
+ rc = atoi(cur + 9);
+ } else if (0 == strncmp(cur, "ICY 200 OK", 10)) {
+ inStream->seekable = 0;
+ rc = 200;
+ } else if (0 == strncmp(cur, "ICY 400 Server Full", 19))
+ rc = 400;
+ else if (0 == strncmp(cur, "ICY 404", 7))
+ rc = 404;
+ else {
+ close(data->sock);
+ data->connState = HTTP_CONN_STATE_CLOSED;
+ return -1;
+ }
+
+ switch (rc) {
+ case 200:
+ case 206:
+ break;
+ case 301:
+ case 302:
+ cur = strstr(cur, "Location: ");
+ if (cur) {
+ char *url;
+ int curlen = 0;
+ cur += strlen("Location: ");
+ while (*(cur + curlen) != '\0'
+ && *(cur + curlen) != '\r') {
+ curlen++;
+ }
+ url = malloc(curlen + 1);
+ memcpy(url, cur, curlen);
+ url[curlen] = '\0';
+ ret = parseUrl(data, url);
+ free(url);
+ if (ret == 0 && data->timesRedirected <
+ HTTP_REDIRECT_MAX) {
+ data->timesRedirected++;
+ close(data->sock);
+ data->connState = HTTP_CONN_STATE_REOPEN;
+ data->buflen = 0;
+ return 0;
+ }
+ }
+ case 400:
+ case 401:
case 403:
- case 404:
- default:
- close(data->sock);
- data->connState = HTTP_CONN_STATE_CLOSED;
- data->buflen = 0;
- return -1;
- }
-
- cur = strstr(data->buffer,"\r\n");
- while(cur && cur!=needle) {
- if(0 == strncmp(cur,"\r\nContent-Length: ",18)) {
- if(!inStream->size) inStream->size = atol(cur+18);
- }
- else if(0 == strncmp(cur, "\r\nicy-metaint:", 14)) {
- data->icyMetaint = atoi(cur+14);
- }
- else if(0 == strncmp(cur, "\r\nicy-name:", 11) ||
- 0 == strncmp(cur, "\r\nice-name:", 11))
- {
- int incr = 11;
- char * temp = strstr(cur+incr,"\r\n");
- if(!temp) break;
- *temp = '\0';
- if(inStream->metaName) free(inStream->metaName);
- while(*(incr+cur) == ' ') incr++;
- inStream->metaName = strdup(cur+incr);
- *temp = '\r';
- DEBUG("inputStream_http: metaName: %s\n",
- inStream->metaName);
- }
- else if(0 == strncmp(cur, "\r\nx-audiocast-name:", 19)) {
- int incr = 19;
- char * temp = strstr(cur+incr,"\r\n");
- if(!temp) break;
- *temp = '\0';
- if(inStream->metaName) free(inStream->metaName);
- while(*(incr+cur) == ' ') incr++;
- inStream->metaName = strdup(cur+incr);
- *temp = '\r';
- DEBUG("inputStream_http: metaName: %s\n",
- inStream->metaName);
- }
- else if(0 == strncmp(cur, "\r\nContent-Type:", 15)) {
- int incr = 15;
- char * temp = strstr(cur+incr,"\r\n");
- if(!temp) break;
- *temp = '\0';
- if(inStream->mime) free(inStream->mime);
- while(*(incr+cur) == ' ') incr++;
- inStream->mime = strdup(cur+incr);
- *temp = '\r';
- }
-
- cur = strstr(cur+2,"\r\n");
- }
-
- if(inStream->size <= 0) inStream->seekable = 0;
-
- needle += 4; /* 4 == strlen("\r\n\r\n") */
- data->buflen -= (needle-data->buffer);
- /*fwrite(data->buffer, 1, data->buflen, stdout);*/
- memmove(data->buffer, needle, data->buflen);
-
- data->connState = HTTP_CONN_STATE_OPEN;
+ case 404:
+ default:
+ close(data->sock);
+ data->connState = HTTP_CONN_STATE_CLOSED;
+ data->buflen = 0;
+ return -1;
+ }
+
+ cur = strstr(data->buffer, "\r\n");
+ while (cur && cur != needle) {
+ if (0 == strncmp(cur, "\r\nContent-Length: ", 18)) {
+ if (!inStream->size)
+ inStream->size = atol(cur + 18);
+ } else if (0 == strncmp(cur, "\r\nicy-metaint:", 14)) {
+ data->icyMetaint = atoi(cur + 14);
+ } else if (0 == strncmp(cur, "\r\nicy-name:", 11) ||
+ 0 == strncmp(cur, "\r\nice-name:", 11)) {
+ int incr = 11;
+ char *temp = strstr(cur + incr, "\r\n");
+ if (!temp)
+ break;
+ *temp = '\0';
+ if (inStream->metaName)
+ free(inStream->metaName);
+ while (*(incr + cur) == ' ')
+ incr++;
+ inStream->metaName = strdup(cur + incr);
+ *temp = '\r';
+ DEBUG("inputStream_http: metaName: %s\n",
+ inStream->metaName);
+ } else if (0 == strncmp(cur, "\r\nx-audiocast-name:", 19)) {
+ int incr = 19;
+ char *temp = strstr(cur + incr, "\r\n");
+ if (!temp)
+ break;
+ *temp = '\0';
+ if (inStream->metaName)
+ free(inStream->metaName);
+ while (*(incr + cur) == ' ')
+ incr++;
+ inStream->metaName = strdup(cur + incr);
+ *temp = '\r';
+ DEBUG("inputStream_http: metaName: %s\n",
+ inStream->metaName);
+ } else if (0 == strncmp(cur, "\r\nContent-Type:", 15)) {
+ int incr = 15;
+ char *temp = strstr(cur + incr, "\r\n");
+ if (!temp)
+ break;
+ *temp = '\0';
+ if (inStream->mime)
+ free(inStream->mime);
+ while (*(incr + cur) == ' ')
+ incr++;
+ inStream->mime = strdup(cur + incr);
+ *temp = '\r';
+ }
+
+ cur = strstr(cur + 2, "\r\n");
+ }
+
+ if (inStream->size <= 0)
+ inStream->seekable = 0;
+
+ needle += 4; /* 4 == strlen("\r\n\r\n") */
+ data->buflen -= (needle - data->buffer);
+ /*fwrite(data->buffer, 1, data->buflen, stdout); */
+ memmove(data->buffer, needle, data->buflen);
+
+ data->connState = HTTP_CONN_STATE_OPEN;
data->prebuffer = 1;
- /*mark as unseekable till we actually implement seeking*/
+ /*mark as unseekable till we actually implement seeking */
inStream->seekable = 0;
- return 0;
+ return 0;
}
-int inputStream_httpOpen(InputStream * inStream, char * url) {
- InputStreamHTTPData * data = newInputStreamHTTPData();
+int inputStream_httpOpen(InputStream * inStream, char *url)
+{
+ InputStreamHTTPData *data = newInputStreamHTTPData();
- inStream->data = data;
+ inStream->data = data;
- if(parseUrl(data,url) < 0) {
- freeInputStreamHTTPData(data);
- return -1;
- }
+ if (parseUrl(data, url) < 0) {
+ freeInputStreamHTTPData(data);
+ return -1;
+ }
- if(initHTTPConnection(inStream) < 0) {
- freeInputStreamHTTPData(data);
- return -1;
- }
+ if (initHTTPConnection(inStream) < 0) {
+ freeInputStreamHTTPData(data);
+ return -1;
+ }
- inStream->seekFunc = inputStream_httpSeek;
- inStream->closeFunc = inputStream_httpClose;
- inStream->readFunc = inputStream_httpRead;
- inStream->atEOFFunc = inputStream_httpAtEOF;
- inStream->bufferFunc = inputStream_httpBuffer;
+ inStream->seekFunc = inputStream_httpSeek;
+ inStream->closeFunc = inputStream_httpClose;
+ inStream->readFunc = inputStream_httpRead;
+ inStream->atEOFFunc = inputStream_httpAtEOF;
+ inStream->bufferFunc = inputStream_httpBuffer;
return 0;
}
-int inputStream_httpSeek(InputStream * inStream, long offset, int whence) {
+int inputStream_httpSeek(InputStream * inStream, long offset, int whence)
+{
/* hack to reopen an HTTP stream if we're trying to seek to
* the beginning */
if ((whence == SEEK_SET) && (offset == 0)) {
- InputStreamHTTPData * data;
+ InputStreamHTTPData *data;
- data = (InputStreamHTTPData*)inStream->data;
+ data = (InputStreamHTTPData *) inStream->data;
close(data->sock);
data->connState = HTTP_CONN_STATE_REOPEN;
data->buflen = 0;
inStream->offset = 0;
return 0;
}
-
+
/* otherwise, we don't know how to seek in HTTP yet */
return -1;
}
-static void parseIcyMetadata(InputStream * inStream, char * metadata,
- int size)
+static void parseIcyMetadata(InputStream * inStream, char *metadata, int size)
{
- char * r;
- char * s;
- char * temp = malloc(size+1);
+ char *r;
+ char *s;
+ char *temp = malloc(size + 1);
memcpy(temp, metadata, size);
temp[size] = '\0';
s = strtok_r(temp, ";", &r);
- while(s) {
- if(0 == strncmp(s, "StreamTitle=", 12)) {
+ while (s) {
+ if (0 == strncmp(s, "StreamTitle=", 12)) {
int cur = 12;
- if(inStream->metaTitle) free(inStream->metaTitle);
- if(*(s+cur) == '\'') cur++;
- if(s[strlen(s)-1] == '\'') {
- s[strlen(s)-1] = '\0';
+ if (inStream->metaTitle)
+ free(inStream->metaTitle);
+ if (*(s + cur) == '\'')
+ cur++;
+ if (s[strlen(s) - 1] == '\'') {
+ s[strlen(s) - 1] = '\0';
}
- inStream->metaTitle = strdup(s+cur);
- DEBUG("inputStream_http: metaTitle: %s\n",
- inStream->metaTitle);
+ inStream->metaTitle = strdup(s + cur);
+ DEBUG("inputStream_http: metaTitle: %s\n",
+ inStream->metaTitle);
}
s = strtok_r(NULL, ";", &r);
}
free(temp);
}
-size_t inputStream_httpRead(InputStream * inStream, void * ptr, size_t size,
- size_t nmemb)
+size_t inputStream_httpRead(InputStream * inStream, void *ptr, size_t size,
+ size_t nmemb)
{
- InputStreamHTTPData * data = (InputStreamHTTPData *)inStream->data;
- long tosend = 0;
- long inlen = size*nmemb;
+ InputStreamHTTPData *data = (InputStreamHTTPData *) inStream->data;
+ long tosend = 0;
+ long inlen = size * nmemb;
long maxToSend = data->buflen;
- inputStream_httpBuffer(inStream);
+ inputStream_httpBuffer(inStream);
- switch(data->connState) {
- case HTTP_CONN_STATE_OPEN:
- if(data->prebuffer || data->buflen < data->icyMetaint) return 0;
+ switch (data->connState) {
+ case HTTP_CONN_STATE_OPEN:
+ if (data->prebuffer || data->buflen < data->icyMetaint)
+ return 0;
break;
- case HTTP_CONN_STATE_CLOSED:
- if(data->buflen) break;
- default:
- return 0;
- }
-
- if(data->icyMetaint > 0) {
- if(data->icyOffset >= data->icyMetaint) {
+ case HTTP_CONN_STATE_CLOSED:
+ if (data->buflen)
+ break;
+ default:
+ return 0;
+ }
+
+ if (data->icyMetaint > 0) {
+ if (data->icyOffset >= data->icyMetaint) {
int metalen = *(data->buffer);
metalen <<= 4;
- if(metalen < 0) metalen = 0;
- if(metalen+1 > data->buflen) {
+ if (metalen < 0)
+ metalen = 0;
+ if (metalen + 1 > data->buflen) {
/* damn that's some fucking big metadata! */
- if(bufferSize < metalen+1) {
- data->connState =
- HTTP_CONN_STATE_CLOSED;
- close(data->sock);
+ if (bufferSize < metalen + 1) {
+ data->connState =
+ HTTP_CONN_STATE_CLOSED;
+ close(data->sock);
data->buflen = 0;
}
return 0;
}
- if(metalen > 0) {
- parseIcyMetadata(inStream, data->buffer+1,
- metalen);
+ if (metalen > 0) {
+ parseIcyMetadata(inStream, data->buffer + 1,
+ metalen);
}
- data->buflen -= metalen+1;
- memmove(data->buffer, data->buffer+metalen+1,
- data->buflen);
+ data->buflen -= metalen + 1;
+ memmove(data->buffer, data->buffer + metalen + 1,
+ data->buflen);
data->icyOffset = 0;
}
- maxToSend = data->icyMetaint-data->icyOffset;
+ maxToSend = data->icyMetaint - data->icyOffset;
maxToSend = maxToSend > data->buflen ? data->buflen : maxToSend;
}
- if(data->buflen > 0) {
- tosend = inlen > maxToSend ? maxToSend : inlen;
- tosend = (tosend/size)*size;
-
- memcpy(ptr, data->buffer, tosend);
- /*fwrite(ptr,1,readed,stdout);*/
- data->buflen -= tosend;
- data->icyOffset+= tosend;
- /*fwrite(data->buffer,1,readed,stdout);*/
- memmove(data->buffer, data->buffer+tosend, data->buflen);
+ if (data->buflen > 0) {
+ tosend = inlen > maxToSend ? maxToSend : inlen;
+ tosend = (tosend / size) * size;
- inStream->offset += tosend;
- }
+ memcpy(ptr, data->buffer, tosend);
+ /*fwrite(ptr,1,readed,stdout); */
+ data->buflen -= tosend;
+ data->icyOffset += tosend;
+ /*fwrite(data->buffer,1,readed,stdout); */
+ memmove(data->buffer, data->buffer + tosend, data->buflen);
+
+ inStream->offset += tosend;
+ }
- return tosend/size;
+ return tosend / size;
}
-int inputStream_httpClose(InputStream * inStream) {
- InputStreamHTTPData * data = (InputStreamHTTPData *)inStream->data;
+int inputStream_httpClose(InputStream * inStream)
+{
+ InputStreamHTTPData *data = (InputStreamHTTPData *) inStream->data;
- switch(data->connState) {
- case HTTP_CONN_STATE_CLOSED:
- break;
- default:
- close(data->sock);
- }
+ switch (data->connState) {
+ case HTTP_CONN_STATE_CLOSED:
+ break;
+ default:
+ close(data->sock);
+ }
- freeInputStreamHTTPData(data);
+ freeInputStreamHTTPData(data);
- return 0;
+ return 0;
}
-int inputStream_httpAtEOF(InputStream * inStream) {
- InputStreamHTTPData * data = (InputStreamHTTPData *)inStream->data;
- switch(data->connState) {
- case HTTP_CONN_STATE_CLOSED:
- if(data->buflen == 0) return 1;
- default:
- return 0;
- }
+int inputStream_httpAtEOF(InputStream * inStream)
+{
+ InputStreamHTTPData *data = (InputStreamHTTPData *) inStream->data;
+ switch (data->connState) {
+ case HTTP_CONN_STATE_CLOSED:
+ if (data->buflen == 0)
+ return 1;
+ default:
+ return 0;
+ }
}
-int inputStream_httpBuffer(InputStream * inStream) {
- InputStreamHTTPData * data = (InputStreamHTTPData *)inStream->data;
- ssize_t readed = 0;
+int inputStream_httpBuffer(InputStream * inStream)
+{
+ InputStreamHTTPData *data = (InputStreamHTTPData *) inStream->data;
+ ssize_t readed = 0;
- if(data->connState == HTTP_CONN_STATE_REOPEN) {
- if(initHTTPConnection(inStream) < 0) return -1;
- }
+ if (data->connState == HTTP_CONN_STATE_REOPEN) {
+ if (initHTTPConnection(inStream) < 0)
+ return -1;
+ }
- if(data->connState == HTTP_CONN_STATE_INIT) {
- if(finishHTTPInit(inStream) < 0) return -1;
- }
+ if (data->connState == HTTP_CONN_STATE_INIT) {
+ if (finishHTTPInit(inStream) < 0)
+ return -1;
+ }
- if(data->connState == HTTP_CONN_STATE_HELLO) {
- if(getHTTPHello(inStream) < 0) return -1;
- }
+ if (data->connState == HTTP_CONN_STATE_HELLO) {
+ if (getHTTPHello(inStream) < 0)
+ return -1;
+ }
- switch(data->connState) {
- case HTTP_CONN_STATE_OPEN:
- case HTTP_CONN_STATE_CLOSED:
- break;
- default:
- return -1;
- }
+ switch (data->connState) {
+ case HTTP_CONN_STATE_OPEN:
+ case HTTP_CONN_STATE_CLOSED:
+ break;
+ default:
+ return -1;
+ }
- if(data->buflen == 0 || data->buflen < data->icyMetaint) {
+ if (data->buflen == 0 || data->buflen < data->icyMetaint) {
data->prebuffer = 1;
- }
- else if(data->buflen > prebufferSize) data->prebuffer = 0;
-
- if(data->connState == HTTP_CONN_STATE_OPEN &&
- data->buflen < bufferSize-1)
- {
- readed = read(data->sock, data->buffer+data->buflen,
- (size_t)(bufferSize-1-data->buflen));
-
- if(readed < 0 && (errno == EAGAIN || errno == EINTR)) {
- readed = 0;
- }
- else if(readed <= 0) {
- close(data->sock);
- data->connState = HTTP_CONN_STATE_CLOSED;
- readed = 0;
- }
- /*fwrite(data->buffer+data->buflen,1,readed,stdout);*/
+ } else if (data->buflen > prebufferSize)
+ data->prebuffer = 0;
+
+ if (data->connState == HTTP_CONN_STATE_OPEN &&
+ data->buflen < bufferSize - 1) {
+ readed = read(data->sock, data->buffer + data->buflen,
+ (size_t) (bufferSize - 1 - data->buflen));
+
+ if (readed < 0 && (errno == EAGAIN || errno == EINTR)) {
+ readed = 0;
+ } else if (readed <= 0) {
+ close(data->sock);
+ data->connState = HTTP_CONN_STATE_CLOSED;
+ readed = 0;
+ }
+ /*fwrite(data->buffer+data->buflen,1,readed,stdout); */
data->buflen += readed;
- }
+ }
- if(data->buflen > prebufferSize) data->prebuffer = 0;
+ if (data->buflen > prebufferSize)
+ data->prebuffer = 0;
- return (readed ? 1 : 0);
+ return (readed ? 1 : 0);
}