问题
现场无法接收到海康的国标报文,可以接收到自己创建的服务器报文,通过抓包是可以捕获到的,但是通过eXosip_event_wait没有收到数据,这是一个异步的处理方案,最终发现是开启防火墙导致的问题
事件接收逻辑
eXosip_listen_addr绑定端口,监听数据
osip_thread_create 创建线程,采用select方式等待数据
int
_eXosip_read_message (struct eXosip_t *excontext, int max_message_nb, int sec_max, int usec_max)
该函数调用select函数,等待接收SIP报文发送过来,超时继续等待
当接收到数据到达的信号,调用excontext->eXtl_transport.tl_read_message (excontext, &osip_fdset, &osip_wrset);开始接收,
tl_read_message是一个函数指针,根据不同的协议类型,选择最终的具体调用,例如UDP的话,实现函数是udp_tl_read_message
调用_eXosip_handle_incoming_message去解析SIP报文,放进队列里面
用户层调用eXosip_event_wait获取事件进行处理
UDP SIP报文接收
代码
static int
udp_tl_read_message (struct eXosip_t *excontext, fd_set * osip_fdset, fd_set * osip_wrset)
当底层select接收到一个事件,调用该函数,通过recvfrom函数接收SIP报文
问题
else if (i < 0) {
#ifdef _WIN32_WCE
int my_errno = 0;
#else
int my_errno = errno;
#endif
OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "Could not read socket (%i) (%i) (%s)\n", i, my_errno, strerror (my_errno)));
if (errno == 0 || errno == 34) {
udp_message_max_length = udp_message_max_length * 2;
osip_free (reserved->buf);
reserved->buf = (char *) osip_malloc (udp_message_max_length * sizeof (char) + 1);
}
if (my_errno == 57) {
_udp_tl_reset_oc (excontext, reserved->udp_socket_oc_family);
}
一旦接收到目标主机不可达的数据包,就会触发该语句,errno为0, 并且udp_message_max_length会翻倍,因此多次出现目标主机不可达,就会导致申请内存失败,从而再也无法接收处理数据
if (reserved->buf == NULL)
reserved->buf = (char *) osip_malloc (udp_message_max_length * sizeof (char) + 1);
if (reserved->buf == NULL)
return OSIP_NOMEM;
因此申请内存这个操作必须注释掉,有两处代码,实际上SIP报文不会超过8000最大的,因此没有必要翻倍
UDP接收套接字的接收或者发送缓存的设置
函数处理接收的SIP报文
static int
udp_tl_open (struct eXosip_t *excontext)
在这里加大接收和发送缓存
unsigned int sendbuf= 1024 * 1024 * 20, recvbuf=1024*1024*20;
setsockopt(sock, SOL_SOCKET, SO_SNDBUF, (char*)&sendbuf, sizeof(sendbuf));
setsockopt(sock, SOL_SOCKET, SO_RCVBUF, (char*)&recvbuf, sizeof(sendbuf));