⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rtsp_util.c

📁 嵌入式系统中c程序实现了rtsp协议的基本内容
💻 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_util.c - mixture of various utilities needed for rtsp client
 */
/*#include "stddefs.h"
#if ((defined ST_7109 || defined ST_7100 )&& defined ST_OSLINUX)
#include "compat.h"
#endif*/
#include "rtsp_private.h"


/*
 * Ugh - a global variable for the loglevel.
 * We probably want to enhance this to pass a function vector as well.
 */



/*
 * rtsp_debug()
 * Display rtsp debug information.  Probably want to hook this into
 * a rtsp_client, and enhance it to do file, console, and user routine
 * output.
 */

void free_session_info (rtsp_session_t *session)
{
  CHECK_AND_FREE(session->session,__LINE__,__FILE__);
  CHECK_AND_FREE(session->url,__LINE__,__FILE__);
 Rtsp_Free(session,__LINE__,__FILE__);
}

/*
 * clear_decode_response()
 * Frees memory associated with that structure and clears it.
 */
void clear_decode_response (rtsp_decode_t *resp)
{
  CHECK_AND_FREE(resp->retresp,__LINE__,__FILE__);
  CHECK_AND_FREE(resp->body,__LINE__,__FILE__);
  CHECK_AND_FREE(resp->accept,__LINE__,__FILE__);
  CHECK_AND_FREE(resp->accept_encoding,__LINE__,__FILE__);
  CHECK_AND_FREE(resp->accept_language,__LINE__,__FILE__);
  CHECK_AND_FREE(resp->allow_public,__LINE__,__FILE__);
  CHECK_AND_FREE(resp->authorization,__LINE__,__FILE__);
  CHECK_AND_FREE(resp->bandwidth,__LINE__,__FILE__);
  CHECK_AND_FREE(resp->blocksize,__LINE__,__FILE__);
  CHECK_AND_FREE(resp->cache_control,__LINE__,__FILE__);
  CHECK_AND_FREE(resp->content_base,__LINE__,__FILE__);
  CHECK_AND_FREE(resp->content_encoding,__LINE__,__FILE__);
  CHECK_AND_FREE(resp->content_language,__LINE__,__FILE__);
  CHECK_AND_FREE(resp->content_location,__LINE__,__FILE__);
  CHECK_AND_FREE(resp->content_type,__LINE__,__FILE__);
  CHECK_AND_FREE(resp->cookie,__LINE__,__FILE__);
  CHECK_AND_FREE(resp->date,__LINE__,__FILE__);
  CHECK_AND_FREE(resp->expires,__LINE__,__FILE__);
  CHECK_AND_FREE(resp->from,__LINE__,__FILE__);
  CHECK_AND_FREE(resp->if_modified_since,__LINE__,__FILE__);
  CHECK_AND_FREE(resp->last_modified,__LINE__,__FILE__);
  CHECK_AND_FREE(resp->location,__LINE__,__FILE__);
  CHECK_AND_FREE(resp->proxy_authenticate,__LINE__,__FILE__);
  CHECK_AND_FREE(resp->proxy_require,__LINE__,__FILE__);
  CHECK_AND_FREE(resp->range,__LINE__,__FILE__);
  CHECK_AND_FREE(resp->referer,__LINE__,__FILE__);
  CHECK_AND_FREE(resp->require,__LINE__,__FILE__);
  CHECK_AND_FREE(resp->retry_after,__LINE__,__FILE__);
  CHECK_AND_FREE(resp->rtp_info,__LINE__,__FILE__);
  CHECK_AND_FREE(resp->scale,__LINE__,__FILE__);
  CHECK_AND_FREE(resp->server,__LINE__,__FILE__);
  CHECK_AND_FREE(resp->session,__LINE__,__FILE__);
  CHECK_AND_FREE(resp->speed,__LINE__,__FILE__);
  CHECK_AND_FREE(resp->transport,__LINE__,__FILE__);
  CHECK_AND_FREE(resp->unsupported,__LINE__,__FILE__);
  CHECK_AND_FREE(resp->user_agent,__LINE__,__FILE__);
  CHECK_AND_FREE(resp->via,__LINE__,__FILE__);
  CHECK_AND_FREE(resp->www_authenticate,__LINE__,__FILE__);
  resp->content_length = 0;
  resp->cseq = 0;
  resp->close_connection = FALSE;
}

/*
 * free_decode_response()
 * frees memory associated with response, along with response.
 */
void free_decode_response (rtsp_decode_t *decode)
{
  if (decode != NULL) {
    clear_decode_response(decode);
   Rtsp_Free(decode,__LINE__,__FILE__);
  }
}


/*
 * rtsp_set_and_decode_url()
 * will decode the url, make sure it matches RTSP url information,
 * pulls out the server name and port, then gets the server address
 */
int rtsp_dissect_url (rtsp_client_t *rptr, const char *url)
{
  const char *uptr;
  const char *nextslash, *nextcolon, *rightbracket;
  int hostlen;

  if (rptr->url != NULL || rptr->server_name != NULL) {
    return (-1);
  }

  uptr = url;
  rptr->url = strdup(url);
  if (strncmp("rtsp://", url, strlen("rtsp://")) == 0) {
    rptr->useTCP = TRUE;
    uptr += strlen("rtsp://");
#if 0
  } else if (strncmp("rtspu://", url, strlen("rtspu:")) == 0) {
    uptr += strlen("rtspu://");
#endif
  } else {
    return(-1);
  }

  rptr->port = 554;
  rightbracket = NULL;
  if (*uptr == '[') {
    uptr++; /* don't include the '['*/
    rightbracket = strchr(uptr, ']');
    if (rightbracket != NULL) {
      /* literal IPv6 address*/
      if (rightbracket[1] == ':') {
	nextcolon = rightbracket + 1;
      } else
	nextcolon = NULL;
      nextslash = strchr(rightbracket, '/');
    } else {
      return (ST_ERROR_BAD_PARAMETER);
    }
  } else {
  nextslash = strchr(uptr, '/');
  nextcolon = strchr(uptr, ':');
  }

  if (nextslash != NULL || nextcolon != NULL) {
    if (nextcolon != NULL &&
	(nextcolon < nextslash || nextslash == NULL)) {
      hostlen = nextcolon - uptr;
      /* have a port number*/
      nextcolon++;
      rptr->port = 0;
      while (isdigit(*nextcolon)) {
	rptr->port *= 10;
	rptr->port += *nextcolon - '0';
	nextcolon++;
      }
      if (rptr->port == 0 || (*nextcolon != '/' && *nextcolon != '\0')) {
	return (ST_ERROR_BAD_PARAMETER);
      }
    } else {
      /* no port number*/
      hostlen = nextslash - uptr;
	
    }
    if (rightbracket != NULL) {
       hostlen--;
    }
    if (hostlen == 0) {
      return (ST_ERROR_BAD_PARAMETER);
    }
    rptr->server_name = Rtsp_Malloc(hostlen + 1,__LINE__,__FILE__);
    if (rptr->server_name == NULL) {
      return (ST_ERROR_NO_MEMORY);
    }
    memcpy(rptr->server_name, uptr, hostlen);
    rptr->server_name[hostlen] = '\0';
  } else {
    if (*uptr == '\0') {
      return (ST_ERROR_BAD_PARAMETER);
    }
    rptr->server_name =strdup(uptr);
    if (rptr->server_name == NULL) {
      return (ST_ERROR_NO_MEMORY);
    }
    if (rightbracket != NULL) {
      rptr->server_name[strlen(rptr->server_name) - 1] = '\0';
    }
  }

  return (0);
}

/*
 * rtsp_setup_redirect()
 * Sets up URLs, does the connect for redirects.  Need to handle
 * 300 case (multiple choices).  Imagine that if we had that, we'd just
 * loop through the body until we found a server that we could connect
 * with.
 */
int rtsp_setup_redirect (rtsp_client_t *info)
{
  rtsp_decode_t *decode;
  int ret;
  if (info->decode_response == NULL)
    return (-1);

  info->redirect_count++;
  if (info->redirect_count > 5) 
    return (-1);

  decode = info->decode_response;
  if (decode->location == NULL)
    return (-1);
  
  if (info->orig_url == NULL) {
    info->orig_url = info->url;
    info->url = NULL;
  } else {
    CHECK_AND_FREE(info->url,__LINE__,__FILE__);
  }

  CHECK_AND_FREE(info->server_name,__LINE__,__FILE__);
  rtsp_close_socket(info);

  ret = rtsp_dissect_url(info, decode->location);
  if (ret != 0) return (ret);
  
  return (rtsp_create_socket(info));

}

/* return last occurrence of needle in haystack */
static const char *my_strrstr (const char *haystack, const char *needle)
{
   int needle_len = strlen(needle);
   int haystack_len = strlen(haystack);

   haystack_len -= needle_len;
   while (haystack_len >= 0) {
     if (strncmp(haystack + haystack_len, needle, needle_len) == 0) {
        return (haystack + haystack_len);
     }
     haystack_len--;
   }
   return (NULL);
}

/* 
 * removes the overlap between the base_url and the control_string
 * the base_url will never contain /trackID= x, so remove it
 * Example: rm_rtsp_overlap("rtsp://www.blah.com/foo", "foo/trackId=2")
 *          will return "rtsp://www.blah.com/foo/trackId=2"
 */
static char *rm_rtsp_overlap (const char *control_string, const char *base_url)
{
  char *str = NULL;
  uint32_t cblen = 0; 
  char *file_ptr = strrchr(control_string, '/'); 

  if (file_ptr != NULL && file_ptr != control_string) {
    char *path = NULL;
    char *last_path_in_base = NULL;
	uint32_t control_len = strlen(control_string);
	uint32_t file_len = strlen(file_ptr);
	uint32_t last_path_len = 0;

    /* path will contain control str without /trackID = x at the end */
    path = (char *)Rtsp_Malloc(control_len - file_len + 1,__LINE__,__FILE__);
    if (path == NULL) 
      exit(EXIT_FAILURE);
    strncpy (path, control_string, control_len - file_len);
    path[control_len - file_len] = '\0';

    last_path_in_base = strdup(my_strrstr(base_url, path));
	if (last_path_in_base != NULL) 
	  last_path_len = strlen(last_path_in_base);
    if (last_path_in_base == NULL 
		|| last_path_len != strlen(path)) {
	  /* couldn't find path in base url or isn't at end of base url */
     Rtsp_Free(path,__LINE__,__FILE__);
	 Rtsp_Free(last_path_in_base,__LINE__,__FILE__);
      return ((char *)NULL);
    } 
	else {
	  /* make sure there is one and only one '/' between the base url
       * and the control string */
      cblen = strlen(base_url) - last_path_len;
      if (*control_string != '/') {
        cblen +=1;
      }
      str = (char *)Rtsp_Malloc(cblen + control_len +1,__LINE__,__FILE__);
      if (str == NULL) 
        exit(EXIT_FAILURE);
      /* copy base_url up to last occurrence of path */
      strncpy(str, base_url, cblen);
      str[cblen] = '\0';
      strcat(str, control_string);
     Rtsp_Free(path,__LINE__,__FILE__);
    }
	Rtsp_Free(last_path_in_base,__LINE__,__FILE__);
  }
  return ((char *)str);
}


/* 
 * attempts to match the session url with  
 * content_base/url or session_name/url
 * if content base and url overlap, or if session_name and 
 * url overlap, remove the overlap and attempt to match again
 * return 1 if matched, 0 otherwise
 */
int rtsp_is_url_my_stream (rtsp_session_t *session,
			   const char *url,
			   const char *content_base,
			   const char *session_name)
{ 
  char *session_url = session->url;
  const char *end;
  int is_match = 0;

  end = my_strrstr(session_url, url); 
  if (end != NULL  || strcmp(url,"*") == 0) {
    if (strncmp(session_url, content_base,
		strlen(session_url) - strlen(end)) == 0
	|| strncmp(session_url, session_name, 
		   strlen(session_url) - strlen(end)) == 0) {
      is_match = 1;
    }
    else {
      /* url isn't contained in the session_url */
      /* check if there is an overlap */
      char *str1 = rm_rtsp_overlap(url, content_base);
      char *str2 = rm_rtsp_overlap(url, session_name);
      if (strcmp(session_url, str1) == 0 
	  || strcmp(session_url, str2) == 0)  
	is_match = 1;
     Rtsp_Free(str1,__LINE__,__FILE__);
     Rtsp_Free(str2,__LINE__,__FILE__);
    }
  }
  return (is_match);
}

struct in_addr get_server_ip_address (rtsp_session_t *session)
{
  return session->parent->server_addr;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -