static inline int check_sessionid(AVFormatContext *s, RTSPMessageHeader *request) { RTSPState *rt = s->priv_data; unsigned char *session_id = rt->session_id; if (!session_id[0]) { av_log(s, AV_LOG_WARNING, "There is no session-id at the moment\n"); return 0; } if (strcmp(session_id, request->session_id)) { av_log(s, AV_LOG_ERROR, "Unexpected session-id %s\n", request->session_id); rtsp_send_reply(s, RTSP_STATUS_SESSION, NULL, request->seq); return AVERROR_STREAM_NOT_FOUND; } return 0; }
static int rtsp_read_options(AVFormatContext *s) { RTSPState *rt = s->priv_data; RTSPMessageHeader request = { 0 }; int ret = 0; /* Parsing headers */ ret = rtsp_read_request(s, &request, "OPTIONS"); if (ret) return ret; rt->seq++; /* Send Reply */ rtsp_send_reply(s, RTSP_STATUS_OK, "Public: ANNOUNCE, PAUSE, SETUP, TEARDOWN, RECORD\r\n", request.seq); return 0; }
static int rtsp_read_record(AVFormatContext *s) { RTSPState *rt = s->priv_data; RTSPMessageHeader request = { 0 }; int ret = 0; char responseheaders[1024]; ret = rtsp_read_request(s, &request, "RECORD"); if (ret) return ret; ret = check_sessionid(s, &request); if (ret) return ret; rt->seq++; snprintf(responseheaders, sizeof(responseheaders), "Session: %s\r\n", rt->session_id); rtsp_send_reply(s, RTSP_STATUS_OK, responseheaders, request.seq); rt->state = RTSP_STATE_STREAMING; return 0; }
static int rtsp_read_setup(AVFormatContext *s, char* host, char *controlurl) { RTSPState *rt = s->priv_data; RTSPMessageHeader request = { 0 }; int ret = 0; char url[1024]; RTSPStream *rtsp_st; char responseheaders[1024]; int localport = -1; int transportidx = 0; int streamid = 0; ret = rtsp_read_request(s, &request, "SETUP"); if (ret) return ret; rt->seq++; if (!request.nb_transports) { av_log(s, AV_LOG_ERROR, "No transport defined in SETUP\n"); return AVERROR_INVALIDDATA; } for (transportidx = 0; transportidx < request.nb_transports; transportidx++) { if (!request.transports[transportidx].mode_record || (request.transports[transportidx].lower_transport != RTSP_LOWER_TRANSPORT_UDP && request.transports[transportidx].lower_transport != RTSP_LOWER_TRANSPORT_TCP)) { av_log(s, AV_LOG_ERROR, "mode=record/receive not set or transport" " protocol not supported (yet)\n"); return AVERROR_INVALIDDATA; } } if (request.nb_transports > 1) av_log(s, AV_LOG_WARNING, "More than one transport not supported, " "using first of all\n"); for (streamid = 0; streamid < rt->nb_rtsp_streams; streamid++) { if (!strcmp(rt->rtsp_streams[streamid]->control_url, controlurl)) break; } if (streamid == rt->nb_rtsp_streams) { av_log(s, AV_LOG_ERROR, "Unable to find requested track\n"); return AVERROR_STREAM_NOT_FOUND; } rtsp_st = rt->rtsp_streams[streamid]; localport = rt->rtp_port_min; if (request.transports[0].lower_transport == RTSP_LOWER_TRANSPORT_TCP) { rt->lower_transport = RTSP_LOWER_TRANSPORT_TCP; if ((ret = ff_rtsp_open_transport_ctx(s, rtsp_st))) { rtsp_send_reply(s, RTSP_STATUS_TRANSPORT, NULL, request.seq); return ret; } rtsp_st->interleaved_min = request.transports[0].interleaved_min; rtsp_st->interleaved_max = request.transports[0].interleaved_max; snprintf(responseheaders, sizeof(responseheaders), "Transport: " "RTP/AVP/TCP;unicast;mode=receive;interleaved=%d-%d" "\r\n", request.transports[0].interleaved_min, request.transports[0].interleaved_max); } else { do { ff_url_join(url, sizeof(url), "rtp", NULL, host, localport, NULL); av_dlog(s, "Opening: %s", url); ret = ffurl_open(&rtsp_st->rtp_handle, url, AVIO_FLAG_READ_WRITE, &s->interrupt_callback, NULL); if (ret) localport += 2; } while (ret || localport > rt->rtp_port_max); if (localport > rt->rtp_port_max) { rtsp_send_reply(s, RTSP_STATUS_TRANSPORT, NULL, request.seq); return ret; } av_dlog(s, "Listening on: %d", ff_rtp_get_local_rtp_port(rtsp_st->rtp_handle)); if ((ret = ff_rtsp_open_transport_ctx(s, rtsp_st))) { rtsp_send_reply(s, RTSP_STATUS_TRANSPORT, NULL, request.seq); return ret; } localport = ff_rtp_get_local_rtp_port(rtsp_st->rtp_handle); snprintf(responseheaders, sizeof(responseheaders), "Transport: " "RTP/AVP/UDP;unicast;mode=receive;source=%s;" "client_port=%d-%d;server_port=%d-%d\r\n", host, request.transports[0].client_port_min, request.transports[0].client_port_max, localport, localport + 1); } /* Establish sessionid if not previously set */ /* Put this in a function? */ /* RFC 2326: session id must be at least 8 digits */ while (strlen(rt->session_id) < 8) av_strlcatf(rt->session_id, 512, "%u", av_get_random_seed()); av_strlcatf(responseheaders, sizeof(responseheaders), "Session: %s\r\n", rt->session_id); /* Send Reply */ rtsp_send_reply(s, RTSP_STATUS_OK, responseheaders, request.seq); rt->state = RTSP_STATE_PAUSED; return 0; }