RTPProxy代码结构说明

RTPProxy是纯C语言开发,使用面向对象的思路实现的对stream、session等的抽象,另外对象的构造、析构和引用计数机制都有实现,和doubango中对象的实现思路类似,每个对象一个c文件,提供类似rtpp_server_ctor和rtpp_server_dtor的构造和析构方法,然后提供一个结构体的实例化对象,结构体对象中第一个对象是该对象的公共接口方法指针,类似如下代码:
static const struct rtpp_server_smethods rtpp_server_smethods = {
    .get = &rtpp_server_get,
    .get_ssrc = &rtpp_server_get_ssrc,
    .set_ssrc = &rtpp_server_set_ssrc,
    .get_seq = &rtpp_server_get_seq,
    .set_seq = &rtpp_server_set_seq,
    .start = &rtpp_server_start
};

并在ctor方法中设置指针变量指向这个全局的变量地址:
    rp->pub.smethods = &rtpp_server_smethods;

 

RTPProxy的实现比想象中简单,完全符合SIP呼叫通话建立规则,一个端口申请一个在RTPProxy的代理端口,一个一对一的通话申请两个RTPProxy的端口,然后RTPProxy在接收到包后转给对应的端口。其中每个session有两个stream对象,一个是caller,一个callee,这样就完成了一对一的包转发和通话流程。

 

为了调试方便,我修改了输入命令的的分割字符串:改为#号分割,便于通过一个客户端的socket发送指令:



struct rtpp_command *
get_command(struct cfg *cf, int controlfd, int *rval, double dtime,
  struct rtpp_command_stats *csp, int umode,
  struct rtpp_cmd_rcache *rcache_obj){
//...
    //for (ap = cmd->argv; (*ap = rtpp_strsep(&cp, "\r\n\t ")) != NULL;) {
    for (ap = cmd->argv; (*ap = rtpp_strsep(&cp, "#")) != NULL;) {
//...
}

rtpproxy的启动:

rtpproxy  -F -f -s udp:0.0.0.0 12221  -d DBUG

写一个UDP Socket的客户端连接到RtpProxy的12221端口,然后发送指令:

 

sendToServer: len [63] – content [#t#U#30044995-03030-3030-3031-34#11.12.112.10#19393#123@11.com#]

input message to others : Read: len [8] – content [t 47868]

#dd#L#30044995-03030-3030-3031-34#11.12.112.10#19398#123@11.com#

sendToServer: len [64] – content [#dd#L#30044995-03030-3030-3031-34#11.12.112.10#19398#123@11.com#]

input message to others : Read: len [9] – content [dd 40888]

 

整体文件的引用关系如下图:

 

测试程序,依赖libevent

//event test udp socket server
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#include <event.h>
#include <event2/listener.h>


#include <fcntl.h>

#include <pthread.h>

#include <signal.h>

#include <sys/types.h>
#include <sys/time.h>
#include <sys/stat.h>
#include <sys/resource.h>

#define LOCAL_IP "11.12.115.139"
#define LOCAL_PORT 19393

#define SVR_IP "11.12.115.200"
#define SVR_PORT  22222
#define BUF_SIZE 1024

#define UR_CLIENT_SOCK_BUF_SIZE (65536)
#define UR_SERVER_SOCK_BUF_SIZE (UR_CLIENT_SOCK_BUF_SIZE * 32)

void read_cb(int fd, short event, void *arg) {
	char buf[BUF_SIZE];
	int len;
	int size = sizeof(struct sockaddr);
	struct sockaddr_in client_addr;

	memset(buf, 0, sizeof(buf));
	len = recvfrom(fd, buf, sizeof(buf), 0, (struct sockaddr *)&client_addr, &size);

	if (len == -1) {
		perror("recvfrom()");
	} else if (len == 0) {
		printf("Connection Closed\n");
	} else {
		printf("Read: len [%d] – content [%s]\n", len, buf);

		/* Echo */
		//sendto(fd, buf, len, 0, (struct sockaddr *)&client_addr, size);
	}
}
 
typedef struct _RTPHeader {
#if 0
   //rtp header
   unsigned int version:2;          /* protocol version */
   unsigned int p:1;                /* padding flag */
   unsigned int x:1;                /* header extension flag */
   unsigned int cc:4;               /* CSRC count */
   unsigned int m:1;                /* marker bit */
   unsigned int pt:7;               /* payload type */
#else      
   unsigned short int rtpheader;
#endif 
   unsigned short int seq;				        /* sequence number */
   unsigned int ts;                       /* timestamp */
   unsigned int ssrc;                     /* synchronization source */
   //UInt32 csrc[1];                /* optional CSRC list */
}RTPHeader;

void sendToServer(int fd, char* msg, int len, struct sockaddr_in *server){
 
    int newLen = len + sizeof(RTPHeader);
    char *rtpBuffer = (char *)malloc(newLen);

	printf("sendToServer: len [%d] – content [%s], rtplen[%d]\n", len, msg, newLen);
    static unsigned short seqNum = 1;
    static unsigned long SSRC = 0x99999;
    RTPHeader rtppacket;
    rtppacket.seq = htons(seqNum++);
    rtppacket.ssrc = htonl(SSRC);
    rtppacket.rtpheader          = htons(0x8000 | 0x08 | 0x80);//96   => 0x60    0x08=> pcma

    memcpy(rtpBuffer, &rtppacket, sizeof(RTPHeader));
    memcpy(rtpBuffer+sizeof(RTPHeader), msg, len);

	sendto(fd, rtpBuffer, newLen, 0, (struct sockaddr *)server, sizeof(struct sockaddr_in));

	free(rtpBuffer);
}

typedef struct AAA{
    struct sockaddr_in *server;
    int fd;
}ServerInfo;

int set_sock_buf_size(int fd, int sz0)
{
	int sz;

	sz = sz0;
	while (sz > 0) {
		if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, (const void*) (&sz), (socklen_t) sizeof(sz)) < 0) {
			sz = sz / 2;
		} else {
			break;
		}
	}

	if (sz < 1) {
		perror("Cannot set socket rcv size"); 
	}

	sz = sz0;
	while (sz > 0) {
		if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (const void*) (&sz), (socklen_t) sizeof(sz)) < 0) {
			sz = sz / 2;
		} else {
			break;
		}
	}

	if (sz < 1) {
		perror("Cannot set socket snd size"); 
	}

	return 0;
}

//recv user input value
static void * recv_input_thread(void *arg)  {
	if (arg == NULL){
    	return NULL;
	}
    ServerInfo *serverInfo = (ServerInfo *) arg;

	char  input;
	char msg[1024];
  
	do{

	    printf("input message to others[lenth<1024]:"); 
        memset(msg, 0x00, 1024);
        //scanf("%s", &msg); 
        gets(msg);
        msg[1023] = '\0'; 
		sendToServer(serverInfo->fd, msg, strlen(msg), serverInfo->server);
 
	}while(input != '0'); 

	printf("Done!\n"); 
    free(serverInfo);
	return NULL;
}

int bind_socket(struct event *ev, int sock_fd, int local_port) { 
	int flag = 1;
	struct sockaddr_in sin;
  
	/* Set IP, port */
	memset(&sin, 0, sizeof(sin));
	sin.sin_family = AF_INET;
	sin.sin_addr.s_addr = inet_addr(LOCAL_IP);
	sin.sin_port = htons(local_port);

#ifdef IP_RECVERR
		if (sin.sin_family != AF_INET6) {
			int on = 0;
#ifdef TURN_IP_RECVERR
			on = 1;
#endif
			if(setsockopt(sock_fd, IPPROTO_IP, IP_RECVERR, (void *)&on, sizeof(on))<0)
				perror("IP_RECVERR");
		}
#endif

#ifdef IPV6_RECVERR
		if (sin.sin_family == AF_INET6) {
			int on = 0;
#ifdef TURN_IP_RECVERR
			on = 1;
#endif
			if(setsockopt(sock_fd, IPPROTO_IPV6, IPV6_RECVERR, (void *)&on, sizeof(on))<0)
				perror("IPV6_RECVERR");
		}
#endif

    if (fcntl(sock_fd, F_SETFL, O_NONBLOCK) == -1) {
        perror("O_NONBLOCK");
        return -1;
    }
	set_sock_buf_size(sock_fd, UR_SERVER_SOCK_BUF_SIZE);

	/* Bind */
	if (bind(sock_fd, (struct sockaddr *)&sin, sizeof(struct sockaddr)) < 0) {
		perror("bind()");
		return -1;
	} else {
		printf("bind() success – [%s] [%u]\n", SVR_IP, local_port);
	}


	/* Init one event and add to active events */
	event_set(ev, sock_fd, EV_READ | EV_PERSIST, &read_cb, NULL);
	if (event_add(ev, NULL) == -1) {
		printf("event_add() failed\n");
	}

	return 0;
}
//[root@localhost sample]# gcc -o send_rtp_test_udp_client send_rtp_test_udp_client.c -levent -lpthread
//[root@localhost sample]# ./send_rtp_test_udp_client  11.12.115.200  12221 19394
int
main(int argc, char **argv)
{
	struct event udp_event;

    if (argc < 4){
		printf("event_init() failed\n");

    	return -1;
    }
    char *serverIp;
    int serverPort = 0;
    int localPort = 0;

    int len = strlen(argv[1]);
    serverIp = (char *)malloc(len + 1);
    memcpy(serverIp, argv[1], len);
    serverIp[len] = '\0';
    serverPort = atoi(argv[2]);
    localPort = atoi(argv[3]);
	
	printf("input serverIp:%s, port:%d, localPort:%d\n", serverIp, serverPort, localPort);


	/* Init. event */
	if (event_init() == NULL) {
		printf("event_init() failed\n");
		return -1;
	}
 
	int sock_fd;
	int flag = 1;
	struct sockaddr_in server;

	/* Create endpoint */
	if ((sock_fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
		perror("socket()");
		return -1;
	}

	/* Set socket option */
	if (setsockopt(sock_fd, SOL_SOCKET, SO_REUSEADDR, &flag, sizeof(int)) < 0) {
		perror("setsockopt()");
		return 1;
	}


	/* Bind socket */
	if (bind_socket(&udp_event, sock_fd, localPort) != 0) {  
		printf("bind_socket() failed\n");
		return -1;
	}

	/* Set IP, port */
	memset(&server, 0, sizeof(server));
	server.sin_family = AF_INET;
	server.sin_addr.s_addr = inet_addr(serverIp);
	server.sin_port = htons(serverPort);


	ServerInfo *serverInfo = (ServerInfo *)malloc(sizeof(ServerInfo));
	serverInfo->server = &server;
	serverInfo->fd = sock_fd;

    pthread_t tidp;
	if ((pthread_create(&tidp, NULL, recv_input_thread, (void*)serverInfo)) == -1){
		printf("create error!\n");
		return 1;
	}



	/* Enter the event loop; does not return. */
	event_dispatch();
	close(sock_fd);


	printf("done\n");
	return 0;
}

编译:gcc -o send_rtp_test_udp_client send_rtp_test_udp_client.c -levent -lpthread

运行:./send_rtp_test_udp_client 11.12.115.200 12221 19993
input serverIp:11.12.115.200, port:12221, localPort:19993
bind() success ?.[11.12.115.200] [19993]
input message to others[lenth<1024]:

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值