📄 sip_reg.c
字号:
/* $Id: sip_reg.c 974 2007-02-19 01:13:53Z bennylp $ *//* * Copyright (C) 2003-2007 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 <pjsip-ua/sip_regc.h>#include <pjsip/sip_endpoint.h>#include <pjsip/sip_parser.h>#include <pjsip/sip_module.h>#include <pjsip/sip_transaction.h>#include <pjsip/sip_event.h>#include <pjsip/sip_util.h>#include <pjsip/sip_auth_msg.h>#include <pjsip/sip_errno.h>#include <pj/assert.h>#include <pj/guid.h>#include <pj/os.h>#include <pj/pool.h>#include <pj/log.h>#include <pj/rand.h>#include <pj/string.h>#define REFRESH_TIMER 1#define DELAY_BEFORE_REFRESH 5#define THIS_FILE "sip_regc.c"/* Outgoing transaction timeout when server sends 100 but never replies * with final response. Value is in MILISECONDS! */#define REGC_TSX_TIMEOUT 33000/** * SIP client registration structure. */struct pjsip_regc{ pj_pool_t *pool; pjsip_endpoint *endpt; pj_bool_t _delete_flag; pj_bool_t has_tsx; pj_int32_t busy; void *token; pjsip_regc_cb *cb; pj_str_t str_srv_url; pjsip_uri *srv_url; pjsip_cid_hdr *cid_hdr; pjsip_cseq_hdr *cseq_hdr; pj_str_t from_uri; pjsip_from_hdr *from_hdr; pjsip_to_hdr *to_hdr; char *contact_buf; pjsip_generic_string_hdr *contact_hdr; pjsip_expires_hdr *expires_hdr; pjsip_contact_hdr *unreg_contact_hdr; pjsip_expires_hdr *unreg_expires_hdr; pj_uint32_t expires; pjsip_route_hdr route_set; pjsip_hdr hdr_list; /* Authorization sessions. */ pjsip_auth_clt_sess auth_sess; /* Auto refresh registration. */ pj_bool_t auto_reg; pj_time_val last_reg; pj_time_val next_reg; pj_timer_entry timer; /* Transport selector */ pjsip_tpselector tp_sel;};PJ_DEF(pj_status_t) pjsip_regc_create( pjsip_endpoint *endpt, void *token, pjsip_regc_cb *cb, pjsip_regc **p_regc){ pj_pool_t *pool; pjsip_regc *regc; pj_status_t status; /* Verify arguments. */ PJ_ASSERT_RETURN(endpt && cb && p_regc, PJ_EINVAL); pool = pjsip_endpt_create_pool(endpt, "regc%p", 1024, 1024); PJ_ASSERT_RETURN(pool != NULL, PJ_ENOMEM); regc = pj_pool_zalloc(pool, sizeof(struct pjsip_regc)); regc->pool = pool; regc->endpt = endpt; regc->token = token; regc->cb = cb; regc->contact_buf = pj_pool_alloc(pool, PJSIP_REGC_CONTACT_BUF_SIZE); regc->expires = PJSIP_REGC_EXPIRATION_NOT_SPECIFIED; status = pjsip_auth_clt_init(®c->auth_sess, endpt, regc->pool, 0); if (status != PJ_SUCCESS) return status; pj_list_init(®c->route_set); pj_list_init(®c->hdr_list); /* Done */ *p_regc = regc; return PJ_SUCCESS;}PJ_DEF(pj_status_t) pjsip_regc_destroy(pjsip_regc *regc){ PJ_ASSERT_RETURN(regc, PJ_EINVAL); if (regc->has_tsx || regc->busy) { regc->_delete_flag = 1; regc->cb = NULL; } else { pjsip_tpselector_dec_ref(®c->tp_sel); pjsip_endpt_release_pool(regc->endpt, regc->pool); } return PJ_SUCCESS;}PJ_DEF(pj_status_t) pjsip_regc_get_info( pjsip_regc *regc, pjsip_regc_info *info ){ PJ_ASSERT_RETURN(regc && info, PJ_EINVAL); info->server_uri = regc->str_srv_url; info->client_uri = regc->from_uri; info->is_busy = (regc->busy || regc->has_tsx); info->auto_reg = regc->auto_reg; info->interval = regc->expires; if (regc->has_tsx) info->next_reg = 0; else if (regc->auto_reg == 0) info->next_reg = 0; else if (regc->expires < 0) info->next_reg = regc->expires; else { pj_time_val now, next_reg; next_reg = regc->next_reg; pj_gettimeofday(&now); PJ_TIME_VAL_SUB(next_reg, now); info->next_reg = next_reg.sec; } return PJ_SUCCESS;}PJ_DEF(pj_pool_t*) pjsip_regc_get_pool(pjsip_regc *regc){ return regc->pool;}static void set_expires( pjsip_regc *regc, pj_uint32_t expires){ if (expires != regc->expires) { regc->expires_hdr = pjsip_expires_hdr_create(regc->pool, expires); } else { regc->expires_hdr = NULL; }}static pj_status_t set_contact( pjsip_regc *regc, int contact_cnt, const pj_str_t contact[] ){ int i; char *s; const pj_str_t contact_STR = { "Contact", 7}; /* Concatenate contacts. */ for (i=0, s=regc->contact_buf; i<contact_cnt; ++i) { if ((s-regc->contact_buf) + contact[i].slen + 2 > PJSIP_REGC_CONTACT_BUF_SIZE) { return PJSIP_EURITOOLONG; } pj_memcpy(s, contact[i].ptr, contact[i].slen); s += contact[i].slen; if (i != contact_cnt - 1) { *s++ = ','; *s++ = ' '; } } /* Set "Contact" header. */ regc->contact_hdr = pjsip_generic_string_hdr_create(regc->pool, &contact_STR, NULL); regc->contact_hdr->hvalue.ptr = regc->contact_buf; regc->contact_hdr->hvalue.slen = (s - regc->contact_buf); return PJ_SUCCESS;}PJ_DEF(pj_status_t) pjsip_regc_init( pjsip_regc *regc, const pj_str_t *srv_url, const pj_str_t *from_url, const pj_str_t *to_url, int contact_cnt, const pj_str_t contact[], pj_uint32_t expires){ pj_str_t tmp; pj_status_t status; PJ_ASSERT_RETURN(regc && srv_url && from_url && to_url && contact_cnt && contact && expires, PJ_EINVAL); /* Copy server URL. */ pj_strdup_with_null(regc->pool, ®c->str_srv_url, srv_url); /* Set server URL. */ tmp = regc->str_srv_url; regc->srv_url = pjsip_parse_uri( regc->pool, tmp.ptr, tmp.slen, 0); if (regc->srv_url == NULL) { return PJSIP_EINVALIDURI; } /* Set "From" header. */ pj_strdup_with_null(regc->pool, ®c->from_uri, from_url); tmp = regc->from_uri; regc->from_hdr = pjsip_from_hdr_create(regc->pool); regc->from_hdr->uri = pjsip_parse_uri(regc->pool, tmp.ptr, tmp.slen, PJSIP_PARSE_URI_AS_NAMEADDR); if (!regc->from_hdr->uri) { PJ_LOG(4,(THIS_FILE, "regc: invalid source URI %.*s", from_url->slen, from_url->ptr)); return PJSIP_EINVALIDURI; } /* Set "To" header. */ pj_strdup_with_null(regc->pool, &tmp, to_url); regc->to_hdr = pjsip_to_hdr_create(regc->pool); regc->to_hdr->uri = pjsip_parse_uri(regc->pool, tmp.ptr, tmp.slen, PJSIP_PARSE_URI_AS_NAMEADDR); if (!regc->to_hdr->uri) { PJ_LOG(4,(THIS_FILE, "regc: invalid target URI %.*s", to_url->slen, to_url->ptr)); return PJSIP_EINVALIDURI; } /* Set "Contact" header. */ status = set_contact( regc, contact_cnt, contact); if (status != PJ_SUCCESS) return status; /* Set "Expires" header, if required. */ set_expires( regc, expires); /* Set "Call-ID" header. */ regc->cid_hdr = pjsip_cid_hdr_create(regc->pool); pj_create_unique_string(regc->pool, ®c->cid_hdr->id); /* Set "CSeq" header. */ regc->cseq_hdr = pjsip_cseq_hdr_create(regc->pool); regc->cseq_hdr->cseq = pj_rand() % 0xFFFF; pjsip_method_set( ®c->cseq_hdr->method, PJSIP_REGISTER_METHOD); /* Create "Contact" header used in unregistration. */ regc->unreg_contact_hdr = pjsip_contact_hdr_create(regc->pool); regc->unreg_contact_hdr->star = 1; /* Create "Expires" header used in unregistration. */ regc->unreg_expires_hdr = pjsip_expires_hdr_create( regc->pool, 0); /* Done. */ return PJ_SUCCESS;}PJ_DEF(pj_status_t) pjsip_regc_set_credentials( pjsip_regc *regc, int count, const pjsip_cred_info cred[] ){ PJ_ASSERT_RETURN(regc && count && cred, PJ_EINVAL); return pjsip_auth_clt_set_credentials(®c->auth_sess, count, cred);}PJ_DEF(pj_status_t) pjsip_regc_set_route_set( pjsip_regc *regc, const pjsip_route_hdr *route_set){ const pjsip_route_hdr *chdr; PJ_ASSERT_RETURN(regc && route_set, PJ_EINVAL); pj_list_init(®c->route_set); chdr = route_set->next; while (chdr != route_set) { pj_list_push_back(®c->route_set, pjsip_hdr_clone(regc->pool, chdr)); chdr = chdr->next; } return PJ_SUCCESS;}/* * Bind client registration to a specific transport/listener. */PJ_DEF(pj_status_t) pjsip_regc_set_transport( pjsip_regc *regc, const pjsip_tpselector *sel){ PJ_ASSERT_RETURN(regc && sel, PJ_EINVAL); pjsip_tpselector_dec_ref(®c->tp_sel); pj_memcpy(®c->tp_sel, sel, sizeof(*sel)); pjsip_tpselector_add_ref(®c->tp_sel); return PJ_SUCCESS;}PJ_DEF(pj_status_t) pjsip_regc_add_headers( pjsip_regc *regc, const pjsip_hdr *hdr_list){ const pjsip_hdr *hdr; PJ_ASSERT_RETURN(regc && hdr_list, PJ_EINVAL); //This is "add" operation, so don't remove headers. //pj_list_init(®c->hdr_list); hdr = hdr_list->next; while (hdr != hdr_list) { pj_list_push_back(®c->hdr_list, pjsip_hdr_clone(regc->pool, hdr)); hdr = hdr->next; } return PJ_SUCCESS;}static pj_status_t create_request(pjsip_regc *regc, pjsip_tx_data **p_tdata){ pj_status_t status; pjsip_tx_data *tdata; PJ_ASSERT_RETURN(regc && p_tdata, PJ_EINVAL); /* Create the request. */ status = pjsip_endpt_create_request_from_hdr( regc->endpt, &pjsip_register_method, regc->srv_url, regc->from_hdr, regc->to_hdr, NULL, regc->cid_hdr, regc->cseq_hdr->cseq, NULL, &tdata); if (status != PJ_SUCCESS) return status; /* Add cached authorization headers. */ pjsip_auth_clt_init_req( ®c->auth_sess, tdata ); /* Add Route headers from route set, ideally after Via header */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -