?? ffserver.c
字號:
return -1; } else { /* search for end of request. */ uint8_t *ptr; c->buffer_ptr += len; ptr = c->buffer_ptr; if ((ptr >= c->buffer + 2 && !memcmp(ptr-2, "\n\n", 2)) || (ptr >= c->buffer + 4 && !memcmp(ptr-4, "\r\n\r\n", 4))) { /* request found : parse it and reply */ if (c->state == HTTPSTATE_WAIT_REQUEST) { ret = http_parse_request(c); } else { ret = rtsp_parse_request(c); } if (ret < 0) return -1; } else if (ptr >= c->buffer_end) { /* request too long: cannot do anything */ return -1; } else goto read_loop; } break; case HTTPSTATE_SEND_HEADER: if (c->poll_entry->revents & (POLLERR | POLLHUP)) return -1; /* no need to write if no events */ if (!(c->poll_entry->revents & POLLOUT)) return 0; len = write(c->fd, c->buffer_ptr, c->buffer_end - c->buffer_ptr); if (len < 0) { if (errno != EAGAIN && errno != EINTR) { /* error : close connection */ av_freep(&c->pb_buffer); return -1; } } else { c->buffer_ptr += len; if (c->stream) c->stream->bytes_served += len; c->data_count += len; if (c->buffer_ptr >= c->buffer_end) { av_freep(&c->pb_buffer); /* if error, exit */ if (c->http_error) { return -1; } /* all the buffer was sent : synchronize to the incoming stream */ c->state = HTTPSTATE_SEND_DATA_HEADER; c->buffer_ptr = c->buffer_end = c->buffer; } } break; case HTTPSTATE_SEND_DATA: case HTTPSTATE_SEND_DATA_HEADER: case HTTPSTATE_SEND_DATA_TRAILER: /* for packetized output, we consider we can always write (the input streams sets the speed). It may be better to verify that we do not rely too much on the kernel queues */ if (!c->is_packetized) { if (c->poll_entry->revents & (POLLERR | POLLHUP)) return -1; /* no need to read if no events */ if (!(c->poll_entry->revents & POLLOUT)) return 0; } if (http_send_data(c) < 0) return -1; break; case HTTPSTATE_RECEIVE_DATA: /* no need to read if no events */ if (c->poll_entry->revents & (POLLERR | POLLHUP)) return -1; if (!(c->poll_entry->revents & POLLIN)) return 0; if (http_receive_data(c) < 0) return -1; break; case HTTPSTATE_WAIT_FEED: /* no need to read if no events */ if (c->poll_entry->revents & (POLLIN | POLLERR | POLLHUP)) return -1; /* nothing to do, we'll be waken up by incoming feed packets */ break; case RTSPSTATE_SEND_REPLY: if (c->poll_entry->revents & (POLLERR | POLLHUP)) { av_freep(&c->pb_buffer); return -1; } /* no need to write if no events */ if (!(c->poll_entry->revents & POLLOUT)) return 0; len = write(c->fd, c->buffer_ptr, c->buffer_end - c->buffer_ptr); if (len < 0) { if (errno != EAGAIN && errno != EINTR) { /* error : close connection */ av_freep(&c->pb_buffer); return -1; } } else { c->buffer_ptr += len; c->data_count += len; if (c->buffer_ptr >= c->buffer_end) { /* all the buffer was sent : wait for a new request */ av_freep(&c->pb_buffer); start_wait_request(c, 1); } } break; case RTSPSTATE_SEND_PACKET: if (c->poll_entry->revents & (POLLERR | POLLHUP)) { av_freep(&c->packet_buffer); return -1; } /* no need to write if no events */ if (!(c->poll_entry->revents & POLLOUT)) return 0; len = write(c->fd, c->packet_buffer_ptr, c->packet_buffer_end - c->packet_buffer_ptr); if (len < 0) { if (errno != EAGAIN && errno != EINTR) { /* error : close connection */ av_freep(&c->packet_buffer); return -1; } } else { c->packet_buffer_ptr += len; if (c->packet_buffer_ptr >= c->packet_buffer_end) { /* all the buffer was sent : wait for a new request */ av_freep(&c->packet_buffer); c->state = RTSPSTATE_WAIT_REQUEST; } } break; case HTTPSTATE_READY: /* nothing to do */ break; default: return -1; } return 0;}static int extract_rates(char *rates, int ratelen, const char *request){ const char *p; for (p = request; *p && *p != '\r' && *p != '\n'; ) { if (strncasecmp(p, "Pragma:", 7) == 0) { const char *q = p + 7; while (*q && *q != '\n' && isspace(*q)) q++; if (strncasecmp(q, "stream-switch-entry=", 20) == 0) { int stream_no; int rate_no; q += 20; memset(rates, 0xff, ratelen); while (1) { while (*q && *q != '\n' && *q != ':') q++; if (sscanf(q, ":%d:%d", &stream_no, &rate_no) != 2) { break; } stream_no--; if (stream_no < ratelen && stream_no >= 0) { rates[stream_no] = rate_no; } while (*q && *q != '\n' && !isspace(*q)) q++; } return 1; } } p = strchr(p, '\n'); if (!p) break; p++; } return 0;}static int find_stream_in_feed(FFStream *feed, AVCodecContext *codec, int bit_rate){ int i; int best_bitrate = 100000000; int best = -1; for (i = 0; i < feed->nb_streams; i++) { AVCodecContext *feed_codec = feed->streams[i]->codec; if (feed_codec->codec_id != codec->codec_id || feed_codec->sample_rate != codec->sample_rate || feed_codec->width != codec->width || feed_codec->height != codec->height) { continue; } /* Potential stream */ /* We want the fastest stream less than bit_rate, or the slowest * faster than bit_rate */ if (feed_codec->bit_rate <= bit_rate) { if (best_bitrate > bit_rate || feed_codec->bit_rate > best_bitrate) { best_bitrate = feed_codec->bit_rate; best = i; } } else { if (feed_codec->bit_rate < best_bitrate) { best_bitrate = feed_codec->bit_rate; best = i; } } } return best;}static int modify_current_stream(HTTPContext *c, char *rates){ int i; FFStream *req = c->stream; int action_required = 0; /* Not much we can do for a feed */ if (!req->feed) return 0; for (i = 0; i < req->nb_streams; i++) { AVCodecContext *codec = req->streams[i]->codec; switch(rates[i]) { case 0: c->switch_feed_streams[i] = req->feed_streams[i]; break; case 1: c->switch_feed_streams[i] = find_stream_in_feed(req->feed, codec, codec->bit_rate / 2); break; case 2: /* Wants off or slow */ c->switch_feed_streams[i] = find_stream_in_feed(req->feed, codec, codec->bit_rate / 4);#ifdef WANTS_OFF /* This doesn't work well when it turns off the only stream! */ c->switch_feed_streams[i] = -2; c->feed_streams[i] = -2;#endif break; } if (c->switch_feed_streams[i] >= 0 && c->switch_feed_streams[i] != c->feed_streams[i]) action_required = 1; } return action_required;}static void do_switch_stream(HTTPContext *c, int i){ if (c->switch_feed_streams[i] >= 0) {#ifdef PHILIP c->feed_streams[i] = c->switch_feed_streams[i];#endif /* Now update the stream */ } c->switch_feed_streams[i] = -1;}/* XXX: factorize in utils.c ? *//* XXX: take care with different space meaning */static void skip_spaces(const char **pp){ const char *p; p = *pp; while (*p == ' ' || *p == '\t') p++; *pp = p;}static void get_word(char *buf, int buf_size, const char **pp){ const char *p; char *q; p = *pp; skip_spaces(&p); q = buf; while (!isspace(*p) && *p != '\0') { if ((q - buf) < buf_size - 1) *q++ = *p; p++; } if (buf_size > 0) *q = '\0'; *pp = p;}static int validate_acl(FFStream *stream, HTTPContext *c){ enum IPAddressAction last_action = IP_DENY; IPAddressACL *acl; struct in_addr *src = &c->from_addr.sin_addr; unsigned long src_addr = ntohl(src->s_addr); for (acl = stream->acl; acl; acl = acl->next) { if (src_addr >= acl->first.s_addr && src_addr <= acl->last.s_addr) { return (acl->action == IP_ALLOW) ? 1 : 0; } last_action = acl->action; } /* Nothing matched, so return not the last action */ return (last_action == IP_DENY) ? 1 : 0;}/* compute the real filename of a file by matching it without its extensions to all the stream filenames */static void compute_real_filename(char *filename, int max_size){ char file1[1024]; char file2[1024]; char *p; FFStream *stream; /* compute filename by matching without the file extensions */ pstrcpy(file1, sizeof(file1), filename); p = strrchr(file1, '.'); if (p) *p = '\0'; for(stream = first_stream; stream != NULL; stream = stream->next) { pstrcpy(file2, sizeof(file2), stream->filename); p = strrchr(file2, '.'); if (p) *p = '\0'; if (!strcmp(file1, file2)) { pstrcpy(filename, max_size, stream->filename); break; } }}enum RedirType { REDIR_NONE, REDIR_ASX, REDIR_RAM, REDIR_ASF, REDIR_RTSP, REDIR_SDP,};/* parse http request and prepare header */static int http_parse_request(HTTPContext *c){ char *p; enum RedirType redir_type; 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]; char *useragent = 0; p = c->buffer; get_word(cmd, sizeof(cmd), (const char **)&p); pstrcpy(c->method, sizeof(c->method), cmd); if (!strcmp(cmd, "GET")) c->post = 0; else if (!strcmp(cmd, "POST")) c->post = 1; else return -1; get_word(url, sizeof(url), (const char **)&p); pstrcpy(c->url, sizeof(c->url), url);
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -