📄 rtsp_comm.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_comm.c - contains communication routines.
*/
#include "rtsp_private.h"
#ifdef HAVE_POLL
#include <sys/poll.h>
#endif
#if !defined(HAVE_ST_ADDRINFO) && !defined(_WIN32)
#include "addrinfo.h"
#endif
/*
* rtsp_create_socket()
* creates and connects socket to server. Requires rtsp_info_t fields
* port, server_addr, server_name be set.
* returns 0 for success, -1 for failure
*/
static int rtsp_get_server_address (rtsp_client_t *info)
{
#ifdef HAVE_IPv6
struct addrinfo hints;
char port[32];
int error;
snprintf(port, sizeof(port), "%d", info->port);
memset(&hints, 0, sizeof(hints));
hints.ai_family = PF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
error = getaddrinfo(info->server_name, port, &hints, &info->addr_info);
if (error) {
rtsp_debug(LOG_CRIT, "Can't get server address info %s - error %d",
info->server_name, h_errno);
return h_errno;
}
#else
struct hostent *host;
#if defined(_WIN32) || !defined(HAVE_INET_NTOA)
info->server_addr.s_addr = inet_addr(info->server_name);
if (info->server_addr.s_addr != INADDR_NONE) return 0;
#else
if (inet_aton(info->server_name, &info->server_addr) != 0) return 0;
#endif
host = gethostbyname(info->server_name);
if (host == NULL) {
rtsp_debug(LOG_CRIT, "Can't get server host name %s", info->server_name);
return (h_errno);
}
info->server_addr = *(struct in_addr *)host->h_addr;
#endif
return 0;
}
int rtsp_create_socket (rtsp_client_t *info)
{
#ifndef HAVE_IPv6
struct sockaddr_in sockaddr;
#endif
int result;
// Do we have a socket already - if so, go ahead
if (info->server_socket != -1) {
return (0);
}
if (info->server_name == NULL) {
rtsp_debug(LOG_CRIT, "No server name in create socket");
return (-1);
}
result = rtsp_get_server_address(info);
if (result != 0) return -1;
#ifndef _WIN32
#ifdef HAVE_IPv6
info->server_socket = socket(info->addr_info->ai_family,
info->addr_info->ai_socktype,
info->addr_info->ai_protocol);
#else
info->server_socket = socket(AF_INET, SOCK_STREAM, 0);
#endif
#else
info->server_socket = WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0, 0);
#endif
if (info->server_socket == -1) {
rtsp_debug(LOG_CRIT, "Couldn't create socket");
return (-1);
}
#ifndef HAVE_IPv6
sockaddr.sin_family = AF_INET;
sockaddr.sin_port = htons(info->port);
sockaddr.sin_addr = info->server_addr;
#endif
#ifndef _WIN32
result = connect(info->server_socket,
#ifndef HAVE_IPv6
(struct sockaddr *)&sockaddr,
sizeof(sockaddr)
#else
info->addr_info->ai_addr,
info->addr_info->ai_addrlen
#endif
);
if (result < 0)
#else
result = WSAConnect(info->server_socket,
(struct sockaddr *)&sockaddr,
sizeof(sockaddr),
NULL,
NULL,
NULL,
NULL);
if (result != 0)
#endif
{
rtsp_debug(LOG_CRIT, "Couldn't connect socket - error %s",
strerror(errno)
);
return (-1);
}
if (info->thread != NULL) {
#ifndef _WIN32
result = fcntl(info->server_socket, F_GETFL);
result = fcntl(info->server_socket, F_SETFL, result | O_NONBLOCK);
if (result < 0) {
rtsp_debug(LOG_ERR, "Couldn't create nonblocking %s",
strerror(errno)
);
}
#else
rtsp_thread_set_nonblocking(info);
#endif
}
return (0);
}
/*
* rtsp_send()
* Sends a buffer over connected socket. If socket isn't connected,
* tries that first.
* Buffer must be formatted to RTSP spec.
* Inputs:
* info - pointer to rtsp_client_t for client session
* buff - pointer to buffer
* len - length of buffer
* Outputs:
* 0 - success, -1 failure
*/
int rtsp_send (rtsp_client_t *info, const char *buff, uint32_t len)
{
int ret;
if (info->server_socket == -1) {
if (rtsp_create_socket(info) != 0)
return (-1);
}
ret = send(info->server_socket, buff, len, 0);
return (ret);
}
/*
* rtsp_receive()
* Receives a response from server with a timeout. If recv returns a
* full buffer, and the last character is not \r or \n, will make a
* bigger buffer and try to receive.
*
* Will set fields in rtsp_client_t. Relevent fields are:
* recv_buff - pointer to receive buffer (malloc'ed so we can always add
* \0 at end).
* recv_buff_len - max size of receive buffer.
* recv_buff_used - number of bytes received.
* recv_buff_parsed - used by above routine in case we got more than
* 1 response at a time.
*/
int rtsp_receive_socket (rtsp_client_t *info, char *buffer, uint32_t len,
uint32_t msec_timeout, int wait)
{
int ret;
#ifdef HAVE_POLL
struct pollfd pollit;
#else
fd_set read_set;
struct timeval timeout;
#endif
if (msec_timeout != 0 && wait != 0) {
#ifdef HAVE_POLL
pollit.fd = info->server_socket;
pollit.events = POLLIN | POLLPRI;
pollit.revents = 0;
ret = poll(&pollit, 1, msec_timeout);
#else
FD_ZERO(&read_set);
FD_SET(info->server_socket, &read_set);
timeout.tv_sec = msec_timeout / 1000;
timeout.tv_usec = (msec_timeout % 1000) * 1000;
ret = select(info->server_socket + 1, &read_set, NULL, NULL, &timeout);
#endif
if (ret <= 0) {
rtsp_debug(LOG_ERR, "Response timed out %d %d", msec_timeout, ret);
if (ret == -1) {
rtsp_debug(LOG_ERR, "Error is %s",
strerror(errno));
}
return (-1);
}
}
//rtsp_debug(LOG_DEBUG, "Calling recv");
#ifndef _WIN32
ret = recv(info->server_socket, buffer, len, 0);
#else
{
WSABUF foo;
int val;
DWORD flag = 0;
DWORD bytes;
foo.buf = buffer;
foo.len = len;
val = WSARecv(info->server_socket, &foo, 1, &bytes, &flag, NULL, NULL);
if (val != 0) {
//rtsp_debug(LOG_DEBUG, "error is %d", WSAGetLastError());
return -1;
}
ret = bytes;
//rtsp_debug(LOG_DEBUG, "recvd %d bytes", ret);
}
#endif
return (ret);
}
/*
* rtsp_close_socket
* closes the socket. Duh.
*/
void rtsp_close_socket (rtsp_client_t *info)
{
if (info->server_socket != -1)
closesocket(info->server_socket);
info->server_socket = -1;
#ifdef HAVE_ST_ADDRINFO
CHECK_AND_FREE(info,addr_info);
#endif
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -