333 lines
10 KiB
C
Executable File
333 lines
10 KiB
C
Executable File
/*
|
|
* Copyright (c) XCAM. All rights reserved.
|
|
*/
|
|
|
|
#include <string.h>
|
|
|
|
#include "livestream_comm.h"
|
|
#include "xcam_livestream_rtsp_server.h"
|
|
#include "livestream_rtsp_message.h"
|
|
|
|
#ifdef __cplusplus
|
|
#if __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
#endif /* __cplusplus */
|
|
|
|
#define RTSP_INVALID_STATUS_STR "Invalid Status"
|
|
#define RTSP_INVALID_STATUS_CODE (-1)
|
|
|
|
typedef struct {
|
|
xcam_char* status_str;
|
|
xcam_s32 status_code;
|
|
} rtsp_msg_status;
|
|
|
|
static rtsp_msg_status g_rtsp_status[] = {
|
|
{"Continue", 100},
|
|
{"OK", 200},
|
|
{"Created", 201},
|
|
{"Accepted", 202},
|
|
{"Non-Authoritative Information", 203},
|
|
{"No Content", 204},
|
|
{"Reset Content", 205},
|
|
{"Partial Content", 206},
|
|
{"Multiple Choices", 300},
|
|
{"Moved Permanently", 301},
|
|
{"Moved Temporarily", 302},
|
|
{"Bad Request", 400},
|
|
{"Unauthorized", 401},
|
|
{"Payment Required", 402},
|
|
{"Forbidden", 403},
|
|
{"Stream Not Found", 404},
|
|
{"Method Not Allowed", 405},
|
|
{"Not Acceptable", 406},
|
|
{"Proxy Authentication Required", 407},
|
|
{"Request Time-out", 408},
|
|
{"Conflict", 409},
|
|
{"Gone", 410},
|
|
{"Length Required", 411},
|
|
{"Precondition Failed", 412},
|
|
{"Request Entity Too Large", 413},
|
|
{"Request-URI Too Large", 414},
|
|
{"Unsupported Media Type", 415},
|
|
{"Over Supported connection ", 416},
|
|
{"Bad Extension", 420},
|
|
{"Invalid Parameter", 450},
|
|
{"Parameter Not Understood", 451},
|
|
{"Conference Not Found", 452},
|
|
{"Not Enough Bandwidth", 453},
|
|
{"Session Not Found", 454},
|
|
{"Method Not Valid In This State", 455},
|
|
{"Header Field Not Valid for Resource", 456},
|
|
{"Invalid Range", 457},
|
|
{"Parameter Is Read-Only", 458},
|
|
{"Unsupported Transport", 461},
|
|
{"Internal Server Error", 500},
|
|
{"Not Implemented", 501},
|
|
{"Bad Gateway", 502},
|
|
{"Service Unavailable", 503},
|
|
{"Gateway Time-out", 504},
|
|
{"RTSP Version Not Supported", 505},
|
|
{"Option not support", 551},
|
|
{"Extended Error:", 911},
|
|
{0, RTSP_INVALID_STATUS_CODE}
|
|
};
|
|
|
|
/*response header example
|
|
RTSP/1.0 200 OK
|
|
Server: Streaming Media Server/1.0.0(Jul 30 2015)
|
|
Cseq: 1
|
|
Public: OPTIONS, DESCRIBE, SETUP, PLAY, TEARDOWN
|
|
*/
|
|
static xcam_bool msg_parser_is_response(const xcam_char* request)
|
|
{
|
|
xcam_char version[RTSP_VER_MAX_LEN] = {0};
|
|
xcam_u32 stat = 0;
|
|
xcam_s32 cnt = 0;
|
|
|
|
memset(version, '\0', sizeof(version));
|
|
cnt = sscanf(request, " %31s %d", version, &stat);
|
|
version[RTSP_VER_MAX_LEN - 1] = '\0';
|
|
if (strncasecmp(version, "RTSP/", strlen("RTSP/"))
|
|
|| cnt < RTSP_SCANF_RET_TWO || 0 == stat) {
|
|
return XCAM_FALSE; /* not a response message */
|
|
}
|
|
|
|
return XCAM_TRUE;
|
|
}
|
|
|
|
xcam_bool livestream_rtsp_message_check_request(const xcam_char* request)
|
|
{
|
|
livestream_rtsp_request_method method;
|
|
xcam_s32 ret = XCAM_SUCCESS;
|
|
|
|
/* check for request message. */
|
|
if (msg_parser_is_response(request)) {
|
|
LOG_LIVESTREAM_INFO("msg formate error, not request, just rtsp response\n");
|
|
return XCAM_FALSE;
|
|
}
|
|
|
|
/* not a response message, check for method request. */
|
|
ret = livestream_rtsp_message_parse_method(request, &method);
|
|
if (ret != XCAM_SUCCESS) {
|
|
LOG_LIVESTREAM_INFO("method=%s requested was invalid. Message discarded.\n", request);
|
|
return XCAM_FALSE;
|
|
}
|
|
|
|
return XCAM_TRUE;
|
|
}
|
|
|
|
xcam_void livestream_rtsp_message_get_response(xcam_s32 status_code, xcam_s32 cseq,
|
|
xcam_char* reply_buf, xcam_u32 buf_len)
|
|
{
|
|
xcam_char status_str[MAX_DATE_LEN] = {0};
|
|
xcam_char buffer[MAX_DATE_LEN] = {0};
|
|
int ret;
|
|
|
|
memset(status_str, '\0', sizeof(status_str));
|
|
livestream_rtsp_message_status_code_to_str(status_code, status_str, sizeof(status_str)-1);
|
|
memset(buffer, '\0', sizeof(buffer));
|
|
livestream_comm_format_date(buffer, sizeof(buffer)-1);
|
|
ret = snprintf(reply_buf, buf_len - 1,
|
|
"%s %d %s\r\n"
|
|
"CSeq: %d\r\n"
|
|
"Cache-Control: no-cache\r\n"
|
|
"Server: %s\r\n"
|
|
"%s\r\n",
|
|
RTSP_VER_STR,
|
|
status_code,
|
|
status_str,
|
|
cseq,
|
|
RTSP_SERVER_DESCRIPTION,
|
|
buffer);
|
|
if (ret < 0) {
|
|
LOG_LIVESTREAM_ERROR("string print reply_buf error\n");
|
|
return;
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
/*OPTIONS rtsp://ip:554/12 RTSP/1.0
|
|
CSeq: 1
|
|
Authorization: Basic Og==
|
|
User-Agent: Streaming Media Client/1.0.0(May 23 2016)*/
|
|
xcam_s32 livestream_rtsp_message_get_stream_name(const xcam_char* request, xcam_char* stream_name, xcam_u32 buf_len)
|
|
{
|
|
xcam_char method[RTSP_METHOD_MAX_LEN] = {0};
|
|
xcam_char url[RTSP_URL_MAX_LEN] = {0};
|
|
xcam_char* tmp_ptr = XCAM_NULL;
|
|
xcam_s32 cnt = 0;
|
|
|
|
cnt = sscanf(request, " %15s %255s", method, url);
|
|
if (cnt != RTSP_SCANF_RET_TWO) {
|
|
LOG_LIVESTREAM_ERROR("rtsp req format error\n");
|
|
return XCAM_FAILURE;
|
|
}
|
|
method[RTSP_METHOD_MAX_LEN - 1] = '\0';
|
|
url[RTSP_URL_MAX_LEN - 1] = '\0';
|
|
|
|
tmp_ptr = strcasestr(url, "rtsp://");
|
|
if (XCAM_NULL == tmp_ptr) {
|
|
LOG_LIVESTREAM_ERROR("rtsp req format error, url do not have rtsp://\n");
|
|
return XCAM_FAILURE;
|
|
}
|
|
|
|
tmp_ptr += strlen("rtsp://");
|
|
tmp_ptr = strchr(tmp_ptr, '/');
|
|
if (!tmp_ptr) {
|
|
LOG_LIVESTREAM_ERROR("rtsp req url do not have stream name\n");
|
|
return XCAM_FAILURE;
|
|
}
|
|
|
|
strncpy(stream_name, tmp_ptr + 1, buf_len - 1);
|
|
stream_name[buf_len - 1] = '\0';
|
|
return XCAM_SUCCESS;
|
|
}
|
|
|
|
xcam_s32 livestream_rtsp_message_get_cseq( const xcam_char* request, xcam_s32* ptr_cseq)
|
|
{
|
|
xcam_char* ptr_temp = XCAM_NULL;
|
|
|
|
ptr_temp = strcasestr(request, RTSP_HEADER_CSEQ);
|
|
if (XCAM_NULL == ptr_temp) {
|
|
LOG_LIVESTREAM_ERROR("there no Cseq in req str\n");
|
|
return XCAM_FAILURE;
|
|
} else {
|
|
if (sscanf(ptr_temp, "%*s %d", ptr_cseq) != RTSP_SCANF_RET_ONE) {
|
|
return XCAM_FAILURE;
|
|
}
|
|
}
|
|
|
|
return XCAM_SUCCESS;
|
|
}
|
|
|
|
xcam_s32 livestream_rtsp_message_get_session_id(const xcam_char* ptr_msg_str, xcam_char* ptr_sess_id,
|
|
xcam_u32 sess_id_size)
|
|
{
|
|
xcam_char* ptr_temp = XCAM_NULL;
|
|
|
|
if (sess_id_size == 0) {
|
|
LOG_LIVESTREAM_ERROR("sessid buf size is 0\n");
|
|
return XCAM_FAILURE;
|
|
}
|
|
|
|
/*get sessionid*/
|
|
ptr_temp = strcasestr(ptr_msg_str, RTSP_HEADER_SESSION);
|
|
if ( XCAM_NULL == ptr_temp) {
|
|
LOG_LIVESTREAM_ERROR("there no sessid in req str\n");
|
|
return XCAM_FAILURE;
|
|
} else {
|
|
if (sscanf(ptr_temp, "%*s %15s", ptr_sess_id) != RTSP_SCANF_RET_ONE) {
|
|
return XCAM_FAILURE;
|
|
}
|
|
}
|
|
ptr_sess_id[sess_id_size - 1] = '\0';
|
|
|
|
return XCAM_SUCCESS;
|
|
}
|
|
|
|
xcam_s32 livestream_rtsp_message_parse_method(const xcam_char* request,
|
|
livestream_rtsp_request_method* ptr_method)
|
|
{
|
|
xcam_char method[RTSP_METHOD_MAX_LEN] = {0};
|
|
|
|
if (RTSP_SCANF_RET_ONE != sscanf(request, "%15[^ ]", method)) {
|
|
return XCAM_FAILURE;
|
|
}
|
|
method[RTSP_METHOD_MAX_LEN - 1] = '\0';
|
|
|
|
if (0 == strncmp(method, RTSP_METHOD_DESCRIBE, strlen(RTSP_METHOD_DESCRIBE))) {
|
|
*ptr_method = LIVESTREAM_RTSP_REQ_METHOD_DISCRIBLE;
|
|
} else if (0 == strncmp(method, RTSP_METHOD_SETUP, strlen(RTSP_METHOD_SETUP))) {
|
|
*ptr_method = LIVESTREAM_RTSP_REQ_METHOD_SETUP;
|
|
} else if (0 == strncmp(method, RTSP_METHOD_PLAY, strlen(RTSP_METHOD_PLAY))) {
|
|
*ptr_method = LIVESTREAM_RTSP_REQ_METHOD_PLAY;
|
|
} else if (0 == strncmp(method, RTSP_METHOD_TEARDOWN, strlen(RTSP_METHOD_TEARDOWN))) {
|
|
*ptr_method = LIVESTREAM_RTSP_REQ_METHOD_TEARDOWN;
|
|
} else if (0 == strncmp(method, RTSP_METHOD_OPTIONS, strlen(RTSP_METHOD_OPTIONS))) {
|
|
*ptr_method = LIVESTREAM_RTSP_REQ_METHOD_OPTIONS;
|
|
} else if (0 == strncmp(method, RTSP_METHOD_PAUSE, strlen(RTSP_METHOD_PAUSE))) {
|
|
*ptr_method = LIVESTREAM_RTSP_REQ_METHOD_PAUSE;
|
|
} else if (0 == strncmp(method, RTSP_METHOD_GET_PARAMETER, strlen(RTSP_METHOD_GET_PARAMETER))) {
|
|
*ptr_method = LIVESTREAM_RTSP_REQ_METHOD_GET_PARAM;
|
|
} else {
|
|
LOG_LIVESTREAM_INFO("not supported rtsp request method maybe rtcp in tcp_itlv\n");
|
|
return XCAM_FAILURE;
|
|
}
|
|
|
|
return XCAM_SUCCESS;
|
|
}
|
|
|
|
xcam_s32 livestream_rtsp_message_status_code_to_str(xcam_s32 code, xcam_char *out_buf_status,
|
|
xcam_s32 buf_len)
|
|
{
|
|
if (out_buf_status == XCAM_NULL || buf_len <= 0) {
|
|
LOG_LIVESTREAM_ERROR("Invalid param %d.\n", code);
|
|
return XCAM_FAILURE;
|
|
}
|
|
|
|
rtsp_msg_status* ptr;
|
|
for (ptr = g_rtsp_status; ptr->status_code != RTSP_INVALID_STATUS_CODE; ptr++) {
|
|
if (ptr->status_code == code) {
|
|
strncpy(out_buf_status, ptr->status_str, buf_len);
|
|
return XCAM_SUCCESS;
|
|
}
|
|
}
|
|
|
|
LOG_LIVESTREAM_ERROR("Invalid status code %d.\n", code);
|
|
strncpy(out_buf_status, RTSP_INVALID_STATUS_STR, buf_len);
|
|
return XCAM_FAILURE;
|
|
}
|
|
|
|
xcam_u32 livestream_rtsp_message_get_aac_config(xcam_u32 sample_rate, xcam_u32 chan_num)
|
|
{
|
|
xcam_u32 config_num = LIVESTREAM_AUDIO_DOUBLECHN_CONFIGNUM_16000;
|
|
|
|
if (chan_num == RTSP_AUDIO_SINGLE_CHN) {
|
|
switch (sample_rate) {
|
|
case LIVESTREAM_AUDIO_SAMPLE_RATE_8000:
|
|
config_num = LIVESTREAM_AUDIO_SINGLECHN_CONFIGNUM_8000;
|
|
break;
|
|
case LIVESTREAM_AUDIO_SAMPLE_RATE_16000:
|
|
config_num = LIVESTREAM_AUDIO_SINGLECHN_CONFIGNUM_16000;
|
|
break;
|
|
case LIVESTREAM_AUDIO_SAMPLE_RATE_32000:
|
|
config_num = LIVESTREAM_AUDIO_SINGLECHN_CONFIGNUM_32000;
|
|
break;
|
|
case LIVESTREAM_AUDIO_SAMPLE_RATE_48000:
|
|
config_num = LIVESTREAM_AUDIO_SINGLECHN_CONFIGNUM_48000;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
} else if (chan_num == RTSP_AUDIO_DOUBLE_CHN) {
|
|
switch (sample_rate) {
|
|
case LIVESTREAM_AUDIO_SAMPLE_RATE_8000:
|
|
config_num = LIVESTREAM_AUDIO_DOUBLECHN_CONFIGNUM_8000;
|
|
break;
|
|
case LIVESTREAM_AUDIO_SAMPLE_RATE_16000:
|
|
config_num = LIVESTREAM_AUDIO_DOUBLECHN_CONFIGNUM_16000;
|
|
break;
|
|
case LIVESTREAM_AUDIO_SAMPLE_RATE_32000:
|
|
config_num = LIVESTREAM_AUDIO_DOUBLECHN_CONFIGNUM_32000;
|
|
break;
|
|
case LIVESTREAM_AUDIO_SAMPLE_RATE_48000:
|
|
config_num = LIVESTREAM_AUDIO_DOUBLECHN_CONFIGNUM_48000;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
} else {
|
|
LOG_LIVESTREAM_ERROR("Invalid audio channel %d\n", chan_num);
|
|
}
|
|
|
|
return config_num;
|
|
}
|
|
|
|
#ifdef __cplusplus
|
|
#if __cplusplus
|
|
}
|
|
#endif
|
|
#endif /* __cplusplus */
|