#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <limits.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <arpa/inet.h>
#include <sys/select.h>
#include <sys/time.h>
#include <time.h>
#include <unistd.h>
#include <signal.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <netinet/in.h>
#include <pthread.h>
#include <errno.h>
#include "rtsputils.h"
#include "rtspservice.h"
#include "rtputils.h"
#include "ringfifo.h"
struct profileid_sps_pps{
char base64profileid[10];
char base64sps[524];
char base64pps[524];
};
pthread_mutex_t mut;
#define MAX_SIZE 1024*1024*200
#define SDP_EL "\r\n"
#define RTSP_RTP_AVP "RTP/AVP"
struct profileid_sps_pps psp; //存base64编码的profileid sps pps
StServPrefs stPrefs;
extern int num_conn;
int g_s32Maxfd = 0;//最大轮询id号
int g_s32DoPlay = 0;
uint32_t s_u32StartPort=RTP_DEFAULT_PORT;
uint32_t s_uPortPool[MAX_CONNECTION];//RTP端口
extern int stop_schedule;
int g_s32Quit = 0;//退出全局变量
void RTP_port_pool_init(int port);
int UpdateSpsOrPps(unsigned char *data,int frame_type,int len);
/**************************************************************************************************
**
**
**
**************************************************************************************************/
void PrefsInit()
{
int l;
//设置服务器信息全局变量
stPrefs.port = SERVER_RTSP_PORT_DEFAULT;
gethostname(stPrefs.hostname,sizeof(stPrefs.hostname));
l=strlen(stPrefs.hostname);
if (getdomainname(stPrefs.hostname+l+1,sizeof(stPrefs.hostname)-l)!=0)
{
stPrefs.hostname[l]='.';
}
#ifdef RTSP_DEBUG
printf("\n");
printf("\thostname is: %s\n", stPrefs.hostname);
printf("\trtsp listening port is: %d\n", stPrefs.port);
printf("\tInput rtsp://hostIP:%d/test.264 to play this\n",stPrefs.port);
printf("\n");
#endif
}
/**************************************************************************************************
**
**
**
**************************************************************************************************/
//为缓冲分配空间
void RTSP_initserver(RTSP_buffer *rtsp, int fd)
{
rtsp->fd = fd;
rtsp->session_list = (RTSP_session *) calloc(1, sizeof(RTSP_session));
rtsp->session_list->session_id = -1;
}
/**************************************************************************************************
**
**
**
**************************************************************************************************/
//为RTP准备两个端口
int RTP_get_port_pair(port_pair *pair)
{
int i;
for (i=0; i<MAX_CONNECTION; ++i)
{
if (s_uPortPool[i]!=0)
{
pair->RTP=(s_uPortPool[i]-s_u32StartPort)*2+s_u32StartPort;
pair->RTCP=pair->RTP+1;
s_uPortPool[i]=0;
return ERR_NOERROR;
}
}
return ERR_GENERIC;
}
/**************************************************************************************************
**
**
**
**************************************************************************************************/
void AddClient(RTSP_buffer **ppRtspList, int fd)
{
RTSP_buffer *pRtsp=NULL,*pRtspNew=NULL;
#ifdef RTSP_DEBUG
fprintf(stderr, "%s, %d\n", __FUNCTION__, __LINE__);
#endif
//在链表头部插入第一个元素
if (*ppRtspList==NULL)
{
/*分配空间*/
if ( !(*ppRtspList=(RTSP_buffer*)calloc(1,sizeof(RTSP_buffer)) ) )
{
fprintf(stderr,"alloc memory error %s,%i\n", __FILE__, __LINE__);
return;
}
pRtsp = *ppRtspList;
}
else
{
//向链表中插入新的元素
for (pRtsp=*ppRtspList; pRtsp!=NULL; pRtsp=pRtsp->next)
{
pRtspNew=pRtsp;
}
/*在链表尾部插入*/
if (pRtspNew!=NULL)
{
if ( !(pRtspNew->next=(RTSP_buffer *)calloc(1,sizeof(RTSP_buffer)) ) )
{
fprintf(stderr, "error calloc %s,%i\n", __FILE__, __LINE__);
return;
}
pRtsp=pRtspNew->next;
pRtsp->next=NULL;
}
}
//设置最大轮询id号
if(g_s32Maxfd < fd)
{
g_s32Maxfd = fd;
}
/*初始化新添加的客户端*/
RTSP_initserver(pRtsp,fd);
fprintf(stderr,"Incoming RTSP connection accepted on socket: %d\n",pRtsp->fd);
}
/**************************************************************************************************
**
**
**
**************************************************************************************************/
/*根据缓冲区的内容,填充后边两个长度数据,检查缓冲区中消息的完整性
* return -1 on ERROR
* return RTSP_not_full (0) if a full RTSP message is NOT present in the in_buffer yet.
* return RTSP_method_rcvd (1) if a full RTSP message is present in the in_buffer and is
* ready to be handled.
* return RTSP_interlvd_rcvd (2) if a complete RTP/RTCP interleaved packet is present.
* terminate on really ugly cases.
*/
int RTSP_full_msg_rcvd(RTSP_buffer *rtsp, int *hdr_len, int *body_len)
{
int eomh; /* end of message header found */
int mb; /* message body exists */
int tc; /* terminator count */
int ws; /* white space */
unsigned int ml; /* total message length including any message body */
int bl; /* message body length */
char c; /* character */
int control;
char *p;
/*是否存在交叉存取的二进制rtp/rtcp数据包,参考RFC2326-10.12*/
if (rtsp->in_buffer[0] == '$')
{
uint16_t *intlvd_len = (uint16_t *)&rtsp->in_buffer[2]; /*跳过通道标志符*/
/*转化为主机字节序,因为长度是网络字节序*/
if ( (bl = ntohs(*intlvd_len)) <= rtsp->in_size)
{
fprintf(stderr,"Interleaved RTP or RTCP packet arrived (len: %hu).\n", bl);
if (hdr_len)
*hdr_len = 4;
if (body_len)
*body_len = bl;
return RTSP_interlvd_rcvd;
}
else
{
/*缓冲区不能完全存放数据*/
fprintf(stderr,"Non-complete Interleaved RTP or RTCP packet arrived.\n");
return RTSP_not_full;
}
}
eomh = mb = ml = bl = 0;
while (ml <= rtsp->in_size)
{
/* look for eol. */
/*计算不包含回车、换行在内的所有字符数*/
control = strcspn(&(rtsp->in_buffer[ml]), "\r\n");
if(control > 0)
ml += control;
else
return ERR_GENERIC;
/* haven't received the entire message yet. */
if (ml > rtsp->in_size)
return RTSP_not_full;
/* 处理终结符,判读是否是消息头的结束*/
tc = ws = 0;
while (!eomh && ((ml + tc + ws) < rtsp->in_size))
{
c = rtsp->in_buffer[ml + tc + ws];
/*统计回车换行*/
if (c == '\r' || c == '\n')
tc++;
else if ((tc < 3) && ((c == ' ') || (c == '\t')))
{
ws++; /*回车、换行之间的空格或者TAB,也是可以接受的 */
}
else
{
break;
}
}
/*
*一对回车、换行符仅仅被统计为一个行终结符
* 双行可以被接受,并将其认为是消息头的结束标识
* 这与RFC2068中的描述一致,参考rfc2068 19.3
*否则,对所有的HTTP/1.1兼容协议消息元素来说,
*回车、换行被认为是合法的行终结符
*/
/* must be the end of the message header */
if ((tc > 2) || ((tc == 2) && (rtsp->in_buffer[ml] == rtsp->in_buffer[ml + 1])))
eomh = 1;
ml += tc + ws;
if (eomh)
{
ml += bl; /* 加入消息体长度 */
if (ml <= rtsp->in_size)
break; /* all done finding the end of the message. */
}
if (ml >= rtsp->in_size)
return RTSP_not_full; /* 还没有完全接收消息 */
/*检查每一行的第一个记号,确定是否有消息体存在 */
if (!mb)
{
/* content length token not yet encountered. */
if (!
评论2