亚洲欧美第一页_禁久久精品乱码_粉嫩av一区二区三区免费野_久草精品视频

? 歡迎來到蟲蟲下載站! | ?? 資源下載 ?? 資源專輯 ?? 關于我們
? 蟲蟲下載站

?? stun_transaction.c

?? 一個開源的sip源代碼
?? C
字號:
/* $Id: stun_transaction.c 1275 2007-05-15 10:42:56Z bennylp $ */
/* 
 * Copyright (C) 2003-2005 Benny Prijono <benny@prijono.org>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
 */
#include <pjnath/stun_transaction.h>
#include <pjnath/errno.h>
#include <pj/assert.h>
#include <pj/log.h>
#include <pj/pool.h>
#include <pj/string.h>
#include <pj/timer.h>


#define TIMER_ACTIVE		1


struct pj_stun_client_tsx
{
    char		 obj_name[PJ_MAX_OBJ_NAME];
    pj_stun_config	*cfg;
    pj_stun_tsx_cb	 cb;
    void		*user_data;

    pj_bool_t		 complete;

    pj_bool_t		 require_retransmit;
    pj_timer_entry	 retransmit_timer;
    unsigned		 transmit_count;
    pj_time_val		 retransmit_time;

    pj_timer_entry	 destroy_timer;

    void		*last_pkt;
    unsigned		 last_pkt_size;
};


static void retransmit_timer_callback(pj_timer_heap_t *timer_heap, 
				      pj_timer_entry *timer);
static void destroy_timer_callback(pj_timer_heap_t *timer_heap, 
				   pj_timer_entry *timer);

#define stun_perror(tsx,msg,rc) pjnath_perror(tsx->obj_name, msg, rc)

/*
 * Create a STUN client transaction.
 */
PJ_DEF(pj_status_t) pj_stun_client_tsx_create(pj_stun_config *cfg,
					      pj_pool_t *pool,
					      const pj_stun_tsx_cb *cb,
					      pj_stun_client_tsx **p_tsx)
{
    pj_stun_client_tsx *tsx;

    PJ_ASSERT_RETURN(cfg && cb && p_tsx, PJ_EINVAL);
    PJ_ASSERT_RETURN(cb->on_send_msg, PJ_EINVAL);

    tsx = PJ_POOL_ZALLOC_T(pool, pj_stun_client_tsx);
    tsx->cfg = cfg;
    pj_memcpy(&tsx->cb, cb, sizeof(*cb));

    tsx->retransmit_timer.cb = &retransmit_timer_callback;
    tsx->retransmit_timer.user_data = tsx;

    tsx->destroy_timer.cb = &destroy_timer_callback;
    tsx->destroy_timer.user_data = tsx;

    pj_ansi_snprintf(tsx->obj_name, sizeof(tsx->obj_name), "stuntsx%p", tsx);

    *p_tsx = tsx;

    PJ_LOG(5,(tsx->obj_name, "STUN client transaction created"));
    return PJ_SUCCESS;
}


PJ_DEF(pj_status_t) 
pj_stun_client_tsx_schedule_destroy(pj_stun_client_tsx *tsx,
				    const pj_time_val *delay)
{
    pj_status_t status;

    PJ_ASSERT_RETURN(tsx && delay, PJ_EINVAL);
    PJ_ASSERT_RETURN(tsx->cb.on_destroy, PJ_EINVAL);

    /* Cancel previously registered timer */
    if (tsx->destroy_timer.id != 0) {
	pj_timer_heap_cancel(tsx->cfg->timer_heap, &tsx->destroy_timer);
	tsx->destroy_timer.id = 0;
    }

    /* Stop retransmission, just in case */
    if (tsx->retransmit_timer.id != 0) {
	pj_timer_heap_cancel(tsx->cfg->timer_heap, &tsx->retransmit_timer);
	tsx->retransmit_timer.id = 0;
    }

    status = pj_timer_heap_schedule(tsx->cfg->timer_heap,
				    &tsx->destroy_timer, delay);
    if (status != PJ_SUCCESS)
	return status;

    tsx->destroy_timer.id = TIMER_ACTIVE;

    return PJ_SUCCESS;
}


/*
 * Destroy transaction immediately.
 */
PJ_DEF(pj_status_t) pj_stun_client_tsx_destroy(pj_stun_client_tsx *tsx)
{
    PJ_ASSERT_RETURN(tsx, PJ_EINVAL);

    if (tsx->retransmit_timer.id != 0) {
	pj_timer_heap_cancel(tsx->cfg->timer_heap, &tsx->retransmit_timer);
	tsx->retransmit_timer.id = 0;
    }
    if (tsx->destroy_timer.id != 0) {
	pj_timer_heap_cancel(tsx->cfg->timer_heap, &tsx->destroy_timer);
	tsx->destroy_timer.id = 0;
    }

    PJ_LOG(5,(tsx->obj_name, "STUN client transaction destroyed"));
    return PJ_SUCCESS;
}


/*
 * Check if transaction has completed.
 */
PJ_DEF(pj_bool_t) pj_stun_client_tsx_is_complete(pj_stun_client_tsx *tsx)
{
    PJ_ASSERT_RETURN(tsx, PJ_FALSE);
    return tsx->complete;
}


/*
 * Set user data.
 */
PJ_DEF(pj_status_t) pj_stun_client_tsx_set_data(pj_stun_client_tsx *tsx,
						void *data)
{
    PJ_ASSERT_RETURN(tsx, PJ_EINVAL);
    tsx->user_data = data;
    return PJ_SUCCESS;
}


/*
 * Get the user data
 */
PJ_DEF(void*) pj_stun_client_tsx_get_data(pj_stun_client_tsx *tsx)
{
    PJ_ASSERT_RETURN(tsx, NULL);
    return tsx->user_data;
}


/*
 * Transmit message.
 */
static pj_status_t tsx_transmit_msg(pj_stun_client_tsx *tsx)
{
    pj_status_t status;

    PJ_ASSERT_RETURN(tsx->retransmit_timer.id == 0, PJ_EBUSY);

    if (tsx->require_retransmit) {
	/* Calculate retransmit/timeout delay */
	if (tsx->transmit_count == 0) {
	    tsx->retransmit_time.sec = 0;
	    tsx->retransmit_time.msec = tsx->cfg->rto_msec;

	} else if (tsx->transmit_count < PJ_STUN_MAX_TRANSMIT_COUNT-1) {
	    unsigned msec;

	    msec = PJ_TIME_VAL_MSEC(tsx->retransmit_time);
	    msec <<= 1;
	    tsx->retransmit_time.sec = msec / 1000;
	    tsx->retransmit_time.msec = msec % 1000;

	} else {
	    tsx->retransmit_time.sec = PJ_STUN_TIMEOUT_VALUE / 1000;
	    tsx->retransmit_time.msec = PJ_STUN_TIMEOUT_VALUE % 1000;
	}

	/* Schedule timer first because when send_msg() failed we can
	 * cancel it (as opposed to when schedule_timer() failed we cannot
	 * cancel transmission).
	 */;
	status = pj_timer_heap_schedule(tsx->cfg->timer_heap, 
					&tsx->retransmit_timer,
					&tsx->retransmit_time);
	if (status != PJ_SUCCESS) {
	    tsx->retransmit_timer.id = 0;
	    return status;
	}
	tsx->retransmit_timer.id = TIMER_ACTIVE;
    }


    tsx->transmit_count++;

    PJ_LOG(5,(tsx->obj_name, "STUN sending message (transmit count=%d)",
	      tsx->transmit_count));

    /* Send message */
    status = tsx->cb.on_send_msg(tsx, tsx->last_pkt, tsx->last_pkt_size);
    if (status != PJ_SUCCESS) {
	if (tsx->retransmit_timer.id != 0) {
	    pj_timer_heap_cancel(tsx->cfg->timer_heap, 
				 &tsx->retransmit_timer);
	    tsx->retransmit_timer.id = 0;
	}
	stun_perror(tsx, "STUN error sending message", status);
	return status;
    }

    return status;
}


/*
 * Send outgoing message and start STUN transaction.
 */
