From b2b618c62f71a448a9bade18f8b2a2274de3a87b Mon Sep 17 00:00:00 2001 From: Michael Smith Date: Sat, 8 Mar 2003 04:57:02 +0000 Subject: [PATCH] Added support for shoutcast login protocol (ewww...) svn path=/trunk/httpp/; revision=4444 --- News | 3 +++ src/connection.c | 41 +++++++++++++++++++++++++++++++++-------- src/httpp/httpp.c | 42 ++++++++++++++++++++++++++++++++++++++++-- src/httpp/httpp.h | 2 ++ 4 files changed, 78 insertions(+), 10 deletions(-) diff --git a/News b/News index 151c8e09..56e1f125 100644 --- a/News +++ b/News @@ -1,3 +1,6 @@ +2003-03-09 + Support for shoutcast source protocol added. + 2003-03-08 Started implementing generic admin interface. Supports (so far): - dynamic configuration of mount fallbacks diff --git a/src/connection.c b/src/connection.c index 50ee4944..13a6e684 100644 --- a/src/connection.c +++ b/src/connection.c @@ -424,6 +424,20 @@ static int _check_pass_http(http_parser_t *parser, return 1; } +static int _check_pass_icy(http_parser_t *parser, char *correctpass) +{ + char *password; + + password = httpp_getvar(parser, HTTPP_VAR_ICYPASSWORD); + if(!password) + return 0; + + if (strcmp(password, correctpass)) + return 0; + else + return 1; +} + static int _check_pass_ice(http_parser_t *parser, char *correctpass) { char *password; @@ -469,6 +483,7 @@ int connection_check_source_pass(http_parser_t *parser, char *mount) char *user = "source"; int ret; int ice_login = config->ice_login; + char *protocol; mount_proxy *mountinfo = config->mounts; thread_mutex_lock(&(config_locks()->mounts_lock)); @@ -492,14 +507,19 @@ int connection_check_source_pass(http_parser_t *parser, char *mount) return 0; } - ret = _check_pass_http(parser, user, pass); - if(!ret && ice_login) - { - ret = _check_pass_ice(parser, pass); - if(ret) - WARN0("Source is using deprecated icecast login"); + protocol = httpp_getvar(parser, "HTTP_VAR_PROTOCOL"); + if(protocol != NULL && !strcmp(protocol, "ICY")) { + ret = _check_pass_icy(parser, pass); + } + else { + ret = _check_pass_http(parser, user, pass); + if(!ret && ice_login) + { + ret = _check_pass_ice(parser, pass); + if(ret) + WARN0("Source is using deprecated icecast login"); + } } - return ret; } @@ -849,7 +869,12 @@ static void *_handle_connection(void *arg) } free(uri); - } else { + } + else if(httpp_parse_icy(parser, header, strlen(header))) { + /* TODO: Map incoming icy connections to /icy_0, etc. */ + _handle_source_request(con, parser, "/"); + } + else { ERROR0("HTTP request parsing failed"); connection_close(con); httpp_destroy(parser); diff --git a/src/httpp/httpp.c b/src/httpp/httpp.c index 14f94c21..0b16f18f 100644 --- a/src/httpp/httpp.c +++ b/src/httpp/httpp.c @@ -270,6 +270,42 @@ static void parse_query(http_parser_t *parser, char *query) } } +/* The old shoutcast procotol. Don't look at this, it's really nasty */ +int httpp_parse_icy(http_parser_t *parser, char *http_data, unsigned long len) +{ + char *data; + char *line[MAX_HEADERS]; + int lines; + + if(http_data == NULL) + return 0; + + data = malloc(len + 1); + memcpy(data, http_data, len); + data[len] = 0; + + lines = split_headers(data, len, line); + + /* Now, this protocol looks like: + * sourcepassword\n + * headers: as normal\n" + * \n + */ + + parser->req_type = httpp_req_source; + httpp_setvar(parser, HTTPP_VAR_URI, "/"); + httpp_setvar(parser, HTTPP_VAR_ICYPASSWORD, line[0]); + httpp_setvar(parser, HTTPP_VAR_PROTOCOL, "ICY"); + /* This protocol is evil */ + httpp_setvar(parser, HTTPP_VAR_VERSION, "666"); + + parse_headers(parser, line, lines); + + free(data); + + return 1; +} + int httpp_parse(http_parser_t *parser, char *http_data, unsigned long len) { char *data, *tmp; @@ -348,8 +384,10 @@ int httpp_parse(http_parser_t *parser, char *http_data, unsigned long len) } parser->uri = strdup(uri); - } else - parser->uri = NULL; + } else { + free(data); + return 0; + } if ((version != NULL) && ((tmp = strchr(version, '/')) != NULL)) { tmp[0] = '\0'; diff --git a/src/httpp/httpp.h b/src/httpp/httpp.h index 5e728e32..e82edf3a 100644 --- a/src/httpp/httpp.h +++ b/src/httpp/httpp.h @@ -14,6 +14,7 @@ #define HTTPP_VAR_REQ_TYPE "__req_type" #define HTTPP_VAR_ERROR_MESSAGE "__errormessage" #define HTTPP_VAR_ERROR_CODE "__errorcode" +#define HTTPP_VAR_ICYPASSWORD "__icy_password" typedef enum httpp_request_type_tag { httpp_req_none, httpp_req_get, httpp_req_post, httpp_req_head, @@ -40,6 +41,7 @@ typedef struct http_parser_tag { http_parser_t *httpp_create_parser(void); void httpp_initialize(http_parser_t *parser, http_varlist_t *defaults); int httpp_parse(http_parser_t *parser, char *http_data, unsigned long len); +int httpp_parse_icy(http_parser_t *parser, char *http_data, unsigned long len); int httpp_parse_response(http_parser_t *parser, char *http_data, unsigned long len, char *uri); void httpp_setvar(http_parser_t *parser, char *name, char *value); char *httpp_getvar(http_parser_t *parser, char *name);