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

📄 sip_endpoint.c

📁 一个开源的sip源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
 */
static void endpt_on_rx_msg( pjsip_endpoint *endpt,
				      pj_status_t status,
				      pjsip_rx_data *rdata )
{
    pjsip_msg *msg = rdata->msg_info.msg;

    if (status != PJ_SUCCESS) {
	char info[30];
	char errmsg[PJ_ERR_MSG_SIZE];

	info[0] = '\0';

	if (status == PJSIP_EMISSINGHDR) {
	    pj_str_t p;

	    p.ptr = info; p.slen = 0;

	    if (rdata->msg_info.cid == NULL || rdata->msg_info.cid->id.slen)
		pj_strcpy2(&p, "Call-ID");
	    if (rdata->msg_info.from == NULL)
		pj_strcpy2(&p, " From");
	    if (rdata->msg_info.to == NULL)
		pj_strcpy2(&p, " To");
	    if (rdata->msg_info.via == NULL)
		pj_strcpy2(&p, " Via");
	    if (rdata->msg_info.cseq == NULL) 
		pj_strcpy2(&p, " CSeq");

	    p.ptr[p.slen] = '\0';
	}

	pj_strerror(status, errmsg, sizeof(errmsg));

	PJ_LOG(1, (THIS_FILE, 
		  "Error processing packet from %s:%d: %s %s [code %d]:\n"
		  "%.*s\n"
		  "-- end of packet.",
		  rdata->pkt_info.src_name, 
		  rdata->pkt_info.src_port,
		  errmsg,
		  info,
		  status,
		  (int)rdata->msg_info.len,	
		  rdata->msg_info.msg_buf));
	return;
    }

    PJ_LOG(5, (THIS_FILE, "Processing incoming message: %s", 
	       pjsip_rx_data_get_info(rdata)));

    /* For response, check that the value in Via sent-by match the transport.
     * If not matched, silently drop the response.
     * Ref: RFC3261 Section 18.1.2 Receiving Response
     */
    if (msg->type == PJSIP_RESPONSE_MSG) {
	const pj_str_t *local_addr;
	int port = rdata->msg_info.via->sent_by.port;
	pj_bool_t mismatch = PJ_FALSE;
	if (port == 0) {
	    pjsip_transport_type_e type;
	    type = (pjsip_transport_type_e)rdata->tp_info.transport->key.type;
	    port = pjsip_transport_get_default_port_for_type(type);
	}
	local_addr = &rdata->tp_info.transport->local_name.host;

	if (pj_strcmp(&rdata->msg_info.via->sent_by.host, local_addr) != 0) {

	    /* The RFC says that we should drop response when sent-by
	     * address mismatch. But it could happen (e.g. with SER) when
	     * endpoint with private IP is sending request to public
	     * server.

	    mismatch = PJ_TRUE;

	     */

	} else if (port != rdata->tp_info.transport->local_name.port) {
	    /* Port or address mismatch, we should discard response */
	    /* But we saw one implementation (we don't want to name it to 
	     * protect the innocence) which put wrong sent-by port although
	     * the "rport" parameter is correct.
	     * So we discard the response only if the port doesn't match
	     * both the port in sent-by and rport. We try to be lenient here!
	     */
	    if (rdata->msg_info.via->rport_param != 
		rdata->tp_info.transport->local_name.port)
		mismatch = PJ_TRUE;
	    else {
		PJ_LOG(4,(THIS_FILE, "Message %s from %s has mismatch port in "
				     "sent-by but the rport parameter is "
				     "correct",
				     pjsip_rx_data_get_info(rdata), 
				     rdata->pkt_info.src_name));
	    }
	}

	if (mismatch) {
	    PJ_TODO(ENDPT_REPORT_WHEN_DROPPING_MESSAGE);
	    PJ_LOG(4,(THIS_FILE, "Dropping response %s from %s:%d because "
				 "sent-by is mismatch", 
				 pjsip_rx_data_get_info(rdata),
				 rdata->pkt_info.src_name, 
				 rdata->pkt_info.src_port));
	    return;
	}
    }


    /* Distribute to modules, starting from modules with highest priority */
    LOCK_MODULE_ACCESS(endpt);

    if (msg->type == PJSIP_REQUEST_MSG) {
	pjsip_module *mod;
	pj_bool_t handled = PJ_FALSE;

	mod = endpt->module_list.next;
	while (mod != &endpt->module_list) {
	    if (mod->on_rx_request)
		handled = (*mod->on_rx_request)(rdata);
	    if (handled)
		break;
	    mod = mod->next;
	}

	/* No module is able to handle the request. */
	if (!handled) {
	    PJ_TODO(ENDPT_RESPOND_UNHANDLED_REQUEST);
	    PJ_LOG(4,(THIS_FILE, "Message %s from %s:%d was dropped/unhandled by"
				 " any modules",
				 pjsip_rx_data_get_info(rdata),
				 rdata->pkt_info.src_name,
				 rdata->pkt_info.src_port));
	}

    } else {
	pjsip_module *mod;
	pj_bool_t handled = PJ_FALSE;

	mod = endpt->module_list.next;
	while (mod != &endpt->module_list) {
	    if (mod->on_rx_response)
		handled = (*mod->on_rx_response)(rdata);
	    if (handled)
		break;
	    mod = mod->next;
	}

	if (!handled) {
	    PJ_LOG(4,(THIS_FILE, "Message %s from %s:%d was dropped/unhandled"
				 " by any modules",
				 pjsip_rx_data_get_info(rdata),
				 rdata->pkt_info.src_name,
				 rdata->pkt_info.src_port));
	}
    }

    UNLOCK_MODULE_ACCESS(endpt);

    /* Must clear mod_data before returning rdata to transport, since
     * rdata may be reused.
     */
    pj_bzero(&rdata->endpt_info, sizeof(rdata->endpt_info));
}

/*
 * This callback is called by transport manager before message is sent.
 * Modules may inspect the message before it's actually sent.
 */
static pj_status_t endpt_on_tx_msg( pjsip_endpoint *endpt,
				    pjsip_tx_data *tdata )
{
    pj_status_t status = PJ_SUCCESS;
    pjsip_module *mod;

    /* Distribute to modules, starting from modules with LOWEST priority */
    LOCK_MODULE_ACCESS(endpt);

    mod = endpt->module_list.prev;
    if (tdata->msg->type == PJSIP_REQUEST_MSG) {
	while (mod != &endpt->module_list) {
	    if (mod->on_tx_request)
		status = (*mod->on_tx_request)(tdata);
	    if (status != PJ_SUCCESS)
		break;
	    mod = mod->prev;
	}

    } else {
	while (mod != &endpt->module_list) {
	    if (mod->on_tx_response)
		status = (*mod->on_tx_response)(tdata);
	    if (status != PJ_SUCCESS)
		break;
	    mod = mod->prev;
	}
    }

    UNLOCK_MODULE_ACCESS(endpt);

    return status;
}


/*
 * Create transmit data buffer.
 */
PJ_DEF(pj_status_t) pjsip_endpt_create_tdata(  pjsip_endpoint *endpt,
					       pjsip_tx_data **p_tdata)
{
    return pjsip_tx_data_create(endpt->transport_mgr, p_tdata);
}

/*
 * Create the DNS resolver instance. 
 */
PJ_DEF(pj_status_t) pjsip_endpt_create_resolver(pjsip_endpoint *endpt,
						pj_dns_resolver **p_resv)
{
#if PJSIP_HAS_RESOLVER
    PJ_ASSERT_RETURN(endpt && p_resv, PJ_EINVAL);
    return pj_dns_resolver_create( endpt->pf, NULL, 0, endpt->timer_heap,
				   endpt->ioqueue, p_resv);
#else
    PJ_UNUSED_ARG(endpt);
    PJ_UNUSED_ARG(p_resv);
    pj_assert(!"Resolver is disabled (PJSIP_HAS_RESOLVER==0)");
    return PJ_EINVALIDOP;
#endif
}

/*
 * Set DNS resolver to be used by the SIP resolver.
 */
PJ_DEF(pj_status_t) pjsip_endpt_set_resolver( pjsip_endpoint *endpt,
					      pj_dns_resolver *resv)
{
    return pjsip_resolver_set_resolver(endpt->resolver, resv);
}

/*
 * Get the DNS resolver being used by the SIP resolver.
 */
PJ_DEF(pj_dns_resolver*) pjsip_endpt_get_resolver(pjsip_endpoint *endpt)
{
    PJ_ASSERT_RETURN(endpt, NULL);
    return pjsip_resolver_get_resolver(endpt->resolver);
}

/*
 * Resolve
 */
PJ_DEF(void) pjsip_endpt_resolve( pjsip_endpoint *endpt,
				  pj_pool_t *pool,
				  pjsip_host_info *target,
				  void *token,
				  pjsip_resolver_callback *cb)
{
    pjsip_resolve( endpt->resolver, pool, target, token, cb);
}

/*
 * Get transport manager.
 */
PJ_DEF(pjsip_tpmgr*) pjsip_endpt_get_tpmgr(pjsip_endpoint *endpt)
{
    return endpt->transport_mgr;
}

/*
 * Get ioqueue instance.
 */
PJ_DEF(pj_ioqueue_t*) pjsip_endpt_get_ioqueue(pjsip_endpoint *endpt)
{
    return endpt->ioqueue;
}

/*
 * Find/create transport.
 */
PJ_DEF(pj_status_t) pjsip_endpt_acquire_transport(pjsip_endpoint *endpt,
						  pjsip_transport_type_e type,
						  const pj_sockaddr_t *remote,
						  int addr_len,
						  const pjsip_tpselector *sel,
						  pjsip_transport **transport)
{
    return pjsip_tpmgr_acquire_transport(endpt->transport_mgr, type, 
					 remote, addr_len, sel, transport);
}


/*
 * Report error.
 */
PJ_DEF(void) pjsip_endpt_log_error(  pjsip_endpoint *endpt,
				     const char *sender,
                                     pj_status_t error_code,
                                     const char *format,
                                     ... )
{
#if PJ_LOG_MAX_LEVEL > 0
    char newformat[256];
    int len;
    va_list marker;

    va_start(marker, format);

    PJ_UNUSED_ARG(endpt);

    len = pj_ansi_strlen(format);
    if (len < (int)sizeof(newformat)-30) {
	pj_str_t errstr;

	pj_ansi_strcpy(newformat, format);
	pj_ansi_snprintf(newformat+len, sizeof(newformat)-len-1,
			 ": [err %d] ", error_code);
	len += pj_ansi_strlen(newformat+len);

	errstr = pj_strerror( error_code, newformat+len, 
			      sizeof(newformat)-len-1);

	len += errstr.slen;
	newformat[len] = '\0';

	pj_log(sender, 1, newformat, marker);
    } else {
	pj_log(sender, 1, format, marker);
    }

    va_end(marker);
#else
    PJ_UNUSED_ARG(format);
    PJ_UNUSED_ARG(error_code);
    PJ_UNUSED_ARG(sender);
    PJ_UNUSED_ARG(endpt);
#endif
}


/*
 * Dump endpoint.
 */
PJ_DEF(void) pjsip_endpt_dump( pjsip_endpoint *endpt, pj_bool_t detail )
{
#if PJ_LOG_MAX_LEVEL >= 3
    PJ_LOG(5, (THIS_FILE, "pjsip_endpt_dump()"));

    /* Lock mutex. */
    pj_mutex_lock(endpt->mutex);

    PJ_LOG(3, (THIS_FILE, "Dumping endpoint %p:", endpt));
    
    /* Dumping pool factory. */
    pj_pool_factory_dump(endpt->pf, detail);

    /* Pool health. */
    PJ_LOG(3, (THIS_FILE," Endpoint pool capacity=%u, used_size=%u",
	       pj_pool_get_capacity(endpt->pool),
	       pj_pool_get_used_size(endpt->pool)));

    /* Resolver */
#if PJSIP_HAS_RESOLVER
    if (pjsip_endpt_get_resolver(endpt)) {
	pj_dns_resolver_dump(pjsip_endpt_get_resolver(endpt), detail);
    }
#endif

    /* Transports. 
     */
    pjsip_tpmgr_dump_transports( endpt->transport_mgr );

    /* Timer. */
    PJ_LOG(3,(THIS_FILE, " Timer heap has %u entries", 
			pj_timer_heap_count(endpt->timer_heap)));

    /* Unlock mutex. */
    pj_mutex_unlock(endpt->mutex);
#else
    PJ_UNUSED_ARG(endpt);
    PJ_UNUSED_ARG(detail);
    PJ_LOG(3,(THIS_FILE, "pjsip_end_dump: can't dump because it's disabled."));
#endif
}

⌨️ 快捷键说明

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