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

📄 proxy.c

📁 简单的基于SIP的会话边界控制器
💻 C
📖 第 1 页 / 共 3 页
字号:
         					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 + -