rtsp_command.c
资源名称:NETVIDEO.rar [点击查看]
上传用户:sun1608
上传日期:2007-02-02
资源大小:6116k
文件大小:15k
源码类别:
流媒体/Mpeg4/MP4
开发平台:
Visual 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 "rtsp_private.h"
- static const char *UserAgent = "Cisco RTSP 1.0";
- /*
- * 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: %urn", info->next_cseq);
- if (info->cookie) {
- SNPRINTF_CHECK("Cookie: %srn", info->cookie);
- }
- if (cmd && cmd->accept) {
- SNPRINTF_CHECK("Accept: %srn", cmd->accept);
- }
- if (cmd && cmd->accept_encoding) {
- SNPRINTF_CHECK("Accept-Encoding: %srn", cmd->accept_encoding);
- }
- if (cmd && cmd->accept_language) {
- SNPRINTF_CHECK("Accept-Language: %srn", cmd->accept_language);
- }
- if (cmd && cmd->authorization) {
- SNPRINTF_CHECK("Authorization: %srn", cmd->authorization);
- }
- if (cmd && cmd->bandwidth != 0) {
- SNPRINTF_CHECK("Bandwidth: %urn", cmd->bandwidth);
- }
- if (cmd && cmd->blocksize != 0) {
- SNPRINTF_CHECK("Blocksize: %urn", cmd->blocksize);
- }
- if (cmd && cmd->cachecontrol) {
- SNPRINTF_CHECK("Cache-Control: %srn", cmd->cachecontrol);
- }
- if (cmd && cmd->conference) {
- SNPRINTF_CHECK("Conference: %srn", cmd->conference);
- }
- if (cmd && cmd->from) {
- SNPRINTF_CHECK("From: %srn", cmd->from);
- }
- if (cmd && cmd->proxyauth) {
- SNPRINTF_CHECK("Proxy-Authorization: %srn", cmd->proxyauth);
- }
- if (cmd && cmd->proxyrequire) {
- SNPRINTF_CHECK("Proxy-Require: %srn", cmd->proxyrequire);
- }
- if (cmd && cmd->range) {
- SNPRINTF_CHECK("Range: %srn", cmd->range);
- }
- if (cmd && cmd->referer) {
- SNPRINTF_CHECK("Referer: %srn", cmd->referer);
- }
- if (cmd && cmd->scale != 0.0) {
- SNPRINTF_CHECK("Scale: %grn", cmd->scale);
- }
- if (session) {
- SNPRINTF_CHECK("Session: %srn", session);
- } else if (cmd && cmd->session) {
- SNPRINTF_CHECK("Session: %srn", cmd->session);
- }
- if (cmd && cmd->speed != 0.0) {
- SNPRINTF_CHECK("Speed: %grn", cmd->speed);
- }
- if (cmd && cmd->transport) {
- SNPRINTF_CHECK("Transport: %srn", cmd->transport);
- }
- SNPRINTF_CHECK("User-Agent: %srn",
- (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.0rn", info->url);
- if (rtsp_build_common(buffer, maxlen, &buflen, info, cmd, NULL) == -1) {
- return (RTSP_RESPONSE_RECV_ERROR);
- }
- ret = snprintf(buffer + buflen, maxlen - buflen, "rn");
- if (ret == -1) {
- return (RTSP_RESPONSE_RECV_ERROR);
- }
- buflen += ret;
- rtsp_debug(LOG_INFO, "Sending DESCRIBE %s", info->url);
- rtsp_debug(LOG_DEBUG, buffer);
- ret = rtsp_send_and_get(info, buffer, buflen);
- decode = info->decode_response;
- if (ret == RTSP_RESPONSE_GOOD) {
- rtsp_debug(LOG_INFO, "DESCRIBE returned correctly");
- *decode_result = info->decode_response;
- info->decode_response = NULL;
- return (RTSP_RESPONSE_GOOD);
- } else if (ret != RTSP_RESPONSE_REDIRECT) {
- rtsp_debug(LOG_ERR, "DESCRIBE return code %d", ret);
- if (ret != RTSP_RESPONSE_RECV_ERROR &&
- decode != NULL) {
- *decode_result = info->decode_response;
- info->decode_response = NULL;
- rtsp_debug(LOG_ERR, "Error code %s %s",
- 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_debug(LOG_ALERT, "Bad url %s", url);
- rtsp_debug(LOG_ALERT, "Should be %s", info->url);
- return (RTSP_RESPONSE_BAD_URL);
- }
- maxlen = sizeof(buffer);
- buflen = snprintf(buffer, maxlen, "SETUP %s RTSP/1.0rn", 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, "rn");
- if (ret == -1) {
- return (RTSP_RESPONSE_RECV_ERROR);
- }
- buflen += ret;
- rtsp_debug(LOG_INFO, "Sending SETUP %s", url);
- rtsp_debug(LOG_DEBUG, buffer);
- ret = rtsp_send_and_get(info, buffer, buflen);
- decode = info->decode_response;
- if (ret == RTSP_RESPONSE_GOOD) {
- rtsp_debug(LOG_INFO, "SETUP returned correctly");
- *decode_result = info->decode_response;
- info->decode_response = NULL;
- #ifndef IPTV_COMPATIBLE
- if ((*decode_result)->session == NULL) {
- return (RTSP_RESPONSE_BAD);
- }
- #endif
- if (is_aggregate && info->session != NULL) {
- if (strcmp(info->session, (*decode_result)->session) != 0) {
- rtsp_debug(LOG_ALERT, "Session for %s returned different %s %s",
- 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 = malloc(sizeof(rtsp_session_t));
- 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_debug(LOG_ERR, "SETUP return code %d", ret);
- if (ret != RTSP_RESPONSE_RECV_ERROR &&
- decode != NULL) {
- *decode_result = info->decode_response;
- info->decode_response = NULL;
- rtsp_debug(LOG_ERR, "Error code %s %s",
- 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;
- rtsp_client_t *info;
- info = session->parent;
- if (info == NULL) {
- rtsp_debug(LOG_ALERT, "Session doesn't point to parent");
- return (FALSE);
- }
- sptr = info->session_list;
- while (sptr != session && sptr != NULL) sptr = sptr->next;
- if (sptr == NULL) {
- rtsp_debug(LOG_ALERT, "session not found in info list");
- return (FALSE);
- }
- if ((cmd != NULL) &&
- (cmd->session != NULL) &&
- (strcmp(cmd->session, session->session) != 0)) {
- rtsp_debug(LOG_ALERT, "Have cmd->session set wrong");
- return (FALSE);
- }
- return (TRUE);
- }
- static int rtsp_send_play_or_pause (const char *command,
- const char *url,
- const char *session,
- 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;
- if (info->server_socket < 0) {
- return (RTSP_RESPONSE_CLOSED_SOCKET);
- }
- maxlen = sizeof(buffer);
- buflen = snprintf(buffer, maxlen, "%s %s RTSP/1.0rn", command, url);
- if (rtsp_build_common(buffer, maxlen, &buflen,
- info, cmd, session) == -1) {
- return (RTSP_RESPONSE_RECV_ERROR);
- }
- ret = snprintf(buffer + buflen, maxlen - buflen, "rn");
- if (ret == -1) {
- return (RTSP_RESPONSE_RECV_ERROR);
- }
- buflen += ret;
- rtsp_debug(LOG_INFO, "Sending %s %s", command, url);
- rtsp_debug(LOG_DEBUG, buffer);
- ret = rtsp_send_and_get(info, buffer, buflen);
- decode = info->decode_response;
- if (ret == RTSP_RESPONSE_GOOD) {
- rtsp_debug(LOG_ERR, "%s returned correctly", command);
- *decode_result = info->decode_response;
- info->decode_response = NULL;
- return (RTSP_RESPONSE_GOOD);
- } else {
- rtsp_debug(LOG_ERR, "%s return code %d", command, ret);
- if (ret != RTSP_RESPONSE_RECV_ERROR &&
- decode != NULL) {
- *decode_result = info->decode_response;
- info->decode_response = NULL;
- rtsp_debug(LOG_ERR, "Error code %s %s",
- decode->retcode,
- decode->retresp);
- }
- return (ret);
- }
- return (RTSP_RESPONSE_RECV_ERROR);
- }
- /*
- * rtsp_send_play - send play command. It helps if Range is set
- */
- int rtsp_send_play (rtsp_session_t *session,
- rtsp_command_t *cmd,
- rtsp_decode_t **decode_result)
- {
- if (check_session(session, cmd) == FALSE) {
- return (RTSP_RESPONSE_MISSING_OR_BAD_PARAM);
- }
- return (rtsp_send_play_or_pause("PLAY",
- session->url,
- session->session,
- session->parent,
- cmd,
- decode_result));
- }
- /*
- * rtsp_send_pause - send a pause on a particular session
- */
- int rtsp_send_pause (rtsp_session_t *session,
- rtsp_command_t *cmd,
- rtsp_decode_t **decode_result)
- {
- if (check_session(session, cmd) == FALSE) {
- return (RTSP_RESPONSE_MISSING_OR_BAD_PARAM);
- }
- return (rtsp_send_play_or_pause("PAUSE",
- session->url,
- session->session,
- session->parent,
- cmd,
- decode_result));
- }
- int rtsp_send_aggregate_play (rtsp_client_t *info,
- const char *aggregate_url,
- rtsp_command_t *cmd,
- rtsp_decode_t **decode_result)
- {
- return (rtsp_send_play_or_pause("PLAY",
- aggregate_url,
- info->session,
- info,
- cmd,
- decode_result));
- }
- int rtsp_send_aggregate_pause (rtsp_client_t *info,
- const char *aggregate_url,
- rtsp_command_t *cmd,
- rtsp_decode_t **decode_result)
- {
- return (rtsp_send_play_or_pause("PAUSE",
- aggregate_url,
- info->session,
- info,
- cmd,
- decode_result));
- }
- static int rtsp_send_teardown_common (rtsp_client_t *info,
- const char *url,
- const char *session,
- 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;
- if (info->server_socket < 0) {
- return (RTSP_RESPONSE_CLOSED_SOCKET);
- }
- maxlen = sizeof(buffer);
- buflen = snprintf(buffer, maxlen, "TEARDOWN %s RTSP/1.0rn", url);
- if (rtsp_build_common(buffer, maxlen, &buflen,
- info, cmd, session) == -1) {
- return (RTSP_RESPONSE_RECV_ERROR);
- }
- ret = snprintf(buffer + buflen, maxlen - buflen, "rn");
- if (ret == -1) {
- return (RTSP_RESPONSE_RECV_ERROR);
- }
- buflen += ret;
- rtsp_debug(LOG_INFO, "Sending TEARDOWN %s", url);
- rtsp_debug(LOG_DEBUG, buffer);
- ret = rtsp_send_and_get(info, buffer, buflen);
- decode = info->decode_response;
- if (ret == RTSP_RESPONSE_GOOD) {
- rtsp_debug(LOG_INFO, "TEARDOWN returned correctly");
- *decode_result = info->decode_response;
- info->decode_response = NULL;
- return (RTSP_RESPONSE_GOOD);
- } else {
- rtsp_debug(LOG_ERR, "TEARDOWN return code %d", ret);
- if (ret != RTSP_RESPONSE_RECV_ERROR &&
- decode != NULL) {
- *decode_result = info->decode_response;
- info->decode_response = NULL;
- rtsp_debug(LOG_ERR, "Error code %s %s",
- decode->retcode,
- decode->retresp);
- }
- return (ret);
- }
- return (RTSP_RESPONSE_RECV_ERROR);
- }
- /*
- * rtsp_send_teardown. Sends a teardown for a session. We might eventually
- * want to provide a teardown for the base url, rather than one for each
- * session
- */
- int rtsp_send_teardown (rtsp_session_t *session,
- rtsp_command_t *cmd,
- rtsp_decode_t **decode_result)
- {
- int ret;
- rtsp_client_t *info;
- rtsp_session_t *sptr;
- if (check_session(session, cmd) == FALSE) {
- return (RTSP_RESPONSE_MISSING_OR_BAD_PARAM);
- }
- info = session->parent;
- ret = rtsp_send_teardown_common(info,
- session->url,
- session->session,
- cmd,
- decode_result);
- if (ret == RTSP_RESPONSE_GOOD) {
- if (info->session_list == session) {
- info->session_list = session->next;
- } else {
- sptr = info->session_list;
- while (sptr->next != session) sptr = sptr->next;
- sptr->next = session->next;
- }
- free_session_info(session);
- }
- return (ret);
- }
- int rtsp_send_aggregate_teardown (rtsp_client_t *info,
- const char *url,
- rtsp_command_t *cmd,
- rtsp_decode_t **decode_result)
- {
- int ret;
- rtsp_session_t *p;
- ret = rtsp_send_teardown_common(info,
- url,
- info->session,
- cmd,
- decode_result);
- if (ret == RTSP_RESPONSE_GOOD) {
- while (info->session_list != NULL) {
- p = info->session_list;
- info->session_list = info->session_list->next;
- free_session_info(p);
- }
- }
- return (ret);
- }