?? ffserver.c
字號:
get_word(protocol, sizeof(protocol), (const char **)&p); if (strcmp(protocol, "HTTP/1.0") && strcmp(protocol, "HTTP/1.1")) return -1; pstrcpy(c->protocol, sizeof(c->protocol), protocol); if (ffserver_debug) http_log("New connection: %s %s\n", cmd, url); /* 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'; } for (p = c->buffer; *p && *p != '\r' && *p != '\n'; ) { if (strncasecmp(p, "User-Agent:", 11) == 0) { useragent = p + 11; if (*useragent && *useragent != '\n' && isspace(*useragent)) useragent++; break; } p = strchr(p, '\n'); if (!p) break; p++; } redir_type = REDIR_NONE; if (match_ext(filename, "asx")) { redir_type = REDIR_ASX; filename[strlen(filename)-1] = 'f'; } else if (match_ext(filename, "asf") && (!useragent || strncasecmp(useragent, "NSPlayer", 8) != 0)) { /* if this isn't WMP or lookalike, return the redirector file */ redir_type = REDIR_ASF; } else if (match_ext(filename, "rpm,ram")) { redir_type = REDIR_RAM; strcpy(filename + strlen(filename)-2, "m"); } else if (match_ext(filename, "rtsp")) { redir_type = REDIR_RTSP; compute_real_filename(filename, sizeof(url) - 1); } else if (match_ext(filename, "sdp")) { redir_type = REDIR_SDP; compute_real_filename(filename, sizeof(url) - 1); } stream = first_stream; while (stream != NULL) { if (!strcmp(stream->filename, filename) && validate_acl(stream, c)) break; stream = stream->next; } if (stream == NULL) { snprintf(msg, sizeof(msg), "File '%s' not found", url); goto send_error; } c->stream = stream; memcpy(c->feed_streams, stream->feed_streams, sizeof(c->feed_streams)); memset(c->switch_feed_streams, -1, sizeof(c->switch_feed_streams)); if (stream->stream_type == STREAM_TYPE_REDIRECT) { c->http_error = 301; q = c->buffer; q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "HTTP/1.0 301 Moved\r\n"); q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "Location: %s\r\n", stream->feed_filename); q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "Content-type: text/html\r\n"); q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "\r\n"); q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "<html><head><title>Moved</title></head><body>\r\n"); q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "You should be <a href=\"%s\">redirected</a>.\r\n", stream->feed_filename); q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "</body></html>\r\n"); /* prepare output buffer */ c->buffer_ptr = c->buffer; c->buffer_end = q; c->state = HTTPSTATE_SEND_HEADER; return 0; } /* If this is WMP, get the rate information */ if (extract_rates(ratebuf, sizeof(ratebuf), c->buffer)) { 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); } } } if (c->post == 0 && stream->stream_type == STREAM_TYPE_LIVE) { current_bandwidth += stream->bandwidth; } if (c->post == 0 && max_bandwidth < current_bandwidth) { c->http_error = 200; q = c->buffer; q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "HTTP/1.0 200 Server too busy\r\n"); q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "Content-type: text/html\r\n"); q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "\r\n"); q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "<html><head><title>Too busy</title></head><body>\r\n"); q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "<p>The server is too busy to serve your request at this time.</p>\r\n"); q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "<p>The bandwidth being served (including your stream) is %dkbit/sec, and this exceeds the limit of %dkbit/sec.</p>\r\n", current_bandwidth, max_bandwidth); q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "</body></html>\r\n"); /* prepare output buffer */ c->buffer_ptr = c->buffer; c->buffer_end = q; c->state = HTTPSTATE_SEND_HEADER; return 0; } if (redir_type != REDIR_NONE) { 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; switch(redir_type) { case REDIR_ASX: q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "HTTP/1.0 200 ASX Follows\r\n"); q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "Content-type: video/x-ms-asf\r\n"); q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "\r\n"); q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "<ASX Version=\"3\">\r\n"); //q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "<!-- Autogenerated by ffserver -->\r\n"); q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "<ENTRY><REF HREF=\"http://%s/%s%s\"/></ENTRY>\r\n", hostbuf, filename, info); q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "</ASX>\r\n"); break; case REDIR_RAM: q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "HTTP/1.0 200 RAM Follows\r\n"); q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "Content-type: audio/x-pn-realaudio\r\n"); q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "\r\n"); q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "# Autogenerated by ffserver\r\n"); q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "http://%s/%s%s\r\n", hostbuf, filename, info); break; case REDIR_ASF: q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "HTTP/1.0 200 ASF Redirect follows\r\n"); q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "Content-type: video/x-ms-asf\r\n"); q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "\r\n"); q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "[Reference]\r\n"); q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "Ref1=http://%s/%s%s\r\n", hostbuf, filename, info); break; case REDIR_RTSP: { char hostname[256], *p; /* extract only hostname */ pstrcpy(hostname, sizeof(hostname), hostbuf); p = strrchr(hostname, ':'); if (p) *p = '\0'; q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "HTTP/1.0 200 RTSP Redirect follows\r\n"); /* XXX: incorrect mime type ? */ q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "Content-type: application/x-rtsp\r\n"); q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "\r\n"); q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "rtsp://%s:%d/%s\r\n", hostname, ntohs(my_rtsp_addr.sin_port), filename); } break; case REDIR_SDP: { uint8_t *sdp_data; int sdp_data_size, len; struct sockaddr_in my_addr; q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "HTTP/1.0 200 OK\r\n"); q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "Content-type: application/sdp\r\n"); q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "\r\n"); len = sizeof(my_addr); getsockname(c->fd, (struct sockaddr *)&my_addr, &len); /* XXX: should use a dynamic buffer */ sdp_data_size = prepare_sdp_description(stream, &sdp_data, my_addr.sin_addr); if (sdp_data_size > 0) { memcpy(q, sdp_data, sdp_data_size); q += sdp_data_size; *q = '\0'; av_free(sdp_data); } } break; default: av_abort(); break; } /* prepare output buffer */ c->buffer_ptr = c->buffer; c->buffer_end = q; c->state = HTTPSTATE_SEND_HEADER; return 0; } } } snprintf(msg, sizeof(msg), "ASX/RAM file not handled"); goto send_error; } stream->conns_served++; /* XXX: add there authenticate and IP match */ if (c->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", (int) (eol - logline), logline); c->suppress_log = 1; } }#ifdef DEBUG_WMP http_log("\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) { if (modify_current_stream(wmpc, ratebuf)) { wmpc->switch_pending = 1; } } } snprintf(msg, sizeof(msg), "POST command not handled"); c->stream = 0; goto send_error; } if (http_start_receive_data(c) < 0) { snprintf(msg, sizeof(msg), "could not open feed"); goto send_error; } c->http_error = 0; c->state = HTTPSTATE_RECEIVE_DATA; return 0; }#ifdef DEBUG_WMP if (strcmp(stream->filename + strlen(stream->filename) - 4, ".asf") == 0) { http_log("\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) { snprintf(msg, sizeof(msg), "Input stream corresponding to '%s' not found", url); goto send_error; } /* prepare http header */ q = c->buffer; q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "HTTP/1.0 200 OK\r\n"); mime_type = c->stream->fmt->mime_type; if (!mime_type) mime_type = "application/x-octet_stream"; q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "Pragma: no-cache\r\n"); /* for asf, we need extra headers */ if (!strcmp(c->stream->fmt->name,"asf_stream")) { /* Need to allocate a client id */ c->wmp_client_id = random() & 0x7fffffff; q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "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); } q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "Content-Type: %s\r\n", mime_type); q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "\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 += snprintf(q, q - (char *) c->buffer + c->buffer_size, "HTTP/1.0 404 Not Found\r\n"); q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "Content-type: %s\r\n", "text/html"); q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "\r\n"); q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "<HTML>\n"); q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "<HEAD><TITLE>404 Not Found</TITLE></HEAD>\n"); q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "<BODY>%s</BODY>\n", msg); q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "</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;}static void fmt_bytecount(ByteIOContext *pb, int64_t count){ static const char *suffix = " kMGTP"; const char *s; for (s = suffix; count >= 100000 && s[1]; count /= 1000, s++) { } url_fprintf(pb, "%"PRId64"%c", count, *s);}static void compute_stats(HTTPContext *c){ HTTPContext *c1; FFStream *stream; char *p; time_t ti; int i, len;
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -