📄 rtsp_command.c
字号:
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is MPEG4IP.
*
* The Initial Developer of the Original Code is Cisco Systems Inc.
* Portions created by Cisco Systems Inc. are
* Copyright (C) Cisco Systems Inc. 2000, 2001. All Rights Reserved.
*
* Contributor(s):
* Bill May wmay@cisco.com
*/
/*
* rtsp_command.c - process API calls to send/receive rtsp commands
*/
#include <string.h>
#include "rtsp_private.h"
#include "sdp.h"
#include "rtsp_client.h"
static const char *UserAgent = "STMicroelectronics RTSP 1.0";
char* strdup(const char* buf)
{
char *tembuf=NULL;
int len;
len=strlen(buf)+1;
tembuf= Rtsp_Malloc(len,__LINE__,__FILE__);
memset(tembuf,0x00,len);
memcpy(tembuf,buf,len-1);
return tembuf;
}
/*
* rtsp_build_common()
* Builds a common header based on rtsp_command_t information.
*/
static int rtsp_build_common (char *buffer,
uint32_t maxlen,
uint32_t *at,
rtsp_client_t *info,
rtsp_command_t *cmd,
const char *session)
{
int ret;
/*
* The below is ugly, but it will allow us to remove a lot of lines
* of code. SNPRINTF_CHECK makes sure (for this routine), that we
* don't have more data in the buffer than allowed - it will return
* an error code if that happens.
*/
#define SNPRINTF_CHECK(fmt, value) \
ret = snprintf(buffer + *at, maxlen - *at, (fmt), (value)); \
if (ret == -1) { \
return (-1); \
}\
*at += ret;
SNPRINTF_CHECK("CSeq: %u\r\n", info->next_cseq);
if (info->cookie) {
SNPRINTF_CHECK("Cookie: %s\r\n", info->cookie);
}
if (cmd && cmd->accept) {
SNPRINTF_CHECK("Accept: %s\r\n", cmd->accept);
}
if (cmd && cmd->accept_encoding) {
SNPRINTF_CHECK("Accept-Encoding: %s\r\n", cmd->accept_encoding);
}
if (cmd && cmd->accept_language) {
SNPRINTF_CHECK("Accept-Language: %s\r\n", cmd->accept_language);
}
if (cmd && cmd->authorization) {
SNPRINTF_CHECK("Authorization: %s\r\n", cmd->authorization);
}
if (cmd && cmd->bandwidth != 0) {
SNPRINTF_CHECK("Bandwidth: %u\r\n", cmd->bandwidth);
}
if (cmd && cmd->blocksize != 0) {
SNPRINTF_CHECK("Blocksize: %u\r\n", cmd->blocksize);
}
if (cmd && cmd->cachecontrol) {
SNPRINTF_CHECK("Cache-Control: %s\r\n", cmd->cachecontrol);
}
if (cmd && cmd->conference) {
SNPRINTF_CHECK("Conference: %s\r\n", cmd->conference);
}
if (cmd && cmd->from) {
SNPRINTF_CHECK("From: %s\r\n", cmd->from);
}
if (cmd && cmd->proxyauth) {
SNPRINTF_CHECK("Proxy-Authorization: %s\r\n", cmd->proxyauth);
}
if (cmd && cmd->proxyrequire) {
SNPRINTF_CHECK("Proxy-Require: %s\r\n", cmd->proxyrequire);
}
if (cmd && cmd->range) {
SNPRINTF_CHECK("Range: %s\r\n", cmd->range);
}
if (cmd && cmd->referer) {
SNPRINTF_CHECK("Referer: %s\r\n", cmd->referer);
}
if (cmd && cmd->scale != 0.0) {
SNPRINTF_CHECK("Scale: %g\r\n", cmd->scale);
}
if (session) {
SNPRINTF_CHECK("Session: %s\r\n", session);
} else if (cmd && cmd->session) {
SNPRINTF_CHECK("Session: %s\r\n", cmd->session);
}
if (cmd && cmd->speed != 0.0) {
SNPRINTF_CHECK("Speed: %g\r\n", cmd->speed);
}
if (cmd && cmd->transport) {
SNPRINTF_CHECK("Transport: %s\r\n", cmd->transport);
}
SNPRINTF_CHECK("User-Agent: %s\r\n",
(cmd && cmd->useragent != NULL ? cmd->useragent : UserAgent));
if (cmd && cmd->User) {
SNPRINTF_CHECK("%s", cmd->User);
}
#undef SNPRINTF_CHECK
return (0);
}
/*
* rtsp_send_describe - send the describe info to a server
*/
int rtsp_send_describe (rtsp_client_t *info,
rtsp_command_t *cmd,
rtsp_decode_t **decode_result)
{
char buffer[2048];
uint32_t maxlen, buflen;
int ret;
rtsp_decode_t *decode;
*decode_result = NULL;
info->redirect_count = 0;
do {
maxlen = sizeof(buffer);
buflen = snprintf(buffer, maxlen, "DESCRIBE %s RTSP/1.0\r\n", info->url);
if (rtsp_build_common(buffer, maxlen, &buflen, info, cmd, NULL) == -1) {
Rtsp_Printf("rtsp_build_common error!\n");
return (RTSP_RESPONSE_RECV_ERROR);
}
ret = snprintf(buffer + buflen, maxlen - buflen, "\r\n");
if (ret == -1) {
return (RTSP_RESPONSE_RECV_ERROR);
}
buflen += ret;
Rtsp_Printf( "Sending DESCRIBE %s\n", info->url);
// Rtsp_Printf( buffer);
ret = rtsp_send_and_get(info, buffer, buflen);
Rtsp_Printf("ret = %d\n",ret);
decode = info->decode_response;
if (ret == RTSP_RESPONSE_GOOD)
{
Rtsp_Printf( "DESCRIBE returned correctly\n");
*decode_result = info->decode_response;
info->decode_response = NULL;
return (RTSP_RESPONSE_GOOD);
}
else if (ret != RTSP_RESPONSE_REDIRECT)
{
Rtsp_Printf( "DESCRIBE return code %d\n", ret);
if (ret != RTSP_RESPONSE_RECV_ERROR &&
decode != NULL) {
*decode_result = info->decode_response;
info->decode_response = NULL;
Rtsp_Printf( "Error code %s %s\n",
decode->retcode,
decode->retresp);
}
return (ret);
}
/*
* Handle this through the redirects
*/
} while (ret == RTSP_RESPONSE_REDIRECT);
return (RTSP_RESPONSE_RECV_ERROR);
}
/*
* rtsp_send_setup - When we get the describe, this will set up a
* particular stream. Use the session handle for all further commands for
* the stream (play, pause, teardown).
*/
int rtsp_send_setup (rtsp_client_t *info,
const char *url,
rtsp_command_t *cmd,
rtsp_session_t **session_result,
rtsp_decode_t **decode_result,
int is_aggregate)
{
char buffer[2048], *temp;
uint32_t maxlen, buflen;
int ret;
rtsp_decode_t *decode;
rtsp_session_t *sptr;
*decode_result = NULL;
*session_result = NULL;
info->redirect_count = 0;
if (cmd == NULL || cmd->transport == NULL) {
return (RTSP_RESPONSE_MISSING_OR_BAD_PARAM);
}
if (strncmp(url, "rtsp://", strlen("rtsp://")) != 0) {
return (RTSP_RESPONSE_BAD_URL);
}
temp = strchr(url + strlen("rtsp://"), '/');
if (temp == NULL) {
return (RTSP_RESPONSE_BAD_URL);
}
if (strncmp(url, info->url, temp - url) != 0) {
Rtsp_Printf( "Bad url %s\n", url);
Rtsp_Printf( "Should be %s\n", info->url);
return (RTSP_RESPONSE_BAD_URL);
}
maxlen = sizeof(buffer);
buflen = snprintf(buffer, maxlen, "SETUP %s RTSP/1.0\r\n", url);
if (rtsp_build_common(buffer,
maxlen,
&buflen,
info,
cmd,
is_aggregate ? info->session : NULL) == -1) {
return (RTSP_RESPONSE_RECV_ERROR);
}
ret = snprintf(buffer + buflen, maxlen - buflen, "\r\n");
if (ret == -1) {
return (RTSP_RESPONSE_RECV_ERROR);
}
buflen += ret;
/* Rtsp_Printf( "Sending SETUP %s\n", url);
Rtsp_Printf( buffer);
*/
ret = rtsp_send_and_get(info, buffer, buflen);
decode = info->decode_response;
if (ret == RTSP_RESPONSE_GOOD) {
/* Rtsp_Printf( "SETUP returned correctly\n");
*/
*decode_result = info->decode_response;
info->decode_response = NULL;
#ifndef IPTV_COMPATIBLE
if ((*decode_result)->session == NULL) {
return (RTSP_RESPONSE_BAD);
}
#endif
temp=strchr((*decode_result)->session,';');
if(temp!=NULL)
{
int i=0;
char *c=NULL;
while ((*decode_result)->session[i]!=';'&& (*decode_result)->session[i]!='\0') i++;
c = (char *)Rtsp_Malloc(i+1,__LINE__,__FILE__);
strncpy(c,(*decode_result)->session,i);
c[i]='\0';
Rtsp_Free((*decode_result)->session,__LINE__,__FILE__);
(*decode_result)->session=c;
}
if (is_aggregate && info->session != NULL) {
if (strcmp(info->session, (*decode_result)->session) != 0) {
/* Rtsp_Printf( "Session for %s returned different %s %s\n",
url, info->session, (*decode_result)->session);
*/
return (RTSP_RESPONSE_BAD);
}
}
sptr = info->session_list;
while (sptr != NULL) {
if (strcmp(sptr->url, url) == 0)
break;
sptr = sptr->next;
}
if (sptr == NULL) {
sptr = (rtsp_session_t*)Rtsp_Malloc(sizeof(rtsp_session_t),__LINE__,__FILE__);
if (sptr == NULL) {
return (RTSP_RESPONSE_RECV_ERROR);
}
sptr->url = strdup( url);
if ((*decode_result)->session != NULL)
sptr->session =strdup((*decode_result)->session);
else
sptr->session = NULL;
sptr->parent = info;
sptr->next = info->session_list;
info->session_list = sptr;
if (is_aggregate && info->session == NULL)
info->session = sptr->session;
}
*session_result = sptr;
return (RTSP_RESPONSE_GOOD);
} else {
/* Rtsp_Printf( "SETUP return code %d\n", ret);
*/
if (ret != RTSP_RESPONSE_RECV_ERROR &&
decode != NULL) {
*decode_result = info->decode_response;
info->decode_response = NULL;
Rtsp_Printf( "Error code %s %s\n",
decode->retcode,
decode->retresp);
}
return (ret);
}
return (RTSP_RESPONSE_RECV_ERROR);
}
/*
* check_session - make sure that the session is correct for that command
*/
static int check_session (rtsp_session_t *session,
rtsp_command_t *cmd)
{
rtsp_session_t *sptr;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -