dialog.h File Reference

sip dialog management header file More...

#include "sip.h"

Include dependency graph for dialog.h:

This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Defines

#define dialog_ref(dialog, tag)   ao2_t_bump(dialog, tag)
 when we create or delete references, make sure to use these functions so we keep track of the refcounts. To simplify the code, we allow a NULL to be passed to dialog_unref().
#define dialog_unref(dialog, tag)   ({ ao2_t_cleanup(dialog, tag); (NULL); })
#define sip_alloc(callid, addr, useglobal_nat, intended_method, req, logger_callid)   __sip_alloc(callid, addr, useglobal_nat, intended_method, req, logger_callid, __FILE__, __LINE__, __PRETTY_FUNCTION__)

Functions

int __sip_ack (struct sip_pvt *p, uint32_t seqno, int resp, int sipmethod)
 Acknowledges receipt of a packet and stops retransmission called with p locked.
struct sip_pvt__sip_alloc (ast_string_field callid, struct ast_sockaddr *sin, int useglobal_nat, const int intended_method, struct sip_request *req, ast_callid logger_callid, const char *file, int line, const char *func)
 Allocate sip_pvt structure, set defaults and link in the container. Returns a reference to the object so whoever uses it later must remember to release the reference.
void __sip_destroy (struct sip_pvt *p, int lockowner, int lockdialoglist)
 Destroy SIP call structure. Make it return NULL so the caller can do things like foo = sip_destroy(foo); and reduce the chance of bugs due to dangling pointers.
void __sip_pretend_ack (struct sip_pvt *p)
 Pretend to ack all packets called with p locked.
int __sip_semi_ack (struct sip_pvt *p, uint32_t seqno, int resp, int sipmethod)
 Acks receipt of packet, keep it around (used for provisional responses).
void dialog_unlink_all (struct sip_pvt *dialog)
 Unlink a dialog from the dialogs container, as well as any other places that it may be currently stored.
int sip_cancel_destroy (struct sip_pvt *p)
 Cancel destruction of SIP dialog. Be careful as this also absorbs the reference - if you call it from within the scheduler, this might be the last reference.
struct sip_pvtsip_destroy (struct sip_pvt *p)
 Destroy SIP call structure. Make it return NULL so the caller can do things like foo = sip_destroy(foo); and reduce the chance of bugs due to dangling pointers.
void sip_scheddestroy (struct sip_pvt *p, int ms)
 Schedule destruction of SIP dialog.
void sip_scheddestroy_final (struct sip_pvt *p, int ms)
 Schedule final destruction of SIP dialog. This can not be canceled. This function is used to keep a dialog around for a period of time in order to properly respond to any retransmits.


Detailed Description

sip dialog management header file

Definition in file dialog.h.


Define Documentation

#define dialog_ref ( dialog,
tag   )     ao2_t_bump(dialog, tag)

when we create or delete references, make sure to use these functions so we keep track of the refcounts. To simplify the code, we allow a NULL to be passed to dialog_unref().

Definition at line 32 of file dialog.h.

Referenced by __find_call(), __sip_reliable_xmit(), dialog_unlink_all(), handle_cc_subscribe(), handle_request_invite(), handle_request_subscribe(), handle_response_invite(), sip_call(), sip_hangup(), sip_new(), sip_poke_peer(), sip_scheddestroy(), sip_send_mwi_to_peer(), start_session_timer(), transmit_register(), and update_provisional_keepalive().

#define dialog_unref ( dialog,
tag   )     ({ ao2_t_cleanup(dialog, tag); (NULL); })

#define sip_alloc ( callid,
addr,
useglobal_nat,
intended_method,
req,
logger_callid   )     __sip_alloc(callid, addr, useglobal_nat, intended_method, req, logger_callid, __FILE__, __LINE__, __PRETTY_FUNCTION__)


Function Documentation

int __sip_ack ( struct sip_pvt p,
uint32_t  seqno,
int  resp,
int  sipmethod 
)

Acknowledges receipt of a packet and stops retransmission called with p locked.

Definition at line 4336 of file chan_sip.c.

References ast_debug, ast_free, ast_sched_del(), sip_pvt::callid, sip_pkt::data, dialog_unref, FALSE, sip_proxy::force, sip_pkt::is_resp, sip_pkt::method, sip_pkt::next, NULL, sip_pvt::outboundproxy, sip_pkt::owner, sip_pvt::packets, sip_pvt::pendinginvite, ref_proxy(), sip_pkt::retransid, sip_pkt::seqno, sip_pvt_lock, sip_pvt_unlock, TRUE, and UNLINK.

Referenced by __sip_pretend_ack(), handle_incoming(), handle_request_invite(), handle_request_publish(), and handle_response().

04337 {
04338    struct sip_pkt *cur, *prev = NULL;
04339    const char *msg = "Not Found";   /* used only for debugging */
04340    int res = FALSE;
04341 
04342    /* If we have an outbound proxy for this dialog, then delete it now since
04343      the rest of the requests in this dialog needs to follow the routing.
04344      If obforcing is set, we will keep the outbound proxy during the whole
04345      dialog, regardless of what the SIP rfc says
04346    */
04347    if (p->outboundproxy && !p->outboundproxy->force) {
04348       ref_proxy(p, NULL);
04349    }
04350 
04351    for (cur = p->packets; cur; prev = cur, cur = cur->next) {
04352       if (cur->seqno != seqno || cur->is_resp != resp) {
04353          continue;
04354       }
04355       if (cur->is_resp || cur->method == sipmethod) {
04356          res = TRUE;
04357          msg = "Found";
04358          if (!resp && (seqno == p->pendinginvite)) {
04359             ast_debug(1, "Acked pending invite %u\n", p->pendinginvite);
04360             p->pendinginvite = 0;
04361          }
04362          if (cur->retransid > -1) {
04363             if (sipdebug)
04364                ast_debug(4, "** SIP TIMER: Cancelling retransmit of packet (reply received) Retransid #%d\n", cur->retransid);
04365          }
04366          /* This odd section is designed to thwart a
04367           * race condition in the packet scheduler. There are
04368           * two conditions under which deleting the packet from the
04369           * scheduler can fail.
04370           *
04371           * 1. The packet has been removed from the scheduler because retransmission
04372           * is being attempted. The problem is that if the packet is currently attempting
04373           * retransmission and we are at this point in the code, then that MUST mean
04374           * that retrans_pkt is waiting on p's lock. Therefore we will relinquish the
04375           * lock temporarily to allow retransmission.
04376           *
04377           * 2. The packet has reached its maximum number of retransmissions and has
04378           * been permanently removed from the packet scheduler. If this is the case, then
04379           * the packet's retransid will be set to -1. The atomicity of the setting and checking
04380           * of the retransid to -1 is ensured since in both cases p's lock is held.
04381           */
04382          while (cur->retransid > -1 && ast_sched_del(sched, cur->retransid)) {
04383             sip_pvt_unlock(p);
04384             usleep(1);
04385             sip_pvt_lock(p);
04386          }
04387          UNLINK(cur, p->packets, prev);
04388          dialog_unref(cur->owner, "unref pkt cur->owner dialog from sip ack before freeing pkt");
04389          if (cur->data) {
04390             ast_free(cur->data);
04391          }
04392          ast_free(cur);
04393          break;
04394       }
04395    }
04396    ast_debug(1, "Stopping retransmission on '%s' of %s %u: Match %s\n",
04397       p->callid, resp ? "Response" : "Request", seqno, msg);
04398    return res;
04399 }

struct sip_pvt* __sip_alloc ( ast_string_field  callid,
struct ast_sockaddr sin,
int  useglobal_nat,
const int  intended_method,
struct sip_request req,
ast_callid  logger_callid,
const char *  file,
int  line,
const char *  func 
) [read]

Allocate sip_pvt structure, set defaults and link in the container. Returns a reference to the object so whoever uses it later must remember to release the reference.

Definition at line 8596 of file chan_sip.c.

References __ao2_alloc_debug(), sip_pvt::allowed_methods, sip_settings::allowtransfer, sip_pvt::allowtransfer, AO2_ALLOC_OPT_LOCK_MUTEX, ao2_cleanup, ao2_t_link, ao2_t_ref, ast_cc_config_params_init, ast_copy_flags, ast_copy_string(), ast_debug, ast_format_cap_alloc, ast_format_cap_append_from_cap(), AST_FORMAT_CAP_FLAG_DEFAULT, AST_LIST_HEAD_INIT_NOLOCK, AST_MEDIA_TYPE_UNKNOWN, ast_random(), AST_RTP_DTMF, ast_sip_ouraddrfor(), ast_sockaddr_copy(), ast_string_field_init, ast_string_field_set, ast_strlen_zero, ast_test_flag, AST_TRANSPORT_UDP, sip_pvt::autoframing, sip_pvt::autokillid, sip_pvt::branch, sip_via::branch, build_callid_pvt(), build_via(), sip_pvt::callid, sip_settings::caps, sip_pvt::caps, sip_pvt::cc_params, check_via(), context, sip_settings::default_context, sip_settings::default_max_forwards, sip_pvt::do_history, do_setnat(), sip_socket::fd, sip_pvt::flags, free_via(), sip_pvt::fromdomainport, sip_pvt::init_icseq, INITIAL_CSEQ, sip_pvt::initid, internip, sip_pvt::jointcaps, make_our_tag(), sip_pvt::maxcallbitrate, sip_pvt::maxforwards, sip_pvt::method, mohinterpret, mohsuggest, sip_pvt::noncodeccapability, NONE, NULL, sip_pvt::ocseq, sip_pvt::offered_media, sip_pvt::ourip, parkinglot, parse_via(), sip_pvt::peercaps, sip_pvt::prefcaps, sip_pvt::provisional_keepalive_sched_id, sip_pvt::recv, sip_pvt::redircaps, sip_pvt::reinviteid, sip_pvt::request_queue, sip_pvt::request_queue_sched_id, sip_pvt::rtp, sip_pvt::sa, sip_via::sent_by, sip_pvt::session_modify, sip_pvt::sessionversion_remote, set_socket_transport(), sip_cfg, sip_destroy_fn(), SIP_DTMF, SIP_DTMF_AUTO, SIP_DTMF_RFC2833, SIP_FLAGS_TO_COPY, sip_get_header(), sip_methods, SIP_OPTIONS, SIP_PAGE2_FLAGS_TO_COPY, SIP_PAGE3_FLAGS_TO_COPY, sip_pvt_callid_set(), SIP_REGISTER, sip_request::socket, sip_pvt::socket, sip_pvt::stateid, sip_pvt::stimer, sip_pvt::subscribed, sip_pvt::t38id, cfsip_methods::text, sip_pvt::timer_b, sip_pvt::timer_t1, TRUE, sip_socket::type, sip_pvt::waitid, and sip_pvt::zone.

08599 {
08600    struct sip_pvt *p;
08601 
08602    p = __ao2_alloc_debug(sizeof(*p), sip_destroy_fn,
08603       AO2_ALLOC_OPT_LOCK_MUTEX, "allocate a dialog(pvt) struct",
08604       file, line, func, 1);
08605    if (!p) {
08606       return NULL;
08607    }
08608 
08609    if (ast_string_field_init(p, 512)) {
08610       ao2_t_ref(p, -1, "failed to string_field_init, drop p");
08611       return NULL;
08612    }
08613 
08614    if (!(p->cc_params = ast_cc_config_params_init())) {
08615       ao2_t_ref(p, -1, "Yuck, couldn't allocate cc_params struct. Get rid o' p");
08616       return NULL;
08617    }
08618 
08619    if (logger_callid) {
08620       sip_pvt_callid_set(p, logger_callid);
08621    }
08622 
08623    p->caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
08624    p->jointcaps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
08625    p->peercaps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
08626    p->redircaps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
08627    p->prefcaps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
08628 
08629    if (!p->caps|| !p->jointcaps || !p->peercaps || !p->redircaps || !p->prefcaps) {
08630       ao2_cleanup(p->caps);
08631       ao2_cleanup(p->jointcaps);
08632       ao2_cleanup(p->peercaps);
08633       ao2_cleanup(p->redircaps);
08634       ao2_cleanup(p->prefcaps);
08635       ao2_t_ref(p, -1, "Yuck, couldn't allocate format capabilities. Get rid o' p");
08636       return NULL;
08637    }
08638 
08639 
08640    /* If this dialog is created as a result of a request or response, lets store
08641     * some information about it in the dialog. */
08642    if (req) {
08643       struct sip_via *via;
08644       const char *cseq = sip_get_header(req, "Cseq");
08645       uint32_t seqno;
08646 
08647       /* get branch parameter from initial Request that started this dialog */
08648       via = parse_via(sip_get_header(req, "Via"));
08649       if (via) {
08650          /* only store the branch if it begins with the magic prefix "z9hG4bK", otherwise
08651           * it is not useful to us to have it */
08652          if (!ast_strlen_zero(via->branch) && !strncasecmp(via->branch, "z9hG4bK", 7)) {
08653             ast_string_field_set(p, initviabranch, via->branch);
08654             ast_string_field_set(p, initviasentby, via->sent_by);
08655          }
08656          free_via(via);
08657       }
08658 
08659       /* Store initial incoming cseq. An error in sscanf here is ignored.  There is no approperiate
08660        * except not storing the number.  CSeq validation must take place before dialog creation in find_call */
08661       if (!ast_strlen_zero(cseq) && (sscanf(cseq, "%30u", &seqno) == 1)) {
08662          p->init_icseq = seqno;
08663       }
08664       /* Later in ast_sip_ouraddrfor we need this to choose the right ip and port for the specific transport */
08665       set_socket_transport(&p->socket, req->socket.type);
08666    } else {
08667       set_socket_transport(&p->socket, AST_TRANSPORT_UDP);
08668    }
08669 
08670    p->socket.fd = -1;
08671    p->method = intended_method;
08672    p->initid = -1;
08673    p->waitid = -1;
08674    p->reinviteid = -1;
08675    p->autokillid = -1;
08676    p->request_queue_sched_id = -1;
08677    p->provisional_keepalive_sched_id = -1;
08678    p->t38id = -1;
08679    p->subscribed = NONE;
08680    p->stateid = -1;
08681    p->sessionversion_remote = -1;
08682    p->session_modify = TRUE;
08683    p->stimer = NULL;
08684    ast_copy_string(p->zone, default_zone, sizeof(p->zone));
08685    p->maxforwards = sip_cfg.default_max_forwards;
08686 
08687    if (intended_method != SIP_OPTIONS) {  /* Peerpoke has it's own system */
08688       p->timer_t1 = global_t1;   /* Default SIP retransmission timer T1 (RFC 3261) */
08689       p->timer_b = global_timer_b;  /* Default SIP transaction timer B (RFC 3261) */
08690    }
08691 
08692    if (!addr) {
08693       p->ourip = internip;
08694    } else {
08695       ast_sockaddr_copy(&p->sa, addr);
08696       ast_sip_ouraddrfor(&p->sa, &p->ourip, p);
08697    }
08698 
08699    /* Copy global flags to this PVT at setup. */
08700    ast_copy_flags(&p->flags[0], &global_flags[0], SIP_FLAGS_TO_COPY);
08701    ast_copy_flags(&p->flags[1], &global_flags[1], SIP_PAGE2_FLAGS_TO_COPY);
08702    ast_copy_flags(&p->flags[2], &global_flags[2], SIP_PAGE3_FLAGS_TO_COPY);
08703 
08704    p->do_history = recordhistory;
08705 
08706    p->branch = ast_random();
08707    make_our_tag(p);
08708    p->ocseq = INITIAL_CSEQ;
08709    p->allowed_methods = UINT_MAX;
08710 
08711    if (sip_methods[intended_method].need_rtp) {
08712       p->maxcallbitrate = default_maxcallbitrate;
08713       p->autoframing = global_autoframing;
08714    }
08715 
08716    if (useglobal_nat && addr) {
08717       /* Setup NAT structure according to global settings if we have an address */
08718       ast_sockaddr_copy(&p->recv, addr);
08719       check_via(p, req);
08720       do_setnat(p);
08721    }
08722 
08723    if (p->method != SIP_REGISTER) {
08724       ast_string_field_set(p, fromdomain, default_fromdomain);
08725       p->fromdomainport = default_fromdomainport;
08726    }
08727    build_via(p);
08728    if (!callid)
08729       build_callid_pvt(p);
08730    else
08731       ast_string_field_set(p, callid, callid);
08732    /* Assign default music on hold class */
08733    ast_string_field_set(p, mohinterpret, default_mohinterpret);
08734    ast_string_field_set(p, mohsuggest, default_mohsuggest);
08735    ast_format_cap_append_from_cap(p->caps, sip_cfg.caps, AST_MEDIA_TYPE_UNKNOWN);
08736    p->allowtransfer = sip_cfg.allowtransfer;
08737    if ((ast_test_flag(&p->flags[0], SIP_DTMF) == SIP_DTMF_RFC2833) ||
08738        (ast_test_flag(&p->flags[0], SIP_DTMF) == SIP_DTMF_AUTO)) {
08739       p->noncodeccapability |= AST_RTP_DTMF;
08740    }
08741    ast_string_field_set(p, context, sip_cfg.default_context);
08742    ast_string_field_set(p, parkinglot, default_parkinglot);
08743    ast_string_field_set(p, engine, default_engine);
08744 
08745    AST_LIST_HEAD_INIT_NOLOCK(&p->request_queue);
08746    AST_LIST_HEAD_INIT_NOLOCK(&p->offered_media);
08747 
08748    /* Add to active dialog list */
08749 
08750    ao2_t_link(dialogs, p, "link pvt into dialogs table");
08751 
08752    ast_debug(1, "Allocating new SIP dialog for %s - %s (%s)\n", callid ? callid : p->callid, sip_methods[intended_method].text, p->rtp ? "With RTP" : "No RTP");
08753    return p;
08754 }

void __sip_destroy ( struct sip_pvt p,
int  lockowner,
int  lockdialoglist 
)

Destroy SIP call structure. Make it return NULL so the caller can do things like foo = sip_destroy(foo); and reduce the chance of bugs due to dangling pointers.

Definition at line 6351 of file chan_sip.c.

References ao2_cleanup, ao2_ref, ao2_t_ref, ao2_t_replace, ast_cc_config_params_destroy(), ast_channel_lock, ast_channel_name(), ast_channel_softhangup_internal_flag_add(), ast_channel_tech_pvt_set(), ast_channel_unlock, ast_debug, ast_free, ast_free_acl_list(), AST_LIST_REMOVE_HEAD, ast_rtp_dtls_cfg_free(), ast_rtp_instance_destroy(), ast_sdp_srtp_destroy(), AST_SOFTHANGUP_DEV, ast_string_field_free_memory, ast_test_flag, ast_udptl_destroy(), ast_unref_namedgroups(), ast_variables_destroy(), ast_verbose, ast_websocket_unref(), sip_subscription_mwi::call, sip_registry::call, sip_peer::call, sip_pvt::callid, sip_pvt::caps, sip_pvt::cc_params, sip_pvt::chanvars, sip_notify::content, DEC_CALL_LIMIT, deinit_req(), destroy_msg_headers(), dialog_unref, sip_pvt::directmediaacl, sip_pvt::dtls_cfg, sip_pvt::epa_entry, sip_pvt::flags, sip_notify::headers, sip_pvt::history, sip_pvt::history_entries, sip_pvt::initreq, sip_pvt::jointcaps, sip_pvt::last_device_state_info, sip_pvt::method, sip_pvt::mwi, sip_peer::mwipvt, sip_pvt::named_callgroups, sip_pvt::named_pickupgroups, sip_pvt::notify, NULL, offered_media_list_destroy(), sip_pvt::options, sip_pvt::outboundproxy, sip_invite_param::outboundproxy, sip_pvt::owner, sip_pvt::peerauth, sip_pvt::peercaps, sip_pvt::prefcaps, sip_st_dlg::quit_flag, sip_pvt::redircaps, ref_proxy(), sip_pvt::registry, sip_pvt::relatedpeer, sip_pvt::request_queue, sip_pvt::route, sip_pvt::rtp, sip_debug_test_pvt(), sip_dump_history(), SIP_INC_COUNT, sip_methods, SIP_PAGE2_CALL_ONHOLD, sip_refer_destroy(), sip_route_clear(), sip_unref_peer, sip_pvt::socket, sip_pvt::srtp, sip_pvt::stimer, stop_session_timer(), sip_socket::tcptls_session, cfsip_methods::text, sip_pvt::trtp, sip_pvt::tsrtp, sip_pvt::udptl, update_call_counter(), sip_pvt::vrtp, sip_pvt::vsrtp, and sip_socket::ws_session.

Referenced by sip_destroy().

06352 {
06353    struct sip_request *req;
06354 
06355    /* Destroy Session-Timers if allocated */
06356    if (p->stimer) {
06357       p->stimer->quit_flag = 1;
06358       stop_session_timer(p);
06359       ast_free(p->stimer);
06360       p->stimer = NULL;
06361    }
06362 
06363    if (sip_debug_test_pvt(p))
06364       ast_verbose("Really destroying SIP dialog '%s' Method: %s\n", p->callid, sip_methods[p->method].text);
06365 
06366    if (ast_test_flag(&p->flags[0], SIP_INC_COUNT) || ast_test_flag(&p->flags[1], SIP_PAGE2_CALL_ONHOLD)) {
06367       update_call_counter(p, DEC_CALL_LIMIT);
06368       ast_debug(2, "This call did not properly clean up call limits. Call ID %s\n", p->callid);
06369    }
06370 
06371    /* Unlink us from the owner if we have one */
06372    if (p->owner) {
06373       if (lockowner)
06374          ast_channel_lock(p->owner);
06375       ast_debug(1, "Detaching from %s\n", ast_channel_name(p->owner));
06376       ast_channel_tech_pvt_set(p->owner, NULL);
06377       /* Make sure that the channel knows its backend is going away */
06378       ast_channel_softhangup_internal_flag_add(p->owner, AST_SOFTHANGUP_DEV);
06379       if (lockowner)
06380          ast_channel_unlock(p->owner);
06381       /* Give the channel a chance to react before deallocation */
06382       usleep(1);
06383    }
06384 
06385    /* Remove link from peer to subscription of MWI */
06386    if (p->relatedpeer && p->relatedpeer->mwipvt == p)
06387       p->relatedpeer->mwipvt = dialog_unref(p->relatedpeer->mwipvt, "delete ->relatedpeer->mwipvt");
06388    if (p->relatedpeer && p->relatedpeer->call == p)
06389       p->relatedpeer->call = dialog_unref(p->relatedpeer->call, "unset the relatedpeer->call field in tandem with relatedpeer field itself");
06390 
06391    if (p->relatedpeer)
06392       p->relatedpeer = sip_unref_peer(p->relatedpeer,"unsetting a dialog relatedpeer field in sip_destroy");
06393 
06394    if (p->registry) {
06395       if (p->registry->call == p)
06396          p->registry->call = dialog_unref(p->registry->call, "nulling out the registry's call dialog field in unlink_all");
06397       ao2_t_replace(p->registry, NULL, "delete p->registry");
06398    }
06399 
06400    if (p->mwi) {
06401       p->mwi->call = NULL;
06402       p->mwi = NULL;
06403    }
06404 
06405    if (dumphistory)
06406       sip_dump_history(p);
06407 
06408    if (p->options) {
06409       if (p->options->outboundproxy) {
06410          ao2_ref(p->options->outboundproxy, -1);
06411       }
06412       ast_free(p->options);
06413       p->options = NULL;
06414    }
06415 
06416    if (p->outboundproxy) {
06417       ref_proxy(p, NULL);
06418    }
06419 
06420    if (p->notify) {
06421       ast_variables_destroy(p->notify->headers);
06422       ast_free(p->notify->content);
06423       ast_free(p->notify);
06424       p->notify = NULL;
06425    }
06426    if (p->rtp) {
06427       ast_rtp_instance_destroy(p->rtp);
06428       p->rtp = NULL;
06429    }
06430    if (p->vrtp) {
06431       ast_rtp_instance_destroy(p->vrtp);
06432       p->vrtp = NULL;
06433    }
06434    if (p->trtp) {
06435       ast_rtp_instance_destroy(p->trtp);
06436       p->trtp = NULL;
06437    }
06438    if (p->udptl) {
06439       ast_udptl_destroy(p->udptl);
06440       p->udptl = NULL;
06441    }
06442    sip_refer_destroy(p);
06443    sip_route_clear(&p->route);
06444    deinit_req(&p->initreq);
06445 
06446    /* Clear history */
06447    if (p->history) {
06448       struct sip_history *hist;
06449       while ( (hist = AST_LIST_REMOVE_HEAD(p->history, list)) ) {
06450          ast_free(hist);
06451          p->history_entries--;
06452       }
06453       ast_free(p->history);
06454       p->history = NULL;
06455    }
06456 
06457    while ((req = AST_LIST_REMOVE_HEAD(&p->request_queue, next))) {
06458       ast_free(req);
06459    }
06460 
06461    offered_media_list_destroy(p);
06462 
06463    if (p->chanvars) {
06464       ast_variables_destroy(p->chanvars);
06465       p->chanvars = NULL;
06466    }
06467 
06468    destroy_msg_headers(p);
06469 
06470    if (p->srtp) {
06471       ast_sdp_srtp_destroy(p->srtp);
06472       p->srtp = NULL;
06473    }
06474 
06475    if (p->vsrtp) {
06476       ast_sdp_srtp_destroy(p->vsrtp);
06477       p->vsrtp = NULL;
06478    }
06479 
06480    if (p->tsrtp) {
06481       ast_sdp_srtp_destroy(p->tsrtp);
06482       p->tsrtp = NULL;
06483    }
06484 
06485    if (p->directmediaacl) {
06486       p->directmediaacl = ast_free_acl_list(p->directmediaacl);
06487    }
06488 
06489    ast_string_field_free_memory(p);
06490 
06491    ast_cc_config_params_destroy(p->cc_params);
06492    p->cc_params = NULL;
06493 
06494    if (p->epa_entry) {
06495       ao2_ref(p->epa_entry, -1);
06496       p->epa_entry = NULL;
06497    }
06498 
06499    if (p->socket.tcptls_session) {
06500       ao2_ref(p->socket.tcptls_session, -1);
06501       p->socket.tcptls_session = NULL;
06502    } else if (p->socket.ws_session) {
06503       ast_websocket_unref(p->socket.ws_session);
06504       p->socket.ws_session = NULL;
06505    }
06506 
06507    if (p->peerauth) {
06508       ao2_t_ref(p->peerauth, -1, "Removing active peer authentication");
06509       p->peerauth = NULL;
06510    }
06511 
06512    p->named_callgroups = ast_unref_namedgroups(p->named_callgroups);
06513    p->named_pickupgroups = ast_unref_namedgroups(p->named_pickupgroups);
06514 
06515    ao2_cleanup(p->caps);
06516    ao2_cleanup(p->jointcaps);
06517    ao2_cleanup(p->peercaps);
06518    ao2_cleanup(p->redircaps);
06519    ao2_cleanup(p->prefcaps);
06520 
06521    ast_rtp_dtls_cfg_free(&p->dtls_cfg);
06522 
06523    if (p->last_device_state_info) {
06524       ao2_ref(p->last_device_state_info, -1);
06525       p->last_device_state_info = NULL;
06526    }
06527 }

void __sip_pretend_ack ( struct sip_pvt p  ) 

Pretend to ack all packets called with p locked.

Definition at line 4403 of file chan_sip.c.

References __sip_ack(), ast_log, ast_str_buffer(), sip_pkt::data, find_sip_method(), sip_pkt::is_resp, LOG_WARNING, sip_pkt::method, method, NULL, sip_pvt::packets, sip_pkt::seqno, sip_methods, and cfsip_methods::text.

Referenced by __sip_autodestruct(), handle_request_bye(), handle_request_cancel(), and sip_reg_timeout().

04404 {
04405    struct sip_pkt *cur = NULL;
04406 
04407    while (p->packets) {
04408       int method;
04409       if (cur == p->packets) {
04410          ast_log(LOG_WARNING, "Have a packet that doesn't want to give up! %s\n", sip_methods[cur->method].text);
04411          return;
04412       }
04413       cur = p->packets;
04414       method = (cur->method) ? cur->method : find_sip_method(ast_str_buffer(cur->data));
04415       __sip_ack(p, cur->seqno, cur->is_resp, method);
04416    }
04417 }

int __sip_semi_ack ( struct sip_pvt p,
uint32_t  seqno,
int  resp,
int  sipmethod 
)

Acks receipt of packet, keep it around (used for provisional responses).

Definition at line 4420 of file chan_sip.c.

References ast_debug, AST_SCHED_DEL, ast_str_buffer(), sip_pvt::callid, sip_pkt::data, FALSE, sip_pkt::is_resp, method_match(), sip_pkt::next, sip_pvt::packets, sip_pkt::retransid, sip_pkt::seqno, sip_methods, cfsip_methods::text, and TRUE.

Referenced by handle_response(), and sip_hangup().

04421 {
04422    struct sip_pkt *cur;
04423    int res = FALSE;
04424 
04425    for (cur = p->packets; cur; cur = cur->next) {
04426       if (cur->seqno == seqno && cur->is_resp == resp &&
04427          (cur->is_resp || method_match(sipmethod, ast_str_buffer(cur->data)))) {
04428          /* this is our baby */
04429          if (cur->retransid > -1) {
04430             if (sipdebug)
04431                ast_debug(4, "*** SIP TIMER: Cancelling retransmission #%d - %s (got response)\n", cur->retransid, sip_methods[sipmethod].text);
04432          }
04433          AST_SCHED_DEL(sched, cur->retransid);
04434          res = TRUE;
04435          break;
04436       }
04437    }
04438    ast_debug(1, "(Provisional) Stopping retransmission (but retaining packet) on '%s' %s %u: %s\n", p->callid, resp ? "Response" : "Request", seqno, res == -1 ? "Not Found" : "Found");
04439    return res;
04440 }

void dialog_unlink_all ( struct sip_pvt dialog  ) 

Unlink a dialog from the dialogs container, as well as any other places that it may be currently stored.

Note:
A reference to the dialog must be held before calling this function, and this function does not release that reference.

The dialog must not be locked when called.

A reference to the dialog must be held before calling this function, and this function does not release that reference.

Definition at line 3233 of file chan_sip.c.

References ao2_t_replace, ao2_t_unlink, ast_channel_name(), ast_channel_tech_pvt(), ast_channel_tech_pvt_set(), ast_channel_unlock, ast_channel_unref, ast_debug, ast_extension_state_del(), ast_free, AST_SCHED_DEL, AST_SCHED_DEL_UNREF, sip_pvt::autokillid, sip_peer::call, sip_registry::call, cb_extensionstate(), sip_pkt::data, dialog_ref, dialog_unref, sip_pvt::initid, sip_peer::mwipvt, sip_pkt::next, NULL, sip_pkt::owner, sip_pvt::packets, sip_pvt::provisional_keepalive_sched_id, sip_pvt::registry, sip_pvt::reinviteid, sip_pvt::relatedpeer, sip_pvt::request_queue_sched_id, sip_pkt::retransid, sip_pvt_lock_full(), sip_pvt_unlock, sip_set_owner(), sip_pvt::stateid, sip_pvt::stimer, stop_session_timer(), sip_pvt::t38id, and sip_pvt::waitid.

Referenced by __sip_autodestruct(), __sip_subscribe_mwi_do(), cleanup_registration(), dialog_needdestroy(), handle_request_subscribe(), manager_sipnotify(), sip_cli_notify(), sip_destroy_peer(), sip_msg_send(), sip_poke_noanswer(), sip_poke_peer(), sip_registry_destroy(), sip_request_call(), sip_send_mwi_to_peer(), transmit_publish(), transmit_register(), and unload_module().

03234 {
03235    struct sip_pkt *cp;
03236    struct ast_channel *owner;
03237 
03238    dialog_ref(dialog, "Let's bump the count in the unlink so it doesn't accidentally become dead before we are done");
03239 
03240    ao2_t_unlink(dialogs, dialog, "unlinking dialog via ao2_unlink");
03241    ao2_t_unlink(dialogs_needdestroy, dialog, "unlinking dialog_needdestroy via ao2_unlink");
03242    ao2_t_unlink(dialogs_rtpcheck, dialog, "unlinking dialog_rtpcheck via ao2_unlink");
03243 
03244    /* Unlink us from the owner (channel) if we have one */
03245    owner = sip_pvt_lock_full(dialog);
03246    if (owner) {
03247       ast_debug(1, "Detaching from channel %s\n", ast_channel_name(owner));
03248       ast_channel_tech_pvt_set(owner, dialog_unref(ast_channel_tech_pvt(owner), "resetting channel dialog ptr in unlink_all"));
03249       ast_channel_unlock(owner);
03250       ast_channel_unref(owner);
03251       sip_set_owner(dialog, NULL);
03252    }
03253    sip_pvt_unlock(dialog);
03254 
03255    if (dialog->registry) {
03256       if (dialog->registry->call == dialog) {
03257          dialog->registry->call = dialog_unref(dialog->registry->call, "nulling out the registry's call dialog field in unlink_all");
03258       }
03259       ao2_t_replace(dialog->registry, NULL, "delete dialog->registry");
03260    }
03261    if (dialog->stateid != -1) {
03262       ast_extension_state_del(dialog->stateid, cb_extensionstate);
03263       dialog->stateid = -1;
03264    }
03265    /* Remove link from peer to subscription of MWI */
03266    if (dialog->relatedpeer && dialog->relatedpeer->mwipvt == dialog) {
03267       dialog->relatedpeer->mwipvt = dialog_unref(dialog->relatedpeer->mwipvt, "delete ->relatedpeer->mwipvt");
03268    }
03269    if (dialog->relatedpeer && dialog->relatedpeer->call == dialog) {
03270       dialog->relatedpeer->call = dialog_unref(dialog->relatedpeer->call, "unset the relatedpeer->call field in tandem with relatedpeer field itself");
03271    }
03272 
03273    /* remove all current packets in this dialog */
03274    while((cp = dialog->packets)) {
03275       dialog->packets = dialog->packets->next;
03276       AST_SCHED_DEL(sched, cp->retransid);
03277       dialog_unref(cp->owner, "remove all current packets in this dialog, and the pointer to the dialog too as part of __sip_destroy");
03278       if (cp->data) {
03279          ast_free(cp->data);
03280       }
03281       ast_free(cp);
03282    }
03283 
03284    AST_SCHED_DEL_UNREF(sched, dialog->waitid, dialog_unref(dialog, "when you delete the waitid sched, you should dec the refcount for the stored dialog ptr"));
03285 
03286    AST_SCHED_DEL_UNREF(sched, dialog->initid, dialog_unref(dialog, "when you delete the initid sched, you should dec the refcount for the stored dialog ptr"));
03287 
03288    if (dialog->reinviteid > -1) {
03289       AST_SCHED_DEL_UNREF(sched, dialog->reinviteid, dialog_unref(dialog, "clear ref for reinvite_timeout"));
03290    }
03291 
03292    if (dialog->autokillid > -1) {
03293       AST_SCHED_DEL_UNREF(sched, dialog->autokillid, dialog_unref(dialog, "when you delete the autokillid sched, you should dec the refcount for the stored dialog ptr"));
03294    }
03295 
03296    if (dialog->request_queue_sched_id > -1) {
03297       AST_SCHED_DEL_UNREF(sched, dialog->request_queue_sched_id, dialog_unref(dialog, "when you delete the request_queue_sched_id sched, you should dec the refcount for the stored dialog ptr"));
03298    }
03299 
03300    AST_SCHED_DEL_UNREF(sched, dialog->provisional_keepalive_sched_id, dialog_unref(dialog, "when you delete the provisional_keepalive_sched_id, you should dec the refcount for the stored dialog ptr"));
03301 
03302    if (dialog->t38id > -1) {
03303       AST_SCHED_DEL_UNREF(sched, dialog->t38id, dialog_unref(dialog, "when you delete the t38id sched, you should dec the refcount for the stored dialog ptr"));
03304    }
03305 
03306    if (dialog->stimer) {
03307       stop_session_timer(dialog);
03308    }
03309 
03310    dialog_unref(dialog, "Let's unbump the count in the unlink so the poor pvt can disappear if it is time");
03311 }

int sip_cancel_destroy ( struct sip_pvt p  ) 

Cancel destruction of SIP dialog. Be careful as this also absorbs the reference - if you call it from within the scheduler, this might be the last reference.

Definition at line 4321 of file chan_sip.c.

References append_history, AST_SCHED_DEL_UNREF, sip_pvt::autokillid, dialog_unref, and sip_pvt::final_destruction_scheduled.

Referenced by handle_request_invite(), handle_request_subscribe(), handle_response(), handle_response_invite(), register_verify(), sip_hangup(), and sip_scheddestroy().

04322 {
04323    if (p->final_destruction_scheduled) {
04324       return 0;
04325    }
04326 
04327    if (p->autokillid > -1) {
04328       append_history(p, "CancelDestroy", "");
04329       AST_SCHED_DEL_UNREF(sched, p->autokillid, dialog_unref(p, "remove ref for autokillid"));
04330    }
04331    return 0;
04332 }

struct sip_pvt* sip_destroy ( struct sip_pvt p  )  [read]

Destroy SIP call structure. Make it return NULL so the caller can do things like foo = sip_destroy(foo); and reduce the chance of bugs due to dangling pointers.

Definition at line 6696 of file chan_sip.c.

References __sip_destroy(), ast_debug, sip_pvt::callid, NULL, and TRUE.

Referenced by sip_destroy_fn().

06697 {
06698    ast_debug(3, "Destroying SIP dialog %s\n", p->callid);
06699    __sip_destroy(p, TRUE, TRUE);
06700    return NULL;
06701 }

void sip_scheddestroy ( struct sip_pvt p,
int  ms 
)

Schedule destruction of SIP dialog.

Definition at line 4285 of file chan_sip.c.

References __sip_autodestruct(), append_history, ast_log, ast_sched_add(), ast_verbose, sip_pvt::autokillid, sip_pvt::callid, dialog_ref, sip_pvt::do_history, sip_pvt::final_destruction_scheduled, LOG_WARNING, sip_pvt::method, sip_cancel_destroy(), sip_debug_test_pvt(), sip_methods, sip_st_dlg::st_active, sip_st_dlg::st_schedid, sip_pvt::stimer, stop_session_timer(), cfsip_methods::text, sip_pvt::timer_b, sip_pvt::timer_t1, and TRUE.

Referenced by __sip_autodestruct(), auto_congest(), check_auth(), check_pendings(), extensionstate_update(), handle_incoming(), handle_invite_replaces(), handle_request_cancel(), handle_request_info(), handle_request_invite(), handle_request_notify(), handle_request_options(), handle_request_publish(), handle_request_register(), handle_request_subscribe(), handle_response_invite(), manager_sipnotify(), receive_message(), sip_cli_notify(), sip_hangup(), sip_msg_send(), sip_scheddestroy_final(), sip_send_mwi_to_peer(), sip_sipredirect(), transmit_fake_auth_response(), and transmit_publish().

04286 {
04287    if (p->final_destruction_scheduled) {
04288       return; /* already set final destruction */
04289    }
04290 
04291    if (ms < 0) {
04292       if (p->timer_t1 == 0) {
04293          p->timer_t1 = global_t1;   /* Set timer T1 if not set (RFC 3261) */
04294       }
04295       if (p->timer_b == 0) {
04296          p->timer_b = global_timer_b;  /* Set timer B if not set (RFC 3261) */
04297       }
04298       ms = p->timer_t1 * 64;
04299    }
04300    if (sip_debug_test_pvt(p)) {
04301       ast_verbose("Scheduling destruction of SIP dialog '%s' in %d ms (Method: %s)\n", p->callid, ms, sip_methods[p->method].text);
04302    }
04303    if (sip_cancel_destroy(p)) {
04304       ast_log(LOG_WARNING, "Unable to cancel SIP destruction.  Expect bad things.\n");
04305    }
04306 
04307    if (p->do_history) {
04308       append_history(p, "SchedDestroy", "%d ms", ms);
04309    }
04310    p->autokillid = ast_sched_add(sched, ms, __sip_autodestruct, dialog_ref(p, "setting ref as passing into ast_sched_add for __sip_autodestruct"));
04311 
04312    if (p->stimer && p->stimer->st_active == TRUE && p->stimer->st_schedid > 0) {
04313       stop_session_timer(p);
04314    }
04315 }

void sip_scheddestroy_final ( struct sip_pvt p,
int  ms 
)

Schedule final destruction of SIP dialog. This can not be canceled. This function is used to keep a dialog around for a period of time in order to properly respond to any retransmits.

Definition at line 4272 of file chan_sip.c.

References sip_pvt::autokillid, sip_pvt::final_destruction_scheduled, and sip_scheddestroy().

Referenced by handle_request_bye().

04273 {
04274    if (p->final_destruction_scheduled) {
04275       return; /* already set final destruction */
04276    }
04277 
04278    sip_scheddestroy(p, ms);
04279    if (p->autokillid != -1) {
04280       p->final_destruction_scheduled = 1;
04281    }
04282 }


Generated on Thu Apr 16 06:30:39 2015 for Asterisk - The Open Source Telephony Project by  doxygen 1.5.6