FFStream *optimal;  optimal = find_optimal_stream(stream, ratebuf); if (optimal) stream = optimal;
if (modify_current_stream(c, ratebuf)) { for (i = 0; i < sizeof(c->feed_streams) / sizeof(c->feed_streams[0]); i++) { if (c->switch_feed_streams[i] >= 0) do_switch_stream(c, i); } }
static int http_parse_request(HTTPContext *c){    char *p;    int post;    int doing_asx;    int doing_ram;    char cmd[32];    char info[1024], *filename;    char url[1024], *q;    char protocol[32];    char msg[1024];    const char *mime_type;    FFStream *stream;    int i;    char ratebuf[32];    p = c->buffer;    q = cmd;    while (!isspace(*p) && *p != '\0') {        if ((q - cmd) < sizeof(cmd) - 1)            *q++ = *p;        p++;    }    *q = '\0';    pstrcpy(c->method, sizeof(c->method), cmd);    if (!strcmp(cmd, "GET"))        post = 0;    else if (!strcmp(cmd, "POST"))        post = 1;    else        return -1;    while (isspace(*p)) p++;    q = url;    while (!isspace(*p) && *p != '\0') {        if ((q - url) < sizeof(url) - 1)            *q++ = *p;        p++;    }    *q = '\0';    pstrcpy(c->url, sizeof(c->url), url);    while (isspace(*p)) p++;    q = protocol;    while (!isspace(*p) && *p != '\0') {        if ((q - protocol) < sizeof(protocol) - 1)            *q++ = *p;        p++;    }    *q = '\0';    if (strcmp(protocol, "HTTP/1.0") && strcmp(protocol, "HTTP/1.1"))        return -1;    pstrcpy(c->protocol, sizeof(c->protocol), protocol);        /* find the filename and the optional info string in the request */    p = url;    if (*p == '/')        p++;    filename = p;    p = strchr(p, '?');    if (p) {        pstrcpy(info, sizeof(info), p);        *p = '\0';    } else {        info[0] = '\0';    }    if (strlen(filename) > 4 && strcmp(".asx", filename + strlen(filename) - 4) == 0) {        doing_asx = 1;        filename[strlen(filename)-1] = 'f';    } else {        doing_asx = 0;    }    if (strlen(filename) > 4 &&         (strcmp(".rpm", filename + strlen(filename) - 4) == 0 ||         strcmp(".ram", filename + strlen(filename) - 4) == 0)) {        doing_ram = 1;        strcpy(filename + strlen(filename)-2, "m");    } else {        doing_ram = 0;    }    stream = first_stream;    while (stream != NULL) {        if (!strcmp(stream->filename, filename))            break;        stream = stream->next;    }    if (stream == NULL) {        sprintf(msg, "File '%s' not found", url);        goto send_error;    }    /* If this is WMP, get the rate information */    if (extract_rates(ratebuf, sizeof(ratebuf), c->buffer)) {        FFStream *optimal;        optimal = find_optimal_stream(stream, ratebuf);        if (optimal)            stream = optimal;    }    if (post == 0 && stream->stream_type == STREAM_TYPE_LIVE) {        /* See if we meet the bandwidth requirements */        for(i=0;i<stream->nb_streams;i++) {            AVStream *st = stream->streams[i];            switch(st->codec.codec_type) {            case CODEC_TYPE_AUDIO:                c->bandwidth += st->codec.bit_rate;                break;            case CODEC_TYPE_VIDEO:                c->bandwidth += st->codec.bit_rate;                break;            default:                av_abort();            }        }    }    c->bandwidth /= 1000;    nb_bandwidth += c->bandwidth;    if (post == 0 && nb_max_bandwidth < nb_bandwidth) {        c->http_error = 200;        q = c->buffer;        q += sprintf(q, "HTTP/1.0 200 Server too busy\r\n");        q += sprintf(q, "Content-type: text/html\r\n");        q += sprintf(q, "\r\n");        q += sprintf(q, "<html><head><title>Too busy</title></head><body>\r\n");        q += sprintf(q, "The server is too busy to serve your request at this time.<p>\r\n");        q += sprintf(q, "The bandwidth being served (including your stream) is %dkbit/sec, and this exceeds the limit of %dkbit/sec\r\n",            nb_bandwidth, nb_max_bandwidth);        q += sprintf(q, "</body></html>\r\n");        /* prepare output buffer */        c->buffer_ptr = c->buffer;        c->buffer_end = q;        c->state = HTTPSTATE_SEND_HEADER;        return 0;    }        if (doing_asx || doing_ram) {        char *hostinfo = 0;                for (p = c->buffer; *p && *p != '\r' && *p != '\n'; ) {            if (strncasecmp(p, "Host:", 5) == 0) {                hostinfo = p + 5;                break;            }            p = strchr(p, '\n');            if (!p)                break;            p++;        }        if (hostinfo) {            char *eoh;            char hostbuf[260];            while (isspace(*hostinfo))                hostinfo++;            eoh = strchr(hostinfo, '\n');            if (eoh) {                if (eoh[-1] == '\r')                    eoh--;                if (eoh - hostinfo < sizeof(hostbuf) - 1) {                    memcpy(hostbuf, hostinfo, eoh - hostinfo);                    hostbuf[eoh - hostinfo] = 0;                    c->http_error = 200;                    q = c->buffer;                    if (doing_asx) {                        q += sprintf(q, "HTTP/1.0 200 ASX Follows\r\n");                        q += sprintf(q, "Content-type: video/x-ms-asf\r\n");                        q += sprintf(q, "\r\n");                        q += sprintf(q, "<ASX Version=\"3\">\r\n");                        q += sprintf(q, "<!-- Autogenerated by ffserver -->\r\n");                        q += sprintf(q, "<ENTRY><REF HREF=\"http://%s/%s%s\"/></ENTRY>\r\n",                                 hostbuf, filename, info);                        q += sprintf(q, "</ASX>\r\n");                    } else if (doing_ram) {                        q += sprintf(q, "HTTP/1.0 200 RAM Follows\r\n");                        q += sprintf(q, "Content-type: audio/x-pn-realaudio\r\n");                        q += sprintf(q, "\r\n");                        q += sprintf(q, "# Autogenerated by ffserver\r\n");                        q += sprintf(q, "http://%s/%s%s\r\n",                                 hostbuf, filename, info);                    } else                        av_abort();                    /* prepare output buffer */                    c->buffer_ptr = c->buffer;                    c->buffer_end = q;                    c->state = HTTPSTATE_SEND_HEADER;                    return 0;                }            }        }        sprintf(msg, "ASX/RAM file not handled");        goto send_error;    }    c->stream = stream;    stream->conns_served++;    /* XXX: add there authenticate and IP match */    if (post) {        /* if post, it means a feed is being sent */        if (!stream->is_feed) {            /* However it might be a status report from WMP! Lets log the data             * as it might come in handy one day             */            char *logline = 0;            int client_id = 0;                        for (p = c->buffer; *p && *p != '\r' && *p != '\n'; ) {                if (strncasecmp(p, "Pragma: log-line=", 17) == 0) {                    logline = p;                    break;                }                if (strncasecmp(p, "Pragma: client-id=", 18) == 0) {                    client_id = strtol(p + 18, 0, 10);                }                p = strchr(p, '\n');                if (!p)                    break;                p++;            }            if (logline) {                char *eol = strchr(logline, '\n');                logline += 17;                if (eol) {                    if (eol[-1] == '\r')                        eol--;                    http_log("%.*s\n", eol - logline, logline);                    c->suppress_log = 1;                }            }#ifdef DEBUG            fprintf(stderr, "\nGot request:\n%s\n", c->buffer);#endif            if (client_id && extract_rates(ratebuf, sizeof(ratebuf), c->buffer)) {                HTTPContext *wmpc;                /* Now we have to find the client_id */                for (wmpc = first_http_ctx; wmpc; wmpc = wmpc->next) {                    if (wmpc->wmp_client_id == client_id)                        break;                }                if (wmpc) {                    FFStream *optimal;                    optimal = find_optimal_stream(wmpc->stream, ratebuf);                    if (optimal) {                        fprintf(stderr, "Would like to switch stream from %s to %s\n",                                wmpc->stream->filename, optimal->filename);                    }                }            }                        sprintf(msg, "POST command not handled");            goto send_error;        }        if (http_start_receive_data(c) < 0) {            sprintf(msg, "could not open feed");            goto send_error;        }        c->http_error = 0;        c->state = HTTPSTATE_RECEIVE_DATA;        return 0;    }#ifdef DEBUG    if (strcmp(stream->filename + strlen(stream->filename) - 4, ".asf") == 0) {        fprintf(stderr, "\nGot request:\n%s\n", c->buffer);    }#endif    if (c->stream->stream_type == STREAM_TYPE_STATUS)        goto send_stats;    /* open input stream */    if (open_input_stream(c, info) < 0) {        sprintf(msg, "Input stream corresponding to '%s' not found", url);        goto send_error;    }    /* prepare http header */    q = c->buffer;    q += sprintf(q, "HTTP/1.0 200 OK\r\n");    mime_type = c->stream->fmt->mime_type;    if (!mime_type)        mime_type = "application/x-octet_stream";    q += sprintf(q, "Pragma: no-cache\r\n");    /* for asf, we need extra headers */    if (!strcmp(c->stream->fmt->name,"asf")) {        /* Need to allocate a client id */        static int wmp_session;        if (!wmp_session)            wmp_session = time(0) & 0xffffff;        c->wmp_client_id = ++wmp_session;        q += sprintf(q, "Server: Cougar 4.1.0.3923\r\nCache-Control: no-cache\r\nPragma: client-id=%d\r\nPragma: features=\"broadcast\"\r\n", c->wmp_client_id);        /* mime_type = "application/octet-stream"; */        /* video/x-ms-asf seems better -- netscape doesn't crash any more! */        mime_type = "video/x-ms-asf";    }    q += sprintf(q, "Content-Type: %s\r\n", mime_type);    q += sprintf(q, "\r\n");        /* prepare output buffer */    c->http_error = 0;    c->buffer_ptr = c->buffer;    c->buffer_end = q;    c->state = HTTPSTATE_SEND_HEADER;    return 0; send_error:    c->http_error = 404;    q = c->buffer;    q += sprintf(q, "HTTP/1.0 404 Not Found\r\n");    q += sprintf(q, "Content-type: %s\r\n", "text/html");    q += sprintf(q, "\r\n");    q += sprintf(q, "<HTML>\n");    q += sprintf(q, "<HEAD><TITLE>404 Not Found</TITLE></HEAD>\n");    q += sprintf(q, "<BODY>%s</BODY>\n", msg);    q += sprintf(q, "</HTML>\n");    /* prepare output buffer */    c->buffer_ptr = c->buffer;    c->buffer_end = q;    c->state = HTTPSTATE_SEND_HEADER;    return 0; send_stats:    compute_stats(c);    c->http_error = 200; /* horrible : we use this value to avoid                            going to the send data state */    c->state = HTTPSTATE_SEND_HEADER;    return 0;}