📄 proxy.c
字号:
forwards_count = atoi(max_forwards->hvalue);
forwards_count -=1;
osip_free (max_forwards->hvalue);
}
sprintf(mfwd, "%i", forwards_count);
max_forwards->hvalue = osip_strdup(mfwd);
}
}*/
break;
/*
* from the internal masqueraded host to an external host
*/
case REQTYP_OUTGOING:
if(i >= 0) {
/* rewrite from */
sts = sip_rewrite_from(request, REQTYP_OUTGOING, 0);
/* rewrite via */
sts = sip_rewrite_via(request, REQTYP_OUTGOING, 0);
/* rewrite contact */
sts = sip_rewrite_contact(request);
/* delete route */
sts = sip_del_route(ticket);
//modify 2007.11.02
if (invite_direct == DIR_OUTGOING) {
/* rewrite call-id */
osip_call_id_free(request->call_id);
request->call_id = NULL;
osip_message_set_call_id(request, osip_strdup(sip_sess_ctl[i].cid_new));
if (MSG_IS_BYE(request)) {
rtp_stop_fwd(osip_message_get_call_id(request), DIR_INCOMING);
rtp_stop_fwd(osip_message_get_call_id(request), DIR_OUTGOING);
}
}
if (invite_direct== DIR_INCOMING && MSG_IS_BYE(request)) {
rtp_stop_fwd(osip_message_get_call_id(request), DIR_INCOMING);
rtp_stop_fwd(osip_message_get_call_id(request), DIR_OUTGOING);
}
}
else {
if(MSG_IS_INVITE(request)) {
invite_direct = DIR_OUTGOING; //add 2007.11.02
char hostname[HOSTNAME_SIZE]; //information for sip_sess_ctl
char port[PORT_SIZE]; //information for sip_sess_ctl
memset(hostname, 0, HOSTNAME_SIZE);
memset(port, 0, PORT_SIZE);
/* rewrite from */
sts = sip_rewrite_from(request, REQTYP_OUTGOING, 0);
/* rewrite via */
sts = sip_rewrite_via(request, REQTYP_OUTGOING, 0);
/* rewrite contact and add sip_sess_ctl*/
osip_contact_t *contact;
osip_message_get_contact(request, 0, &contact);
if (contact) {
osip_list_remove(request->contacts, 0);
if (contact->url->host) {
strcpy(hostname,contact->url->host);
osip_free(contact->url->host);
contact->url->host = NULL;
}
osip_uri_set_host(contact->url, osip_strdup(args_info.outaddr_arg));
char contact_port[5];
sprintf(contact_port, "%d", SIP_LISTENING_PORT);
if (contact->url->port) {
strcpy(port,contact->url->port);
osip_free(contact->url->port);
contact->url->port = NULL;
osip_uri_set_port(contact->url, osip_strdup(contact_port));
}
osip_list_add(request->contacts, contact, 0);
}else {
/* no contact, should be repair, now not supported */
printf("Can't rewrite Contact Header: no contact header!\n");
}
/* rewrite call-id */
char cidnew[CALLID_SIZE];
char *cidrand;
cidrand = osip_call_id_new_random();
sprintf(cidnew, "%s@%s", cidrand, args_info.outaddr_arg);
sts = sessctl_new(sip_sess_ctl, callid, cidnew, hostname,
port, SESSNUM_SIZE);
if (sts < 0) return STS_FAILURE;
osip_call_id_free(request->call_id);
request->call_id = NULL;
osip_message_set_call_id(request, osip_strdup(cidnew));
/* rewrite sdp */
sts = sip_rewrite_sdp(ticket, DIR_OUTGOING);
}
else {
printf("Can't handle this message!\n");
//osip_free(request);
return STS_FAILURE;
}
}
break;
default:
/*
* we may end up here for two reasons:
* 1) An incomming request (from outbound) that is directed to
* an unknown (not registered) local UA
* 2) an outgoing request from a local UA that is not registered.
*
* Case 1) we should probably answer with "404 Not Found",
* case 2) more likely a "403 Forbidden"
*
* How about "408 Request Timeout" ?
*
*/
//sip_gen_response(ticket, 408 /* Request Timeout */);
return STS_FAILURE;
}
/* Determine Next-Hop Address */
/* For outgoing request:
* priority probably should be:
* 1) Route header
* 2) fixed outbound proxy
* 3) SIP URI
* For incoming request:
* All should be sent to NAT
*/
if (type == REQTYP_OUTGOING) {
/*if (request->routes && !osip_list_eol(request->routes, 0)) {
osip_route_t *route = NULL;
route = (osip_route_t *) osip_list_get(request->routes, 0);
if (route==NULL || route->url==NULL || route->url->host==NULL)
return STS_FAILURE;
if (inet_aton(route->url->host, &destaddr) < 0) {
printf("proxy_request(): route->url->host error!\n");
return STS_FAILURE;
}
if (route->url->port) {
destport = atoi(route->url->port);
} else {
destport = SIP_LISTENING_PORT;
}
//osip_list_remove(request->routes, 0);
//osip_route_free(route);
} else */
if (MSG_IS_INVITE(request)) {
if (inet_aton(args_info.proxy_addr_arg, &destaddr) < 0) {
printf("proxy_request(): proxy ip error!\n");
return STS_FAILURE;
}
destport = SIP_LISTENING_PORT;
}
else {
/* get the destination from the SIP URI */
if (inet_aton(req_uri->host, &destaddr) < 0) {
printf("proxy_request(): req_uri->host error!\n");
return STS_FAILURE;
}
if (req_uri->port) {
destport = atoi(req_uri->port);
} else {
destport = SIP_LISTENING_PORT;
}
}
}
if (type == REQTYP_INCOMING) {
sts = regctl_findaddr(sip_reg_ctl, req_uri->username, &destaddr,
&destport, REGNUM_SIZE);
if (sts < 0) {
printf("ERROR:proxy_request: can not get ip by username");
return STS_FAILURE;
}
}
/*
* RFC 3261, Section 16.6 step 10
* Proxy Behavior - Forward the new request
*/
sts = osip_message_to_str(request, &buffer, &buflen);
if (sts != 0) {
printf("ERROR:proxy_request(): osip_message_to_str failed\n");
return STS_FAILURE;
}
char tmp[8196];
sprintf(tmp,"<cursip>%s</cursip>",buffer);
strcat(interface_buffer,tmp);
printf("%s\n",buffer);
sipsock_send(destaddr, destport, ticket->protocol, buffer, buflen);
osip_free (buffer);
return STS_SUCCESS;
}
/*
* PROXY_RESPONSE
*
* RETURNS
* STS_SUCCESS on success
* STS_FAILURE on error
* RFC3261
* Section 16.7: Proxy Behavior - Response Processing
* 1. Find the appropriate response context
* 2. Update timer C for provisional responses
* 3. Remove the topmost Via
* 4. Add the response to the response context
* 5. Check to see if this response should be forwarded immediately
* 6. When necessary, choose the best final response from the
* response context
* 7. Aggregate authorization header field values if necessary
* 8. Optionally rewrite Record-Route header field values
* 9. Forward the response
* 10. Generate any necessary CANCEL requests
*
*/
int proxy_response(sip_ticket_t *ticket) {
int sts,i;
int type;
struct in_addr dest_addr;
int dest_port;
char *buffer;
size_t buflen;
char *callid;
osip_message_t *response;
osip_via_t *via;
if (ticket == NULL) {
printf("ERROR:proxy_response: called with NULL ticket!\n");
return STS_FAILURE;
}
response = ticket->sipmsg;
/*
* figure out if this is an request coming from the outside
* world to one of our registered clients
*/
sts = sip_find_direction(ticket);
if(sts) {
printf("Can't handle this message,we can't find matching dialog!\n");
//osip_free(response);
return STS_FAILURE;
}
type = ticket->direction;
/* According call_id we check whether this response belong to a existed dialog */
osip_call_id_to_str(response->call_id,&callid);
i = sessctl_find(sip_sess_ctl,callid,SESSNUM_SIZE);
switch (type) {
/* from an external host to the internal masqueraded host */
case RESTYP_INCOMING:
/* Response for REGISTER */
// if (MSG_IS_RESPONSE_FOR(response,"REGISTER")) {
//sts = proxy_rewrite_register_response(ticket);
// }
if(i >= 0) {
/* Rewrite Via */
sts = sip_rewrite_via(response, RESTYP_INCOMING, i);
/* Rewrite From */
sts = sip_rewrite_from(response, RESTYP_INCOMING, i);
/* Add record-route */
sip_add_recordroute(ticket);
if (MSG_IS_RESPONSE_FOR(response,"INVITE") &&
MSG_IS_STATUS_2XX(response)) {
/* positive response, start RTP stream */
sts = sip_rewrite_sdp(ticket,DIR_INCOMING);
}
/* negative - stop a possibly started RTP stream */
if ((MSG_IS_STATUS_4XX(response)) ||
(MSG_IS_STATUS_5XX(response)) ||
(MSG_IS_STATUS_6XX(response))) {
rtp_stop_fwd(osip_message_get_call_id(response), DIR_INCOMING);
rtp_stop_fwd(osip_message_get_call_id(response), DIR_OUTGOING);
}
/* Rewrite Call-id */
osip_call_id_free(response->call_id);
response->call_id = NULL;
osip_message_set_call_id(response, osip_strdup(sip_sess_ctl[i].cid_old));
if (MSG_IS_RESPONSE_FOR(response,"BYE")) {
/* positive response, delete sip_sess_t */
sip_purge_recordroute(ticket);
sessctl_free(sip_sess_ctl, i);
}
if ((MSG_IS_STATUS_4XX(response)) ||
(MSG_IS_STATUS_5XX(response)) ||
(MSG_IS_STATUS_6XX(response))) {
sessctl_free(sip_sess_ctl, i);
}
}
else {
printf("Can't handle this message,we can't find matching dialog!\n");
return STS_FAILURE;
}
break;
/* from the internal masqueraded host to an external host */
case RESTYP_OUTGOING:
if(i >= 0) {
/* Remove My Via */
sip_del_myvia(ticket);
/* Remove Record-route */
sip_purge_recordroute(ticket);
/* Rewrite Contact if have */
sip_rewrite_contact(response);
/* Rewrite To */
sip_rewrite_to(response,RESTYP_OUTGOING,i);
if (MSG_IS_RESPONSE_FOR(response,"INVITE")) {
/* positive response, start RTP stream */
if (MSG_IS_STATUS_2XX(response)) {
sts = sip_rewrite_sdp(ticket,DIR_OUTGOING);
}
/* negative - stop a possibly started RTP stream */
else if ((MSG_IS_STATUS_4XX(response)) ||
(MSG_IS_STATUS_5XX(response)) ||
(MSG_IS_STATUS_6XX(response))) {
sessctl_free(sip_sess_ctl, i);
rtp_stop_fwd(osip_message_get_call_id(response), DIR_INCOMING);
rtp_stop_fwd(osip_message_get_call_id(response), DIR_OUTGOING);
}
}
if (MSG_IS_RESPONSE_FOR(response,"BYE")) {
/* positive response, delete sip_sess_t */
sessctl_free(sip_sess_ctl, i);
}
}
else {
printf("Can't handle this message,we can't find matching dialog!\n");
//osip_free(response);
return STS_FAILURE;
}
break;
default:
printf("response from/to unregistered UA (%s@%s)",
response->from->url->username? response->from->url->username:"*NULL*",
response->from->url->host? response->from->url->host : "*NULL*");
return STS_FAILURE;
}
/* Determine Next-Hop Address - VIA Header */
if (type == RESTYP_OUTGOING) {
via = (osip_via_t *) osip_list_get (response->vias, 0);
if (via == NULL) {
printf("ERROR:proxy_response(): list_get via failed!\n");
return STS_FAILURE;
}
if (inet_aton(via->host, &dest_addr) < 0) {
printf("proxy_response(): get ip from via->host error!\n");
return STS_FAILURE;
}
if (via->port) {
dest_port = atoi(via->port);
} else {
dest_port = SIP_LISTENING_PORT;
}
}
if (type == RESTYP_INCOMING) {
sts = regctl_findaddr(sip_reg_ctl, response->from->url->username, &dest_addr,
&dest_port, REGNUM_SIZE);
if (sts < 0) {
printf("ERROR:proxy_response(): can not get ip by username!\n");
return STS_FAILURE;
}
}
sts = osip_message_to_str(response, &buffer, &buflen);
if (sts != 0) {
printf("ERROR:proxy_response(): osip_message_to_str failed\n");
return STS_FAILURE;
}
printf("%s\n",buffer);
char tmp[8196];
sprintf(tmp,"<cursip>%s</cursip>",buffer);
strcat(interface_buffer,tmp);
sipsock_send(dest_addr, dest_port, ticket->protocol, buffer, buflen);
osip_free (buffer);
return STS_SUCCESS;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -