aboutsummaryrefslogtreecommitdiffstats
path: root/trunk/src/inputStream_http.c
diff options
context:
space:
mode:
Diffstat (limited to 'trunk/src/inputStream_http.c')
-rw-r--r--trunk/src/inputStream_http.c912
1 files changed, 0 insertions, 912 deletions
diff --git a/trunk/src/inputStream_http.c b/trunk/src/inputStream_http.c
deleted file mode 100644
index 3f18575dd..000000000
--- a/trunk/src/inputStream_http.c
+++ /dev/null
@@ -1,912 +0,0 @@
-/* the Music Player Daemon (MPD)
- * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com)
- * This project's homepage is: http://www.musicpd.org
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include "inputStream_http.h"
-
-#include "utils.h"
-#include "log.h"
-#include "conf.h"
-
-#include <stdio.h>
-#include <sys/time.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netdb.h>
-#include <sys/param.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <unistd.h>
-#include <errno.h>
-#include <stdlib.h>
-#include <string.h>
-#include <fcntl.h>
-
-#define HTTP_CONN_STATE_CLOSED 0
-#define HTTP_CONN_STATE_INIT 1
-#define HTTP_CONN_STATE_HELLO 2
-#define HTTP_CONN_STATE_OPEN 3
-#define HTTP_CONN_STATE_REOPEN 4
-
-#define HTTP_BUFFER_SIZE_DEFAULT 131072
-#define HTTP_PREBUFFER_SIZE_DEFAULT (HTTP_BUFFER_SIZE_DEFAULT >> 2)
-
-#define HTTP_REDIRECT_MAX 10
-
-static char *proxyHost;
-static char *proxyPort;
-static char *proxyUser;
-static char *proxyPassword;
-static int bufferSize = HTTP_BUFFER_SIZE_DEFAULT;
-static int prebufferSize = HTTP_PREBUFFER_SIZE_DEFAULT;
-
-typedef struct _InputStreemHTTPData {
- char *host;
- char *path;
- char *port;
- int sock;
- int connState;
- char *buffer;
- size_t buflen;
- int timesRedirected;
- int icyMetaint;
- int prebuffer;
- int icyOffset;
- char *proxyAuth;
- char *httpAuth;
-} InputStreamHTTPData;
-
-void inputStream_initHttp(void)
-{
- ConfigParam *param = getConfigParam(CONF_HTTP_PROXY_HOST);
- char *test;
-
- if (param) {
- proxyHost = param->value;
-
- param = getConfigParam(CONF_HTTP_PROXY_PORT);
-
- if (!param) {
- FATAL("%s specified but not %s", CONF_HTTP_PROXY_HOST,
- CONF_HTTP_PROXY_PORT);
- }
- proxyPort = param->value;
-
- param = getConfigParam(CONF_HTTP_PROXY_USER);
-
- if (param) {
- proxyUser = param->value;
-
- param = getConfigParam(CONF_HTTP_PROXY_PASSWORD);
-
- if (!param) {
- FATAL("%s specified but not %s\n",
- CONF_HTTP_PROXY_USER,
- CONF_HTTP_PROXY_PASSWORD);
- }
-
- proxyPassword = param->value;
- } else {
- param = getConfigParam(CONF_HTTP_PROXY_PASSWORD);
-
- if (param) {
- FATAL("%s specified but not %s\n",
- CONF_HTTP_PROXY_PASSWORD, CONF_HTTP_PROXY_USER);
- }
- }
- } else if ((param = getConfigParam(CONF_HTTP_PROXY_PORT))) {
- FATAL("%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_USER))) {
- FATAL("%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_PASSWORD))) {
- FATAL("%s specified but not %s, line %i\n",
- CONF_HTTP_PROXY_PASSWORD, CONF_HTTP_PROXY_HOST,
- param->line);
- }
-
- param = getConfigParam(CONF_HTTP_BUFFER_SIZE);
-
- if (param) {
- bufferSize = strtol(param->value, &test, 10);
-
- if (bufferSize <= 0 || *test != '\0') {
- FATAL("\"%s\" specified for %s at line %i is not a "
- "positive integer\n",
- param->value, CONF_HTTP_BUFFER_SIZE, param->line);
- }
-
- bufferSize *= 1024;
-
- if (prebufferSize > bufferSize)
- prebufferSize = bufferSize;
- }
-
- param = getConfigParam(CONF_HTTP_PREBUFFER_SIZE);
-
- if (param) {
- prebufferSize = strtol(param->value, &test, 10);
-
- if (prebufferSize <= 0 || *test != '\0') {
- FATAL("\"%s\" specified for %s at line %i is not a "
- "positive integer\n",
- param->value, CONF_HTTP_PREBUFFER_SIZE,
- param->line);
- }
-
- prebufferSize *= 1024;
- }
-
- if (prebufferSize > bufferSize)
- prebufferSize = bufferSize;
-}
-
-/* base64 code taken from xmms */
-
-#define BASE64_LENGTH(len) (4 * (((len) + 2) / 3))
-
-static char *base64Dup(char *s)
-{
- int i;
- int len = strlen(s);
- char *ret = xcalloc(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', '+', '/'
- };
-
- /* Transform the 3x8 bits to 4x6 bits, as required by base64. */
- 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;
- }
- /* 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';
-
- return ret;
-}
-
-static char *authString(char *header, char *user, char *password)
-{
- char *ret = NULL;
- int templen;
- char *temp;
- char *temp64;
-
- if (!user || !password)
- return NULL;
-
- templen = strlen(user) + strlen(password) + 2;
- temp = xmalloc(templen);
- strcpy(temp, user);
- strcat(temp, ":");
- strcat(temp, password);
- temp64 = base64Dup(temp);
- free(temp);
-
- ret = xmalloc(strlen(temp64) + strlen(header) + 3);
- strcpy(ret, header);
- strcat(ret, temp64);
- strcat(ret, "\r\n");
- free(temp64);
-
- return ret;
-}
-
-#define PROXY_AUTH_HEADER "Proxy-Authorization: Basic "
-#define HTTP_AUTH_HEADER "Authorization: Basic "
-
-#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 = xmalloc(sizeof(InputStreamHTTPData));
-
- if (proxyHost) {
- ret->proxyAuth = proxyAuthString(proxyUser, proxyPassword);
- } else
- ret->proxyAuth = NULL;
-
- ret->httpAuth = NULL;
- ret->host = NULL;
- ret->path = NULL;
- ret->port = NULL;
- ret->connState = HTTP_CONN_STATE_CLOSED;
- ret->timesRedirected = 0;
- ret->icyMetaint = 0;
- ret->prebuffer = 0;
- ret->icyOffset = 0;
- ret->buffer = xmalloc(bufferSize);
-
- 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);
-
- free(data->buffer);
-
- free(data);
-}
-
-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;
-
- temp = url + strlen("http://");
-
- colon = strchr(temp, ':');
- at = strchr(temp, '@');
-
- if (data->httpAuth) {
- free(data->httpAuth);
- data->httpAuth = NULL;
- }
-
- if (at) {
- char *user;
- char *passwd;
-
- if (colon && colon < at) {
- user = xmalloc(colon - temp + 1);
- memcpy(user, temp, colon - temp);
- user[colon - temp] = '\0';
-
- passwd = xmalloc(at - colon);
- memcpy(passwd, colon + 1, at - colon - 1);
- passwd[at - colon - 1] = '\0';
- } else {
- user = xmalloc(at - temp + 1);
- memcpy(user, temp, at - temp);
- user[at - temp] = '\0';
-
- passwd = xstrdup("");
- }
-
- data->httpAuth = httpAuthString(user, passwd);
-
- free(user);
- free(passwd);
-
- temp = at + 1;
- colon = strchr(temp, ':');
- }
-
- slash = strchr(temp, '/');
-
- 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;
-
- if (len <= 1)
- return -1;
-
- data->host = xmalloc(len);
- memcpy(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 = xmalloc(len + 1);
- memcpy(data->port, colon + 1, len);
- data->port[len] = '\0';
- DEBUG(__FILE__ ": Port: %s\n", data->port);
- } else {
- data->port = xstrdup("80");
- }
-
- /* fetch the path */
- if (proxyHost)
- data->path = xstrdup(url);
- else
- data->path = xstrdup(slash ? slash : "/");
-
- return 0;
-}
-
-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;
- /**
- * 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) {
- connHost = proxyHost;
- connPort = proxyPort;
- } 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));
- 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));
- 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) {
- data->connState = HTTP_CONN_STATE_INIT;
- data->buflen = 0;
- freeaddrinfo(ans);
- return 0; /* success */
- }
-
- /* failed, get the next one */
-
- DEBUG(__FILE__ ": unable to connect: %s\n", strerror(errno));
- close(data->sock);
- }
-
- freeaddrinfo(ans);
- 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;
- int length;
- char request[2048];
-
- 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));
- goto close_err;
- }
-
- getsockopt(data->sock, SOL_SOCKET, SO_ERROR, &error, &error_len);
- if (error)
- goto close_err;
-
- /* deal with ICY metadata later, for now its fucking up stuff! */
- length = snprintf(request, sizeof(request),
- "GET %s HTTP/1.1\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 : ""));
-
- if (length >= sizeof(request))
- goto close_err;
- ret = write(data->sock, request, length);
- if (ret != length)
- goto close_err;
-
- data->connState = HTTP_CONN_STATE_HELLO;
- return 0;
-
-close_err:
- close(data->sock);
- data->connState = HTTP_CONN_STATE_CLOSED;
- return -1;
-}
-
-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 = xmalloc(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 = xstrdup(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 = xstrdup(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 = xstrdup(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;
-
- return 0;
-}
-
-int inputStream_httpOpen(InputStream * inStream, char *url)
-{
- InputStreamHTTPData *data = newInputStreamHTTPData();
-
- inStream->data = data;
-
- if (parseUrl(data, url) < 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;
-
- return 0;
-}
-
-int inputStream_httpSeek(InputStream * inStream, long offset, int whence)
-{
- InputStreamHTTPData *data;
-
- if (!inStream->seekable)
- return -1;
-
- switch (whence) {
- case SEEK_SET:
- inStream->offset = offset;
- break;
- case SEEK_CUR:
- inStream->offset += offset;
- break;
- case SEEK_END:
- inStream->offset = inStream->size + offset;
- break;
- default:
- return -1;
- }
-
- data = (InputStreamHTTPData *)inStream->data;
- close(data->sock);
- data->connState = HTTP_CONN_STATE_REOPEN;
- data->buflen = 0;
-
- inputStream_httpBuffer(inStream);
-
- return 0;
-}
-
-static void parseIcyMetadata(InputStream * inStream, char *metadata, int size)
-{
- char *r;
- char *s;
- char *temp = xmalloc(size + 1);
- memcpy(temp, metadata, size);
- temp[size] = '\0';
- s = strtok_r(temp, ";", &r);
- 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';
- }
- inStream->metaTitle = xstrdup(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)
-{
- InputStreamHTTPData *data = (InputStreamHTTPData *) inStream->data;
- long tosend = 0;
- long inlen = size * nmemb;
- long maxToSend = data->buflen;
-
- inputStream_httpBuffer(inStream);
-
- 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) {
- int metalen = *(data->buffer);
- metalen <<= 4;
- 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);
- data->buflen = 0;
- }
- return 0;
- }
- if (metalen > 0) {
- parseIcyMetadata(inStream, data->buffer + 1,
- metalen);
- }
- data->buflen -= metalen + 1;
- memmove(data->buffer, data->buffer + metalen + 1,
- data->buflen);
- data->icyOffset = 0;
- }
- 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);
-
- inStream->offset += tosend;
- }
-
- return tosend / size;
-}
-
-int inputStream_httpClose(InputStream * inStream)
-{
- InputStreamHTTPData *data = (InputStreamHTTPData *) inStream->data;
-
- switch (data->connState) {
- case HTTP_CONN_STATE_CLOSED:
- break;
- default:
- close(data->sock);
- }
-
- freeInputStreamHTTPData(data);
-
- 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;
-
- 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_HELLO) {
- if (getHTTPHello(inStream) < 0)
- 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) {
- 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); */
- data->buflen += readed;
- }
-
- if (data->buflen > prebufferSize)
- data->prebuffer = 0;
-
- return (readed ? 1 : 0);
-}