⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 proxy.c

📁 简单的基于SIP的会话边界控制器
💻 C
📖 第 1 页 / 共 3 页
字号:
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>

#include <osipparser2/osip_parser.h>
#include <osipparser2/osip_message.h>
#include <osipparser2/sdp_message.h>

#include "nsrsbc.h"
#include "regctl.h"
#include "sessctl.h"
#include "cmdline.h"

extern struct sip_reg_ctl_t sip_reg_ctl[REGNUM_SIZE];
extern struct sip_sess_ctl_t sip_sess_ctl[SESSNUM_SIZE];
extern struct gengetopt_args_info args_info;
extern int interface_sock;
extern char interface_buffer[BUFFER_SIZE];
int invite_direct = 0;   //add 2007.11.02

char *osip_call_id_new_random(void)
{
	char *tmp = (char *) osip_malloc (33);
	unsigned int number = osip_build_random_number();
	sprintf(tmp, "%u", number);
	return tmp;
}

char *osip_from_tag_new_random(void) {
	return osip_call_id_new_random ();
}

char *osip_to_tag_new_random(void) {
	return osip_call_id_new_random ();
}

/*
 * SIP_REWRITE_SDP
 *
 * rewrite the SDP Body
 *
 * RETURNS
 *	STS_SUCCESS on success
 *	STS_FAILURE on error
 */

int sip_rewrite_sdp(sip_ticket_t *ticket, int direction) {
	
	/* Write SDP message's o, c, m, start rtp sock */
	
	int sts;
	char *buf;
	size_t buflen;
	char clen[8]; /* content length: probably never more than 7 digits !*/
	
	osip_message_t *mymsg = ticket->sipmsg;
	osip_body_t *body;
	sdp_message_t  *sdp;
	sdp_connection_t *sdp_conn;
	sdp_media_t *sdp_med;
	
	int media_stream_no;
	int have_c_media = 0;
	int rtp_direction=0;
	
	struct in_addr map_addr, addr_sess, addr_media;
	int map_port, msg_port;
	struct in_addr outside_addr, inside_addr;
	
	/* 1. Get SDP Message */

	//memset(buf,0,1024);
	sts = osip_message_get_body(mymsg, 0, &body);
	if (sts != 0) {
		printf("sip_rewrite_sdp(): no body found in message.\n");
		return STS_SUCCESS;
	}

	sts = osip_body_to_str(body, &buf, &buflen);
	if (sts != 0) {
		printf("ERROR:sip_rewrite_sdp(): unable to sip_body_to_str.\n");
		return STS_FAILURE;
	}
	buf[buflen]='\0';
//    printf("%s\n",buf);
	sts = sdp_message_init(&sdp);
	sts = sdp_message_parse(sdp, buf);
	if (sts != 0) {
		printf("ERROR:sip_rewrite_sdp(): unable to sdp_message_parse.\n");
		osip_free(buf);
		sdp_message_free(sdp);
		return STS_FAILURE;
	}
	osip_free(buf);
	
	
	inside_addr.s_addr = inet_addr(args_info.inaddr_arg);
	outside_addr.s_addr = inet_addr(args_info.outaddr_arg);
	
	/* figure out what address to use for RTP relay */
	if (direction == DIR_INCOMING) {
         	memcpy(&map_addr, &inside_addr, sizeof (map_addr));
	       rtp_direction = DIR_OUTGOING;
	}
	else {
		memcpy(&map_addr, &outside_addr, sizeof (map_addr));
		rtp_direction = DIR_INCOMING;
	}
		
	/*
	 * 2. Rewrite 'o=' item (originator) on session level if present.
	 */
	if (sdp->o_addrtype && sdp->o_addr) {
		if (strcmp(sdp->o_addrtype, "IP4") != 0) {
			printf("ERROR:sip_rewrite_sdp():got IP6 in SDP originator!\n");
			sdp_message_free(sdp);
			return STS_FAILURE;
		}
		osip_free(sdp->o_addr);
		sdp->o_addr = osip_malloc(HOSTNAME_SIZE);
		sprintf(sdp->o_addr, "%s", inet_ntoa(map_addr));
	}
	
	/*
	 * first, check presence of a 'c=' item on session level
	 * According to RFC2327, ALL media description must include a 'c=' item now
	 */
	if (sdp->c_connection == NULL || sdp->c_connection->c_addr == NULL) {
		/*
	 	 * No 'c=' on session level, search on media level now
	 	 * search each media description
	 	 */
		media_stream_no=0;
		while (!sdp_message_endof_media(sdp, media_stream_no)) {
			/* check if n'th media stream is present */
			if (sdp_message_c_addr_get(sdp, media_stream_no, 0) == NULL) {
				printf("ERROR: sip_rewrite_sdp(): have no 'c=' on session level and neither on media level (media=%i)\n", media_stream_no);
				sdp_message_free(sdp);
				return STS_FAILURE;
			}
			media_stream_no++;
		}
	}
	
	/* Required 'c=' items ARE present */
	/*
	 * rewrite 'c=' item on session level if present and not yet done.
	 * remember the original address in addr_sess
	 */
	memset(&addr_sess, 0, sizeof(addr_sess));
	if (sdp->c_connection && sdp->c_connection->c_addr) {
		addr_sess.s_addr = inet_addr(sdp->c_connection->c_addr);
      		/*
       		 * Rewrite
       		 * an IP address of 0.0.0.0 means *MUTE*, don't rewrite such
       		 */
      		if (strcmp(sdp->c_connection->c_addr, "0.0.0.0") != 0) {
         		osip_free(sdp->c_connection->c_addr);
         		sdp->c_connection->c_addr = osip_malloc(HOSTNAME_SIZE);
         		sprintf(sdp->c_connection->c_addr, "%s", inet_ntoa(map_addr));
      		} else {
         		/* 0.0.0.0 - don't rewrite */
         		printf("sip_rewrite_sdp: got a MUTE c= record (on session level)\n");
		}
	}
	
	/*
	 * loop through all media descriptions,
	 * start RTP proxy and rewrite them
	 */	
	for (media_stream_no=0;;media_stream_no++) {
		/* check if n'th media stream is present */
		if (sdp_message_m_port_get(sdp, media_stream_no) == NULL) break;
		
		/* check if a 'c=' item is present in this media description, 
		 * if so -> rewrite it 
		 */
		memset(&addr_media, 0, sizeof(addr_media));
		have_c_media = 0;
		sdp_conn = sdp_message_connection_get(sdp, media_stream_no, 0);
		if (sdp_conn && sdp_conn->c_addr) {
			if (strcmp(sdp_conn->c_addr, "0.0.0.0") != 0) {
				addr_media.s_addr = inet_addr(sdp_conn->c_addr);
				have_c_media=1;
				/* have a valid address */
				osip_free(sdp_conn->c_addr);
				sdp_conn->c_addr = osip_malloc(HOSTNAME_SIZE);
				sprintf(sdp_conn->c_addr, "%s", inet_ntoa(map_addr));
			} else {
				/* 0.0.0.0 - don't rewrite */
				printf("sip_rewrite_sdp(): got a MUTE c= record (media level)\n");
			}
		}

		/* Rewrite port number, start an RTP proxying stream */
		if (sdp_message_m_port_get(sdp, media_stream_no)) {
			msg_port = atoi(sdp_message_m_port_get(sdp, media_stream_no));
			if (msg_port > 0) {
				osip_uri_t *cont_url = NULL;
            			char *client_id=NULL;
            			/* try to get some additional UA specific unique ID */
            			if (!osip_list_eol(mymsg->contacts, 0)) {
               			cont_url = ((osip_contact_t*)(mymsg->contacts->node->element))->url;
           				if (cont_url) 
                				client_id=cont_url->username;
           					if (client_id == NULL)  client_id=cont_url->host;
            			}

            			/*
             			 * do we have a 'c=' item on media level?
             			 * if not, use the same as on session level
             			 */
            			if (have_c_media == 0) {
               			memcpy(&addr_media, &addr_sess, sizeof(addr_sess));
            			}
            			
				sts = rtp_relay_start_fwd(osip_message_get_call_id(mymsg),
                                		client_id, rtp_direction,
                                		media_stream_no,
                                		map_addr, &map_port,
                                		addr_media, msg_port);
				
				if (sts == STS_SUCCESS) {
					/* and rewrite the port */
					sdp_med = osip_list_get(sdp->m_medias, media_stream_no);
					if (sdp_med && sdp_med->m_port) {
						osip_free(sdp_med->m_port);
						sdp_med->m_port = osip_malloc(8); /* 5 digits, \0 + align */
						sprintf(sdp_med->m_port, "%i", map_port);
					} else {
						printf("ERROR:sip_rewrite_sdp():rewriting port in m= failed sdp_med = %p, m_number_of_port=%p\n", 
							sdp_med, sdp_med->m_port);
					}
				}
			}
		} else {
			/* no port defined - skip entry */
			printf("WARN:no port defined in m=(media) stream_no=%i\n", media_stream_no);
			continue;
		}
	}

	/* remove old body */
	sts = osip_list_remove(mymsg->bodies, 0);
	osip_body_free(body);

	/* dump new body */
	sdp_message_to_str(sdp, &buf);
	buflen = strlen(buf);

	/* free sdp structure */
	sdp_message_free(sdp);

	/* include new body */
	osip_message_set_body(mymsg, buf, buflen);
	if (sts != 0) {
		printf("ERROR: sip_rewrite_sdp(): unable to osip_message_set_body body.\n");
	}

	/* free content length resource and include new one*/
	osip_content_length_free(mymsg->content_length);
	mymsg->content_length = NULL;
	sprintf(clen,"%ld",(long)buflen);
	sts = osip_message_set_content_length(mymsg, clen);

	/* free old body */
	osip_free(buf);

	return STS_SUCCESS;
}


/*
 * PROXY_REWRITE_REGISTER
 *
 * rewrites the REGISTER Message
 * 
 * RETURNS
 *	STS_SUCCESS on success
 */
int proxy_rewrite_register(sip_ticket_t *ticket) {
	/* REGISTER handle:
	* 1. save register informaiton
	* 2. rewrite the sip message
	* 3. send to the register proxy
	*/
	int sts,i;
	struct in_addr dest_addr;
	char *buffer;
	size_t buflen;
	
	osip_message_t *request;
	struct in_addr recv_addr;
	int recv_port;
	
	char reg_hostname[HOSTNAME_SIZE];
	char reg_port[PORT_SIZE];
	char reg_username[USERNAME_SIZE];
	memset(reg_hostname, 0, HOSTNAME_SIZE);
	memset(reg_port, 0, PORT_SIZE);
	memset(reg_username, 0, USERNAME_SIZE);
	
	if (ticket == NULL) {
		printf("ERROR: proxy_rewrite_register: register with NULL ticket\n");
		return STS_FAILURE;
	}
	request = ticket->sipmsg;	
	
	/* 1. rewrite request uri */ 
	sts = sip_rewrite_requri(request, REQTYP_OUTGOING, 0);
	if (sts == STS_FAILURE)
	{
		printf("ERROR: can not rewrite register request uri\n");
		return STS_FAILURE;
	}

	/* 2. rewrite from */
	{
		osip_from_t *from;
		from = osip_message_get_from(request);
		
		if (from->url->username) {
			strcpy(reg_username, from->url->username);
		} else {
			printf("ERROR: can not register without a username!\n");
			return STS_FAILURE;
		}			
		
		if (from->url->host) {
			osip_free(from->url->host);
			from->url->host = NULL;
		}
		osip_uri_set_host(from->url, osip_strdup(args_info.proxy_addr_arg));
		
		if (from->url->port) {
			osip_free(from->url->port);
			from->url->port = NULL;
			char new_port[6];
			sprintf(new_port, "%d", SIP_LISTENING_PORT);
			osip_uri_set_port(from->url, osip_strdup(new_port));
		}
	}
	/* tag header now do not rewrite */


	/* 3. rewrite to */
	{
		osip_to_t *to;
		to = osip_message_get_to(request);
		
		if (to->url->host) {
			osip_free(to->url->host);
			to->url->host = NULL;
		}
		osip_uri_set_host(to->url, osip_strdup(args_info.proxy_addr_arg));
		
		if (to->url->port) {
			osip_free(to->url->port);
			to->url->port = NULL;
			char nport[6];
			sprintf(nport, "%d", SIP_LISTENING_PORT);
			osip_uri_set_port(to->url, osip_strdup(nport));
		}
	}

	/* 4. rewrite via */
	/* there could be many via headers, now just supported one via */
	osip_via_t *via;
	osip_message_get_via(request, 0, &via);
	if (via) {
		char via_port[6];
		sprintf(via_port, "%d", SIP_LISTENING_PORT);
		
		osip_list_remove(request->vias, 0);
		if (via->host) {
			osip_free(via->host);
			via->host = NULL;
		}	
		via_set_host(via, osip_strdup(args_info.outaddr_arg));
		if (via->port) {
			osip_free(via->port);
			via->port = NULL;
			via_set_port(via, osip_strdup(via_port));
		}
		osip_list_add(request->vias, via, 0);
	} else {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -