📄 proxy.c
字号:
#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 + -