📄 rtsp_util.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 + -