This source file includes following definitions.
- gf_rtsp_read_reply
- gf_rtsp_get_body_info
- gf_rtsp_refill_buffer
- gf_rtsp_fill_buffer
- gf_rtsp_transport_parse
- gf_rtsp_parse_header
- gf_rtsp_nc_to_string
#include <gpac/internal/ietf_dev.h>
#ifndef GPAC_DISABLE_STREAMING
#include <gpac/token.h>
GF_Err gf_rtsp_read_reply(GF_RTSPSession *sess)
{
GF_Err e;
u32 res, body_size = 0;
u32 BodyStart = 0;
while (1) {
if (!BodyStart) gf_rtsp_get_body_info(sess, &BodyStart, &body_size);
if (BodyStart) {
res = sess->CurrentSize - sess->CurrentPos;
if (!body_size || (res >= body_size + BodyStart)) {
break;
}
}
e = gf_rtsp_refill_buffer(sess);
if (e) return e;
}
return GF_OK;
}
void gf_rtsp_get_body_info(GF_RTSPSession *sess, u32 *body_start, u32 *body_size)
{
u32 i;
s32 start;
char *buffer;
char *cl_str, val[30];
*body_start = *body_size = 0;
buffer = sess->TCPBuffer + sess->CurrentPos;
start = gf_token_find(buffer, 0, sess->CurrentSize - sess->CurrentPos, "\r\n\r\n");
if (start<=0) {
return;
}
*body_start = start + 4;
cl_str = strstr(buffer, "Content-Length: ");
if (!cl_str) cl_str = strstr(buffer, "Content-length: ");
if (cl_str) {
cl_str += 16;
i = 0;
while (cl_str[i] != '\r') {
val[i] = cl_str[i];
i += 1;
}
val[i] = 0;
*body_size = atoi(val);
} else {
*body_size = 0;
}
}
GF_Err gf_rtsp_refill_buffer(GF_RTSPSession *sess)
{
GF_Err e;
u32 res;
char *ptr;
if (!sess) return GF_BAD_PARAM;
if (!sess->connection) return GF_IP_NETWORK_EMPTY;
res = sess->CurrentSize - sess->CurrentPos;
if (!res) return gf_rtsp_fill_buffer(sess);
ptr = (char *)gf_malloc(sizeof(char) * res);
memcpy(ptr, sess->TCPBuffer+sess->CurrentPos, res);
memcpy(sess->TCPBuffer, ptr, res);
gf_free(ptr);
sess->CurrentPos = 0;
sess->CurrentSize = res;
e = gf_sk_receive(sess->connection, sess->TCPBuffer + sess->CurrentSize,
RTSP_TCP_BUF_SIZE - sess->CurrentSize,
0, &res);
if (!e) {
sess->CurrentSize += res;
}
return e;
}
GF_Err gf_rtsp_fill_buffer(GF_RTSPSession *sess)
{
GF_Err e = GF_OK;
if (!sess->connection) return GF_IP_NETWORK_EMPTY;
if (sess->CurrentSize == sess->CurrentPos) {
e = gf_sk_receive(sess->connection, sess->TCPBuffer, RTSP_TCP_BUF_SIZE, 0, &sess->CurrentSize);
sess->CurrentPos = 0;
sess->TCPBuffer[sess->CurrentSize] = 0;
if (e) sess->CurrentSize = 0;
} else if (!sess->CurrentSize) e = GF_IP_NETWORK_EMPTY;
return e;
}
GF_RTSPTransport *gf_rtsp_transport_parse(char *buffer)
{
Bool IsFirst;
char buf[100], param_name[100], param_val[100];
s32 pos, nPos;
u32 v1, v2;
GF_RTSPTransport *tmp;
if (!buffer) return NULL;
if (strnicmp(buffer, "RTP/AVP", 7) && strnicmp(buffer, "RTP/SAVP", 8)) return NULL;
GF_SAFEALLOC(tmp, GF_RTSPTransport);
if (!tmp) return NULL;
IsFirst = GF_TRUE;
pos = 0;
while (1) {
pos = gf_token_get(buffer, pos, " ;", buf, 100);
if (pos <= 0) break;
if (strstr(buf, "=")) {
nPos = gf_token_get(buf, 0, "=", param_name, 100);
gf_token_get(buf, nPos, "=", param_val, 100);
} else {
strcpy(param_name, buf);
}
if (IsFirst) {
tmp->Profile = gf_strdup(param_name);
IsFirst = GF_FALSE;
continue;
}
if (!stricmp(param_name, "destination")) {
if (tmp->destination) gf_free(tmp->destination);
tmp->destination = gf_strdup(param_val);
}
else if (!stricmp(param_name, "source")) {
if (tmp->source) gf_free(tmp->source);
tmp->source = gf_strdup(param_val);
}
else if (!stricmp(param_name, "unicast")) tmp->IsUnicast = GF_TRUE;
else if (!stricmp(param_name, "RECORD")) tmp->IsRecord = GF_TRUE;
else if (!stricmp(param_name, "append")) tmp->Append = GF_TRUE;
else if (!stricmp(param_name, "interleaved")) {
u32 rID, rcID;
tmp->IsInterleaved = GF_TRUE;
if (sscanf(param_val, "%u-%u", &rID, &rcID) == 1) {
sscanf(param_val, "%u", &rID);
tmp->rtcpID = tmp->rtpID = (u8) rID;
} else {
tmp->rtpID = (u8) rID;
tmp->rtcpID = (u8) rcID;
}
}
else if (!stricmp(param_name, "layers")) sscanf(param_val, "%u", &tmp->MulticastLayers);
else if (!stricmp(param_name, "ttl")) sscanf(param_val, "%c ", &tmp->TTL);
else if (!stricmp(param_name, "port")) {
sscanf(param_val, "%u-%u", &v1, &v2);
tmp->port_first = (u16) v1;
tmp->port_last = (u16) v2;
}
else if (!stricmp(param_name, "server_port")) {
sscanf(param_val, "%d-%d", &v1, &v2);
tmp->port_first = (u16) v1;
tmp->port_last = (u16) v2;
}
else if (!stricmp(param_name, "client_port")) {
sscanf(param_val, "%d-%d", &v1, &v2);
tmp->client_port_first = (u16) v1;
tmp->client_port_last = (u16) v2;
}
else if (!stricmp(param_name, "ssrc")) sscanf(param_val, "%X", &tmp->SSRC);
}
return tmp;
}
GF_Err gf_rtsp_parse_header(char *buffer, u32 BufferSize, u32 BodyStart, GF_RTSPCommand *com, GF_RTSPResponse *rsp)
{
char LineBuffer[1024];
char HeaderBuf[100], ValBuf[1024], temp[400];
s32 Pos, LinePos;
u32 HeaderLine;
LinePos = 0;
strcpy(HeaderBuf, "");
while (1) {
LinePos = gf_token_get_line(buffer, LinePos, BufferSize, LineBuffer, 1024);
if (LinePos <= 0) return GF_REMOTE_SERVICE_ERROR;
Pos = gf_token_get(LineBuffer, 0, ":\r\n", temp, 400);
if (Pos <= 0) {
HeaderLine = 2;
}
else if (LineBuffer[0] != ' ') {
HeaderLine = 1;
} else {
Pos = gf_token_get(LineBuffer, 0, ", \r\n", temp, 400);
if (Pos <= 0) {
HeaderLine = 2;
} else {
strcat(ValBuf, "\r\n");
strcat(ValBuf, temp);
continue;
}
}
if (HeaderLine && strlen(HeaderBuf)) {
if (rsp) {
gf_rtsp_set_response_value(rsp, HeaderBuf, ValBuf);
}
else {
gf_rtsp_set_command_value(com, HeaderBuf, ValBuf);
}
}
if ( (HeaderLine == 2) || ((u32) LinePos >= BodyStart) ) return GF_OK;
strcpy(HeaderBuf, temp);
Pos += 1;
if (LineBuffer[Pos] == ' ') Pos += 1;
if (!strcmp(LineBuffer+Pos, "\r\n")) {
HeaderBuf[0] = 0;
continue;
}
Pos = gf_token_get(LineBuffer, Pos, "\r\n", ValBuf, 400);
if (Pos <= 0) break;
}
return GF_REMOTE_SERVICE_ERROR;
}
GF_EXPORT
const char *gf_rtsp_nc_to_string(u32 ErrCode)
{
switch (ErrCode) {
case NC_RTSP_Continue:
return "Continue";
case NC_RTSP_OK:
return "OK";
case NC_RTSP_Created:
return "Created";
case NC_RTSP_Low_on_Storage_Space:
return "Low on Storage Space";
case NC_RTSP_Multiple_Choice:
return "Multiple Choice";
case NC_RTSP_Moved_Permanently:
return "Moved Permanently";
case NC_RTSP_Moved_Temporarily:
return "Moved Temporarily";
case NC_RTSP_See_Other:
return "See Other";
case NC_RTSP_Use_Proxy:
return "Use Proxy";
case NC_RTSP_Bad_Request:
return "Bad Request";
case NC_RTSP_Unauthorized:
return "Unauthorized";
case NC_RTSP_Payment_Required:
return "Payment Required";
case NC_RTSP_Forbidden:
return "Forbidden";
case NC_RTSP_Not_Found:
return "Not Found";
case NC_RTSP_Method_Not_Allowed:
return "Method Not Allowed";
case NC_RTSP_Not_Acceptable:
return "Not Acceptable";
case NC_RTSP_Proxy_Authentication_Required:
return "Proxy Authentication Required";
case NC_RTSP_Request_Timeout:
return "Request Timeout";
case NC_RTSP_Gone:
return "Gone";
case NC_RTSP_Length_Required:
return "Length Required";
case NC_RTSP_Precondition_Failed:
return "Precondition Failed";
case NC_RTSP_Request_Entity_Too_Large:
return "Request Entity Too Large";
case NC_RTSP_Request_URI_Too_Long:
return "Request URI Too Long";
case NC_RTSP_Unsupported_Media_Type:
return "Unsupported Media Type";
case NC_RTSP_Invalid_parameter:
return "Invalid parameter";
case NC_RTSP_Illegal_Conference_Identifier:
return "Illegal Conference Identifier";
case NC_RTSP_Not_Enough_Bandwidth:
return "Not Enough Bandwidth";
case NC_RTSP_Session_Not_Found:
return "Session Not Found";
case NC_RTSP_Method_Not_Valid_In_This_State:
return "Method Not Valid In This State";
case NC_RTSP_Header_Field_Not_Valid:
return "Header Field Not Valid";
case NC_RTSP_Invalid_Range:
return "Invalid Range";
case NC_RTSP_Parameter_Is_ReadOnly:
return "Parameter Is Read-Only";
case NC_RTSP_Aggregate_Operation_Not_Allowed:
return "Aggregate Operation Not Allowed";
case NC_RTSP_Only_Aggregate_Operation_Allowed:
return "Only Aggregate Operation Allowed";
case NC_RTSP_Unsupported_Transport:
return "Unsupported Transport";
case NC_RTSP_Destination_Unreachable:
return "Destination Unreachable";
case NC_RTSP_Internal_Server_Error:
return "Internal Server Error";
case NC_RTSP_Bad_Gateway:
return "Bad Gateway";
case NC_RTSP_Service_Unavailable:
return "Service Unavailable";
case NC_RTSP_Gateway_Timeout:
return "Gateway Timeout";
case NC_RTSP_RTSP_Version_Not_Supported:
return "RTSP Version Not Supported";
case NC_RTSP_Option_not_support:
return "Option not support";
case NC_RTSP_Not_Implemented:
default:
return "Not Implemented";
}
}
#endif