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

📄 sip_util.c

📁 基于sip协议的网络电话源码
💻 C
📖 第 1 页 / 共 3 页
字号:
	via = (pjsip_via_hdr*) pjsip_msg_find_hdr( tdata->msg,						   PJSIP_H_VIA, NULL);	if (!via) {	    /* Shouldn't happen if request was created with PJSIP API! 	     * But we handle the case anyway for robustness.	     */	    pj_assert(!"Via header not found!");	    via = pjsip_via_hdr_create(tdata->pool);	    pjsip_msg_insert_first_hdr(tdata->msg, (pjsip_hdr*)via);	}	if (via->branch_param.slen == 0) {	    pj_str_t tmp;	    via->branch_param.ptr = pj_pool_alloc(tdata->pool,						  PJSIP_MAX_BRANCH_LEN);	    via->branch_param.slen = PJSIP_MAX_BRANCH_LEN;	    pj_memcpy(via->branch_param.ptr, PJSIP_RFC3261_BRANCH_ID,		      PJSIP_RFC3261_BRANCH_LEN);	    tmp.ptr = via->branch_param.ptr + PJSIP_RFC3261_BRANCH_LEN + 2;	    *(tmp.ptr-2) = 80; *(tmp.ptr-1) = 106;	    pj_generate_unique_string(&tmp);	}	via->transport = pj_str(stateless_data->cur_transport->type_name);	via->sent_by = stateless_data->cur_transport->local_name;	via->rport_param = 0;	/* Send message using this transport. */	status = pjsip_transport_send( stateless_data->cur_transport,				       tdata,				       cur_addr,				       cur_addr_len,				       stateless_data,				       &stateless_send_transport_cb);	if (status == PJ_SUCCESS) {	    /* Recursively call this function. */	    sent = tdata->buf.cur - tdata->buf.start;	    stateless_send_transport_cb( stateless_data, tdata, sent );	    return;	} else if (status == PJ_EPENDING) {	    /* This callback will be called later. */	    return;	} else {	    /* Recursively call this function. */	    sent = -status;	    stateless_send_transport_cb( stateless_data, tdata, sent );	    return;	}    }}/* Resolver callback for sending stateless request. */static void stateless_send_resolver_callback( pj_status_t status,				  void *token,				  const struct pjsip_server_addresses *addr){    pjsip_send_state *stateless_data = token;    /* Fail on server resolution. */    if (status != PJ_SUCCESS) {	if (stateless_data->app_cb) {	    pj_bool_t cont = PJ_FALSE;	    (*stateless_data->app_cb)(stateless_data, -status, &cont);	}	pjsip_tx_data_dec_ref(stateless_data->tdata);	return;    }    /* Copy server addresses */    pj_memcpy( &stateless_data->addr, addr, sizeof(pjsip_server_addresses));    /* Process the addresses. */    stateless_send_transport_cb( stateless_data, stateless_data->tdata,				 -PJ_EPENDING);}/* * Send stateless request. * The sending process consists of several stages: *  - determine which host to contact (#pjsip_get_request_addr). *  - resolve the host (#pjsip_endpt_resolve) *  - establish transport (#pjsip_endpt_acquire_transport) *  - send the message (#pjsip_transport_send) */PJ_DEF(pj_status_t) pjsip_endpt_send_request_stateless(pjsip_endpoint *endpt, 				   pjsip_tx_data *tdata,				   void *token,				   void (*cb)(pjsip_send_state*,					      pj_ssize_t sent,					      pj_bool_t *cont)){    pjsip_host_info dest_info;    pjsip_send_state *stateless_data;    pj_status_t status;    PJ_ASSERT_RETURN(endpt && tdata, PJ_EINVAL);    /* Get destination name to contact. */    status = pjsip_process_route_set(tdata, &dest_info);    if (status != PJ_SUCCESS)	return status;    /* Keep stateless data. */    stateless_data = pj_pool_zalloc(tdata->pool, sizeof(pjsip_send_state));    stateless_data->token = token;    stateless_data->endpt = endpt;    stateless_data->tdata = tdata;    stateless_data->app_cb = cb;    /* Resolve destination host.     * The processing then resumed when the resolving callback is called.     */    pjsip_endpt_resolve( endpt, tdata->pool, &dest_info, stateless_data,			 &stateless_send_resolver_callback);    return PJ_SUCCESS;}/* * Determine which address (and transport) to use to send response message * based on the received request. This function follows the specification * in section 18.2.2 of RFC 3261 and RFC 3581 for calculating the destination * address and transport. */PJ_DEF(pj_status_t) pjsip_get_response_addr( pj_pool_t *pool,					     pjsip_rx_data *rdata,					     pjsip_response_addr *res_addr ){    pjsip_transport *src_transport = rdata->tp_info.transport;    /* Check arguments. */    PJ_ASSERT_RETURN(pool && rdata && res_addr, PJ_EINVAL);    /* rdata must be a request message! */    PJ_ASSERT_RETURN(rdata->msg_info.msg->type == PJSIP_REQUEST_MSG,		     PJ_EINVAL);    /* All requests must have "received" parameter.     * This must always be done in transport layer.     */    pj_assert(rdata->msg_info.via->recvd_param.slen != 0);    /* Do the calculation based on RFC 3261 Section 18.2.2 and RFC 3581 */    if (PJSIP_TRANSPORT_IS_RELIABLE(src_transport)) {	/* For reliable protocol such as TCP or SCTP, or TLS over those, the	 * response MUST be sent using the existing connection to the source	 * of the original request that created the transaction, if that 	 * connection is still open. 	 * If that connection is no longer open, the server SHOULD open a 	 * connection to the IP address in the received parameter, if present,	 * using the port in the sent-by value, or the default port for that 	 * transport, if no port is specified. 	 * If that connection attempt fails, the server SHOULD use the 	 * procedures in [4] for servers in order to determine the IP address	 * and port to open the connection and send the response to.	 */	res_addr->transport = rdata->tp_info.transport;	pj_memcpy(&res_addr->addr, &rdata->pkt_info.src_addr,		  rdata->pkt_info.src_addr_len);	res_addr->addr_len = rdata->pkt_info.src_addr_len;	res_addr->dst_host.type = src_transport->key.type;	res_addr->dst_host.flag = src_transport->flag;	pj_strdup( pool, &res_addr->dst_host.addr.host, 		   &rdata->msg_info.via->recvd_param);	res_addr->dst_host.addr.port = rdata->msg_info.via->sent_by.port;	if (res_addr->dst_host.addr.port == 0) {	    res_addr->dst_host.addr.port = 		pjsip_transport_get_default_port_for_type(res_addr->dst_host.type);	}    } else if (rdata->msg_info.via->maddr_param.slen) {	/* Otherwise, if the Via header field value contains a maddr parameter,	 * the response MUST be forwarded to the address listed there, using 	 * the port indicated in sent-by, or port 5060 if none is present. 	 * If the address is a multicast address, the response SHOULD be sent 	 * using the TTL indicated in the ttl parameter, or with a TTL of 1 if	 * that parameter is not present. 	 */	res_addr->transport = NULL;	res_addr->dst_host.type = src_transport->key.type;	res_addr->dst_host.flag = src_transport->flag;	pj_strdup( pool, &res_addr->dst_host.addr.host, 		   &rdata->msg_info.via->maddr_param);	res_addr->dst_host.addr.port = rdata->msg_info.via->sent_by.port;	if (res_addr->dst_host.addr.port == 0)	    res_addr->dst_host.addr.port = 5060;    } else if (rdata->msg_info.via->rport_param >= 0) {	/* There is both a "received" parameter and an "rport" parameter, 	 * the response MUST be sent to the IP address listed in the "received"	 * parameter, and the port in the "rport" parameter. 	 * The response MUST be sent from the same address and port that the 	 * corresponding request was received on.	 */	res_addr->transport = rdata->tp_info.transport;	pj_memcpy(&res_addr->addr, &rdata->pkt_info.src_addr,		  rdata->pkt_info.src_addr_len);	res_addr->addr_len = rdata->pkt_info.src_addr_len;	res_addr->dst_host.type = src_transport->key.type;	res_addr->dst_host.flag = src_transport->flag;	pj_strdup( pool, &res_addr->dst_host.addr.host, 		   &rdata->msg_info.via->recvd_param);	res_addr->dst_host.addr.port = rdata->msg_info.via->sent_by.port;	if (res_addr->dst_host.addr.port == 0) {	    res_addr->dst_host.addr.port = 		pjsip_transport_get_default_port_for_type(res_addr->dst_host.type);	}    } else {	res_addr->transport = NULL;	res_addr->dst_host.type = src_transport->key.type;	res_addr->dst_host.flag = src_transport->flag;	pj_strdup( pool, &res_addr->dst_host.addr.host, 		   &rdata->msg_info.via->recvd_param);	res_addr->dst_host.addr.port = rdata->msg_info.via->sent_by.port;	if (res_addr->dst_host.addr.port == 0) {	    res_addr->dst_host.addr.port = 		pjsip_transport_get_default_port_for_type(res_addr->dst_host.type);	}    }    return PJ_SUCCESS;}/* * Callback called by transport during send_response. */static void send_response_transport_cb(void *token, pjsip_tx_data *tdata,				       pj_ssize_t sent){    pjsip_send_state *send_state = token;    pj_bool_t cont = PJ_FALSE;    /* Call callback, if any. */    if (send_state->app_cb)	(*send_state->app_cb)(send_state, sent, &cont);    /* Decrement transport reference counter. */    pjsip_transport_dec_ref(send_state->cur_transport);    /* Decrement transmit data ref counter. */    pjsip_tx_data_dec_ref(tdata);}/* * Resolver calback during send_response. */static void send_response_resolver_cb( pj_status_t status, void *token,				       const pjsip_server_addresses *addr ){    pjsip_send_state *send_state = token;    if (status != PJ_SUCCESS) {	if (send_state->app_cb) {	    pj_bool_t cont = PJ_FALSE;	    (*send_state->app_cb)(send_state, -status, &cont);	}	pjsip_tx_data_dec_ref(send_state->tdata);	return;    }    /* Only handle the first address resolved. */    /* Acquire transport. */    status = pjsip_endpt_acquire_transport( send_state->endpt, 					    addr->entry[0].type,					    &addr->entry[0].addr,					    addr->entry[0].addr_len,					    &send_state->tdata->tp_sel,					    &send_state->cur_transport);    if (status != PJ_SUCCESS) {	if (send_state->app_cb) {	    pj_bool_t cont = PJ_FALSE;	    (*send_state->app_cb)(send_state, -status, &cont);	}	pjsip_tx_data_dec_ref(send_state->tdata);	return;    }    /* Update address in send_state. */    send_state->addr = *addr;    /* Send response using the transoprt. */    status = pjsip_transport_send( send_state->cur_transport, 				   send_state->tdata,				   &addr->entry[0].addr,				   addr->entry[0].addr_len,				   send_state,				   &send_response_transport_cb);    if (status == PJ_SUCCESS) {	pj_ssize_t sent = send_state->tdata->buf.cur - 			  send_state->tdata->buf.start;	send_response_transport_cb(send_state, send_state->tdata, sent);    } else if (status == PJ_EPENDING) {	/* Transport callback will be called later. */    } else {	send_response_transport_cb(send_state, send_state->tdata, -status);    }}/* * Send response. */PJ_DEF(pj_status_t) pjsip_endpt_send_response( pjsip_endpoint *endpt,					       pjsip_response_addr *res_addr,					       pjsip_tx_data *tdata,					       void *token,					       void (*cb)(pjsip_send_state*,							  pj_ssize_t sent,							  pj_bool_t *cont)){    /* Determine which transports and addresses to send the response,     * based on Section 18.2.2 of RFC 3261.     */    pjsip_send_state *send_state;    pj_status_t status;    /* Create structure to keep the sending state. */    send_state = pj_pool_zalloc(tdata->pool, sizeof(pjsip_send_state));    send_state->endpt = endpt;    send_state->tdata = tdata;    send_state->token = token;    send_state->app_cb = cb;    if (res_addr->transport != NULL) {	send_state->cur_transport = res_addr->transport;	pjsip_transport_add_ref(send_state->cur_transport);	status = pjsip_transport_send( send_state->cur_transport, tdata, 				       &res_addr->addr,				       res_addr->addr_len,				       send_state,				       &send_response_transport_cb );	if (status == PJ_SUCCESS) {	    pj_ssize_t sent = tdata->buf.cur - tdata->buf.start;	    send_response_transport_cb(send_state, tdata, sent);	    return PJ_SUCCESS;	} else if (status == PJ_EPENDING) {	    /* Callback will be called later. */	    return PJ_SUCCESS;	} else {	    pjsip_transport_dec_ref(send_state->cur_transport);	    return status;	}    } else {	pjsip_endpt_resolve(endpt, tdata->pool, &res_addr->dst_host, 			    send_state, &send_response_resolver_cb);	return PJ_SUCCESS;    }}/* * Send response combo */PJ_DEF(pj_status_t) pjsip_endpt_send_response2( pjsip_endpoint *endpt,					        pjsip_rx_data *rdata,					        pjsip_tx_data *tdata,						void *token,						void (*cb)(pjsip_send_state*,							   pj_ssize_t sent,							   pj_bool_t *cont)){    pjsip_response_addr res_addr;    pj_status_t status;    status = pjsip_get_response_addr(tdata->pool, rdata, &res_addr);    if (status != PJ_SUCCESS) {	pjsip_tx_data_dec_ref(tdata);	return PJ_SUCCESS;    }    status = pjsip_endpt_send_response(endpt, &res_addr, tdata, token, cb);    return status;}/* * Send response */PJ_DEF(pj_status_t) pjsip_endpt_respond_stateless( pjsip_endpoint *endpt,						   pjsip_rx_data *rdata,						   int st_code,						   const pj_str_t *st_text,						   const pjsip_hdr *hdr_list,						   const pjsip_msg_body *body){    pj_status_t status;    pjsip_response_addr res_addr;    pjsip_tx_data *tdata;    /* Verify arguments. */    PJ_ASSERT_RETURN(endpt && rdata, PJ_EINVAL);    PJ_ASSERT_RETURN(rdata->msg_info.msg->type == PJSIP_REQUEST_MSG,		     PJSIP_ENOTREQUESTMSG);    /* Check that no UAS transaction has been created for this request.      * If UAS transaction has been created for this request, application     * MUST send the response statefully using that transaction.     */    PJ_ASSERT_RETURN(pjsip_rdata_get_tsx(rdata)==NULL, PJ_EINVALIDOP);    /* Create response message */    status = pjsip_endpt_create_response( endpt, rdata, st_code, st_text, 					  &tdata);    if (status != PJ_SUCCESS)	return status;    /* Add the message headers, if any */    if (hdr_list) {	const pjsip_hdr *hdr = hdr_list->next;	while (hdr != hdr_list) {	    pjsip_msg_add_hdr( tdata->msg, pjsip_hdr_clone(tdata->pool, hdr) );	    hdr = hdr->next;	}    }    /* Add the message body, if any. */    if (body) {	tdata->msg->body = pjsip_msg_body_clone( tdata->pool, body );	if (tdata->msg->body == NULL) {	    pjsip_tx_data_dec_ref(tdata);	    return status;	}    }    /* Get where to send request. */    status = pjsip_get_response_addr( tdata->pool, rdata, &res_addr );    if (status != PJ_SUCCESS) {	pjsip_tx_data_dec_ref(tdata);	return status;    }    /* Send! */    status = pjsip_endpt_send_response( endpt, &res_addr, tdata, NULL, NULL );    return status;}/* * Get the event string from the event ID. */PJ_DEF(const char *) pjsip_event_str(pjsip_event_id_e e){    return event_str[e];}

⌨️ 快捷键说明

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