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#[email protected]#]

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

#dd#L#30044995-03030-3030-3031-34#11.12.112.10#19398#[email protected]#

sendToServer: len [64] – content [#dd#L#30044995-03030-3030-3031-34#11.12.112.10#19398#[email protected]#]

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]:

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章