PJ_DEF(pj_status_t) pj_stun_client_tsx_send_msg(pj_stun_client_tsx *tsx,
						pj_bool_t retransmit,
						void *pkt,
						unsigned pkt_len)
{
    PJ_ASSERT_RETURN(tsx && pkt && pkt_len, PJ_EINVAL);
    PJ_ASSERT_RETURN(tsx->retransmit_timer.id == 0, PJ_EBUSY);

    /* Encode message */
    tsx->last_pkt = pkt;
    tsx->last_pkt_size = pkt_len;

    /* Update STUN retransmit flag */
    tsx->require_retransmit = retransmit;

    /* Send the message */
    return tsx_transmit_msg(tsx);
}


/* Retransmit timer callback */
static void retransmit_timer_callback(pj_timer_heap_t *timer_heap, 
				      pj_timer_entry *timer)
{
    pj_stun_client_tsx *tsx = (pj_stun_client_tsx *) timer->user_data;
    pj_status_t status;

    PJ_UNUSED_ARG(timer_heap);

    if (tsx->transmit_count >= PJ_STUN_MAX_TRANSMIT_COUNT) {
	/* Retransmission count exceeded. Transaction has failed */
	tsx->retransmit_timer.id = 0;
	PJ_LOG(4,(tsx->obj_name, "STUN timeout waiting for response"));
	if (!tsx->complete) {
	    tsx->complete = PJ_TRUE;
	    if (tsx->cb.on_complete) {
		tsx->cb.on_complete(tsx, PJNATH_ESTUNTIMEDOUT, NULL, NULL, 0);
	    }
	}
	return;
    }

    tsx->retransmit_timer.id = 0;
    status = tsx_transmit_msg(tsx);
    if (status != PJ_SUCCESS) {
	tsx->retransmit_timer.id = 0;
	if (!tsx->complete) {
	    tsx->complete = PJ_TRUE;
	    if (tsx->cb.on_complete) {
		tsx->cb.on_complete(tsx, status, NULL, NULL, 0);
	    }
	}
    }
}

/*
 * Request to retransmit the request.
 */
PJ_DEF(pj_status_t) pj_stun_client_tsx_retransmit(pj_stun_client_tsx *tsx)
{
    if (tsx->destroy_timer.id != 0) {
	return PJ_SUCCESS;
    }

    if (tsx->retransmit_timer.id != 0) {
	pj_timer_heap_cancel(tsx->cfg->timer_heap, &tsx->retransmit_timer);
	tsx->retransmit_timer.id = 0;
    }

    return tsx_transmit_msg(tsx);
}

/* Timer callback to destroy transaction */
static void destroy_timer_callback(pj_timer_heap_t *timer_heap, 
				   pj_timer_entry *timer)
{
    pj_stun_client_tsx *tsx = (pj_stun_client_tsx *) timer->user_data;

    PJ_UNUSED_ARG(timer_heap);

    tsx->destroy_timer.id = PJ_FALSE;
    tsx->cb.on_destroy(tsx);
    /* Don't access transaction after this */
}


/*
 * Notify the STUN transaction about the arrival of STUN response.
 */
PJ_DEF(pj_status_t) pj_stun_client_tsx_on_rx_msg(pj_stun_client_tsx *tsx,
						 const pj_stun_msg *msg,
						 const pj_sockaddr_t *src_addr,
						 unsigned src_addr_len)
{
    pj_stun_errcode_attr *err_attr;
    pj_status_t status;

    /* Must be STUN response message */
    if (!PJ_STUN_IS_SUCCESS_RESPONSE(msg->hdr.type) && 
	!PJ_STUN_IS_ERROR_RESPONSE(msg->hdr.type))
    {
	PJ_LOG(4,(tsx->obj_name, 
		  "STUN rx_msg() error: not response message"));
	return PJNATH_EINSTUNMSGTYPE;
    }


    /* We have a response with matching transaction ID. 
     * We can cancel retransmit timer now.
     */
    if (tsx->retransmit_timer.id) {
	pj_timer_heap_cancel(tsx->cfg->timer_heap, &tsx->retransmit_timer);
	tsx->retransmit_timer.id = 0;
    }

    /* Find STUN error code attribute */
    err_attr = (pj_stun_errcode_attr*) 
		pj_stun_msg_find_attr(msg, PJ_STUN_ATTR_ERROR_CODE, 0);

    if (err_attr && err_attr->err_code <= 200) {
	/* draft-ietf-behave-rfc3489bis-05.txt Section 8.3.2:
	 * Any response between 100 and 299 MUST result in the cessation
	 * of request retransmissions, but otherwise is discarded.
	 */
	PJ_LOG(4,(tsx->obj_name, 
		  "STUN rx_msg() error: received provisional %d code (%.*s)",
		  err_attr->err_code,
		  (int)err_attr->reason.slen,
		  err_attr->reason.ptr));
	return PJ_SUCCESS;
    }

    if (err_attr == NULL) {
	status = PJ_SUCCESS;
    } else {
	status = PJ_STATUS_FROM_STUN_CODE(err_attr->err_code);
    }

    /* Call callback */
    if (!tsx->complete) {
	tsx->complete = PJ_TRUE;
	if (tsx->cb.on_complete) {
	    tsx->cb.on_complete(tsx, status, msg, src_addr, src_addr_len);
	}
    }

    return PJ_SUCCESS;

}

?? 快捷鍵說明

復制代碼 Ctrl + C
搜索代碼 Ctrl + F
全屏模式 F11
切換主題 Ctrl + Shift + D
顯示快捷鍵 ?
增大字號 Ctrl + =
減小字號 Ctrl + -
亚洲欧美第一页_禁久久精品乱码_粉嫩av一区二区三区免费野_久草精品视频
成人深夜在线观看| 一区二区三区蜜桃| 日韩精品一区二区三区中文不卡 | 亚洲欧洲另类国产综合| 久久久久亚洲蜜桃| 久久在线免费观看| 精品处破学生在线二十三| www国产精品av| 久久久一区二区| 中文字幕在线视频一区| 亚洲视频一区二区在线| 亚洲永久免费av| 丝袜亚洲另类丝袜在线| 青青草视频一区| 韩国精品在线观看| 国产激情视频一区二区在线观看 | 国产精品久久三| 亚洲视频一区二区在线| 午夜视频久久久久久| 蜜桃精品视频在线| 国产精品影视天天线| 成人午夜精品一区二区三区| 色综合久久99| 4hu四虎永久在线影院成人| 久久综合中文字幕| 亚洲视频一区二区免费在线观看| 亚欧色一区w666天堂| 精品一区中文字幕| 99久久免费精品| 欧美一区二区福利视频| 国产色产综合产在线视频| 亚洲美女视频在线观看| 久久不见久久见免费视频1| 成人免费三级在线| 欧美一区午夜视频在线观看| 国产日产欧美一区二区三区| 一区二区三区四区激情| 国产在线播放一区二区三区| 欧美不卡视频一区| 亚洲精品免费电影| 国产成人av资源| 欧美一区二区性放荡片| 亚洲免费看黄网站| 国产一区二区三区免费观看| 欧美日韩在线免费视频| 国产欧美日韩卡一| 老司机午夜精品| 欧美日韩亚洲国产综合| 中文无字幕一区二区三区| 日本成人在线一区| 99re这里都是精品| 久久蜜桃av一区二区天堂| 日本中文字幕一区| 欧美午夜精品久久久久久超碰| 欧美高清一级片在线观看| 美女视频黄a大片欧美| 欧美性生交片4| 亚洲色欲色欲www| 国产盗摄视频一区二区三区| 欧美一区二区网站| 日本在线不卡视频一二三区| 一本一道波多野结衣一区二区| 久久亚洲精精品中文字幕早川悠里 | 亚洲国产精品成人综合色在线婷婷| 午夜不卡av在线| 欧美综合视频在线观看| 亚洲精品高清在线| 99国产精品久久久久久久久久久| 欧美国产成人在线| 国产91丝袜在线播放九色| 亚洲精品一区二区在线观看| 天堂在线一区二区| 欧美一区三区二区| 日本不卡一区二区| 欧美一区二区三区公司| 日韩电影在线观看一区| 91精品国产一区二区三区香蕉| 图片区小说区区亚洲影院| 欧美日韩精品欧美日韩精品一| 亚洲aaa精品| 日韩欧美国产电影| 国产在线精品一区二区| 久久久久久久久久久久电影| 成人黄色小视频| 亚洲九九爱视频| 欧美人xxxx| 免费的成人av| 国产日韩精品一区二区三区在线| 国产福利不卡视频| 亚洲人成人一区二区在线观看| 色欧美88888久久久久久影院| 夜夜操天天操亚洲| 91精品久久久久久久99蜜桃| 国模冰冰炮一区二区| 蜜臀av性久久久久蜜臀aⅴ流畅| 7799精品视频| 国产成人精品免费网站| 一区二区三区久久久| 欧美日韩国产中文| 国产在线精品一区在线观看麻豆| 亚洲国产精品成人综合| 欧美亚洲动漫精品| 久久99国产精品免费网站| 国产拍欧美日韩视频二区| 欧美性受极品xxxx喷水| 久久精品国产99久久6| 亚洲日本va在线观看| 91精品视频网| 一本色道久久综合亚洲aⅴ蜜桃 | 日韩精品一区二区三区中文不卡 | 久久不见久久见中文字幕免费| 亚洲国产精品成人综合| 欧美女孩性生活视频| 国产一区二区三区综合| 亚洲成人www| 亚洲国产精品精华液ab| 在线成人小视频| 粗大黑人巨茎大战欧美成人| 天天操天天干天天综合网| 欧美国产精品一区二区| 日韩欧美国产三级电影视频| 在线中文字幕一区| 国产suv精品一区二区三区| 午夜国产不卡在线观看视频| 国产亚洲欧美色| 欧美精品丝袜中出| 97久久人人超碰| 国产伦精一区二区三区| 日本在线播放一区二区三区| 亚洲乱码日产精品bd| 国产日韩av一区| 精品成人一区二区三区四区| 在线不卡a资源高清| 91久久香蕉国产日韩欧美9色| 国产成人精品午夜视频免费| 久久99久国产精品黄毛片色诱| 亚洲第一激情av| 亚洲午夜久久久久久久久电影网 | 日韩精品1区2区3区| 夜夜精品浪潮av一区二区三区| 欧美国产精品专区| 欧美激情自拍偷拍| 国产亚洲欧美色| 欧美国产在线观看| 国产色婷婷亚洲99精品小说| 久久综合久色欧美综合狠狠| 日韩欧美一级片| 日韩三级电影网址| 日韩免费电影一区| 91精品国产福利| 欧美一区二区国产| 欧美成人一区二区三区片免费| 51精品秘密在线观看| 中文字幕免费一区| 国产精品久久久久久久久晋中 | 91精品国产综合久久久久久| 欧美又粗又大又爽| 欧美亚洲高清一区| 欧美一区二区视频观看视频| 欧美老年两性高潮| 欧美成人a∨高清免费观看| 精品国产乱码久久久久久蜜臀| 精品福利在线导航| 欧美韩国日本一区| 亚洲精品免费在线观看| 天天做天天摸天天爽国产一区| 午夜日韩在线电影| 韩国三级中文字幕hd久久精品| 国产一区二区h| 99国内精品久久| 欧美肥胖老妇做爰| 国产午夜精品一区二区三区四区| 欧美韩国日本不卡| 午夜欧美大尺度福利影院在线看 | 成熟亚洲日本毛茸茸凸凹| 99精品在线观看视频| 欧美少妇性性性| 欧美精品一区二区三区高清aⅴ| 国产欧美一区视频| 亚洲bdsm女犯bdsm网站| 国产精品一区二区男女羞羞无遮挡 | 欧美一区二区三区在线| 国产午夜一区二区三区| 亚洲久本草在线中文字幕| 免费av成人在线| 99视频一区二区| 日韩亚洲欧美在线观看| 国产精品剧情在线亚洲| 亚洲图片欧美色图| 国产suv精品一区二区883| 欧美午夜一区二区三区免费大片| 精品福利一区二区三区| 亚洲午夜电影网| 丁香桃色午夜亚洲一区二区三区| 欧美在线视频不卡| 亚洲国产成人在线| 蜜桃精品视频在线观看| 欧美亚洲综合色| 欧美国产精品v| 免费美女久久99|