📄 rtpopen.c
字号:
/*------------------------------------------------------------------------- * rtpopen.c - rtpopen, rtpopensockets *------------------------------------------------------------------------- */#include <netinet/in.h>#include <sys/types.h>#include <stdio.h>#include <stdlib.h>#include <sys/socket.h>#include <hash.h>#include <strings.h>#include <string.h>#include <unistd.h>#include <time.h>#include <rtp.h>#include <rtcp.h>#include <util.h>#include <arpa/inet.h>#include <pthread.h>/*------------------------------------------------------------------------ * rtpopen - open a new RTP session, allocate resources and create state *------------------------------------------------------------------------ */struct session *rtpopen(struct in_addr session, int port, int bpbufsz, int bpbufcnt){ struct session *psn; int rv, packetsneeded; psn = (struct session *) malloc(sizeof(struct session)); if (psn == NULL) return NULL; memset(psn, 0, sizeof(struct session)); psn->sn_rtpfd = psn->sn_rtcpfd = -1; psn->sn_ssrcs = htnew(RTP_SSRCHTSZ, hashunsignedint, unsignedinteq, NULL, (void(*)(void *)) rtpdestroystream); psn->sn_cnames = htnew(RTP_CNAMEHTSZ, hashstring, (int(*)(unsigned int, unsigned int))strcasecmp, (void(*)(unsigned int))free, (void(*)(void *))free); psn->sn_cyclesources = (ssrc_t *) malloc(sizeof(ssrc_t) * RTCP_RRMAXRBLOCKS); packetsneeded = RTCP_RRMAXRBLOCKS / RTCP_MAXRBLOCKS + ((RTCP_RRMAXRBLOCKS % RTCP_MAXRBLOCKS) != 0); psn->sn_cyclebuf = (char *) malloc(RTCP_RRMAXRBLOCKS * sizeof(struct rblock) + packetsneeded * (RTCP_HEADERSZ + sizeof(ssrc_t))); rv = bufpoolinit(&psn->sn_bpool, bpbufsz, bpbufcnt); pthread_cond_init(&psn->sn_cond, NULL); pthread_mutex_init(&psn->sn_mutex, NULL); pthread_mutex_init(&psn->sn_getstreammutex, NULL); pthread_mutex_init(&psn->sn_cnamemutex, NULL); pthread_mutex_init(&psn->sn_rtpthrmutex, NULL); pthread_mutex_init(&psn->sn_rtcpthrmutex, NULL); pthread_mutex_init(&psn->sn_rtcpcyclethrmutex, NULL); psn->sn_addr = session; psn->sn_port = port; psn->sn_bw = RTP_DEFAULT_SESSIONBW; psn->sn_ssrc = rtpmkssrc(NULL); psn->sn_autocleanup = TRUE; if (rtpopensockets(psn, session, port) == ERROR || psn->sn_ssrcs == NULL || psn->sn_cnames == NULL || psn->sn_cyclesources == NULL || psn->sn_cyclebuf == NULL || rv == ERROR) { rtpclose(psn); return NULL; } return psn;}/*------------------------------------------------------------------------ * rtpopensockets - open socket for RTP and RTCP datagrams *------------------------------------------------------------------------ */intrtpopensockets(struct session *psn, struct in_addr session, int port){ struct sockaddr_in saddr; struct ip_mreq mreq; unsigned char loop; int reuse; unsigned char ttl; psn->sn_rtpfd = socket(AF_INET, SOCK_DGRAM, 0); psn->sn_rtcpfd = socket(AF_INET, SOCK_DGRAM, 0); if (psn->sn_rtpfd < 0 || psn->sn_rtcpfd < 0) { return ERROR; } memset(&saddr, 0, sizeof(struct sockaddr_in)); saddr.sin_family = AF_INET; if(IN_CLASSD(ntohl(session.s_addr))) { saddr.sin_addr = session; } else { saddr.sin_addr.s_addr = htonl(INADDR_ANY); } if (IN_CLASSD(ntohl(session.s_addr))) { reuse = 1; if (setsockopt(psn->sn_rtpfd, SOL_SOCKET, SO_REUSEADDR, (char *) &reuse, sizeof(reuse)) < 0) { close(psn->sn_rtpfd); close(psn->sn_rtcpfd); return ERROR; } if (setsockopt(psn->sn_rtcpfd, SOL_SOCKET, SO_REUSEADDR, (char *) &reuse, sizeof(reuse)) < 0) { close(psn->sn_rtpfd); close(psn->sn_rtcpfd); return ERROR; } } saddr.sin_port = htons(port); if (bind(psn->sn_rtpfd, (struct sockaddr *) &saddr, sizeof(struct sockaddr_in)) < 0) { close(psn->sn_rtpfd); close(psn->sn_rtcpfd); return ERROR; } saddr.sin_port = htons(port + 1); if (bind(psn->sn_rtcpfd, (struct sockaddr *) &saddr, sizeof(struct sockaddr_in)) < 0) { close(psn->sn_rtpfd); close(psn->sn_rtcpfd); return ERROR; } psn->sn_rtcpto = saddr; if (!IN_CLASSD(ntohl(session.s_addr))) psn->sn_rtcpto.sin_addr.s_addr = RTP_INADDRUNINITIALIZED; if (IN_CLASSD(ntohl(session.s_addr))) { mreq.imr_multiaddr = session; mreq.imr_interface.s_addr = htonl(INADDR_ANY); if (setsockopt(psn->sn_rtpfd, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *) &mreq, sizeof(struct ip_mreq)) < 0) { close(psn->sn_rtpfd); close(psn->sn_rtcpfd); return ERROR; } if (setsockopt(psn->sn_rtcpfd, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *) &mreq, sizeof(struct ip_mreq)) < 0) { close(psn->sn_rtpfd); close(psn->sn_rtcpfd); return ERROR; } /* * Disable loopback on RTCP socket so we don't want to hear ourselves. * This isn't done for the RTP socket because this implementation * assumes no sending. */ loop = 0; if (setsockopt(psn->sn_rtcpfd, IPPROTO_IP, IP_MULTICAST_LOOP, (char *) &loop, sizeof(loop)) < 0) { close(psn->sn_rtpfd); close(psn->sn_rtcpfd); return ERROR; } /* * Set TTL. * This isn't done for the RTP socket because this implementation * assumes no sending. */ ttl = RTP_DEFAULT_SESSIONTTL; if (setsockopt(psn->sn_rtcpfd, IPPROTO_IP, IP_MULTICAST_TTL, (char *) &ttl, sizeof(ttl)) < 0) { close(psn->sn_rtpfd); close(psn->sn_rtcpfd); return ERROR; } } return OK;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -