![]() |
Home page |
Mailing list |
Docs
Asterisk developer's documentation :: Codename Pineapple
sip3_dialog.c File Reference
Olle E. Johansson <oej@edvina.net> (all the chan_sip3 changes)
Definition in file sip3_dialog.c.
#include "asterisk.h"
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <errno.h>
#include <stdlib.h>
#include <fcntl.h>
#include <netdb.h>
#include <signal.h>
#include <sys/signal.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <arpa/inet.h>
#include <netinet/ip.h>
#include <regex.h>
#include "asterisk/lock.h"
#include "asterisk/channel.h"
#include "asterisk/config.h"
#include "asterisk/logger.h"
#include "asterisk/module.h"
#include "asterisk/pbx.h"
#include "asterisk/options.h"
#include "asterisk/sched.h"
#include "asterisk/io.h"
#include "asterisk/rtp.h"
#include "asterisk/udptl.h"
#include "asterisk/acl.h"
#include "asterisk/manager.h"
#include "asterisk/callerid.h"
#include "asterisk/cli.h"
#include "asterisk/app.h"
#include "asterisk/musiconhold.h"
#include "asterisk/dsp.h"
#include "asterisk/features.h"
#include "asterisk/srv.h"
#include "asterisk/astdb.h"
#include "asterisk/causes.h"
#include "asterisk/utils.h"
#include "asterisk/file.h"
#include "asterisk/astobj.h"
#include "asterisk/dnsmgr.h"
#include "asterisk/devicestate.h"
#include "asterisk/linkedlists.h"
#include "asterisk/stringfields.h"
#include "asterisk/monitor.h"
#include "asterisk/localtime.h"
#include "asterisk/abstract_jb.h"
#include "asterisk/compiler.h"
#include "asterisk/threadstorage.h"
#include "sip3.h"
#include "sip3funcs.h"
Include dependency graph for sip3_dialog.c:

Go to the source code of this file.
Functions | |
| void | __sip_ack (struct sip_dialog *dialog, int seqno, int resp, int sipmethod, int reset) |
| For a reliable transmission, we need to get an reply to stop retransmission. Acknowledges receipt of a packet and stops retransmission. | |
| static int | __sip_autodestruct (void *data) |
| Kill a SIP dialog (called by scheduler). | |
| void | __sip_destroy (struct sip_dialog *dialog, int lockowner, int lockdialoglist) |
| Execute destruction of SIP dialog structure, release memory. | |
| GNURK void | __sip_pretend_ack (struct sip_dialog *dialog) |
| Pretend to ack all packets - nothing to do with SIP_ACK (the method) maybe the lock on p is not strictly necessary but there might be a race. | |
| int | __sip_semi_ack (struct sip_dialog *dialog, int seqno, int resp, int sipmethod) |
| Acks receipt of packet, keep it around (used for provisional responses). | |
| AST_MUTEX_DEFINE_STATIC (dialoglock) | |
| Protect the SIP dialog list (of sip_dialog's). | |
| AST_THREADSTORAGE_CUSTOM (ts_temp_pvt, temp_pvt_init, temp_pvt_cleanup) | |
| A per-thread temporary pvt structure. | |
| GNURK void | build_via (struct sip_dialog *dialog, int forcenewbranch) |
| Build a Via header for a request. | |
| static int | dialog_activate_media (struct sip_dialog *dialog, struct sip_network *sipnet) |
| Activate media streams - Audio, Video and T.38 UDPTL if needed. | |
| void | dialog_lock (struct sip_dialog *dialog, int state) |
| Helper function to lock and unlock, hiding the underlying locking mechanism. | |
| void | dialoglist_lock (void) |
| Lock list of active SIP dialogs. | |
| void | dialoglist_unlock (void) |
| Unlock list of active SIP dialogs. | |
| const char * | dialogstate2str (const enum dialogstate state) |
| Convert SIP dialog states to string. | |
| void | dialogstatechange (struct sip_dialog *dialog, enum dialogstate newstate) |
| Change dialog state for a SIP dialog and output to debug. | |
| GNURK void | find_via_branch (struct sip_request *req, char *viabuf, size_t vialen) |
| Find via branch parameter. | |
| const char * | hangup_cause2sip (int cause) |
| Convert Asterisk hangup causes to SIP codes. | |
| int | hangup_sip2cause (int cause) |
| Convert SIP hangup causes to Asterisk hangup causes. | |
| GNURK void | initialize_initreq (struct sip_dialog *dialog, struct sip_request *req) |
| Initialize the initital request packet in the pvt structure. This packet is used for creating replies and future requests in a dialog. | |
| GNURK void | make_our_tag (char *tagbuf, size_t len) |
| Make our SIP dialog tag. | |
| sip_dialog * | match_or_create_dialog (struct sip_request *req, struct sockaddr_in *sin, const int intended_method) |
| static char * | ourdialogbranch (struct sip_dialog *dialog, int forcenewbranch) |
| Make branch tag for via header if it does not exist yet. | |
| void | set_initreq (struct sip_dialog *dialog, struct sip_request *req) |
| Set packet to initreq status. Set flag to avoid de-allocation until dialog is destroyed. | |
| sip_dialog * | sip_alloc (ast_string_field callid, struct sockaddr_in *sin, int useglobal_nat, const int intended_method) |
| Allocate SIP_PVT structure and set defaults. | |
| GNURK void | sip_cancel_destroy (struct sip_dialog *p) |
| Cancel destruction of SIP dialog. | |
| void | sip_destroy (struct sip_dialog *dialog) |
| Destroy SIP call structure. | |
| GNURK void | sip_scheddestroy (struct sip_dialog *p, int ms) |
| Schedule destruction of SIP dialog. | |
| static void | temp_pvt_cleanup (void *data) |
| Cleanup temporary PVT. | |
| static int | temp_pvt_init (void *data) |
| Initialize temporary PVT. | |
| int | transmit_final_response (struct sip_dialog *dialog, const char *msg, struct sip_request *req, enum xmittype reliable) |
| Transmit final response to a request and close dialog Set dialog state to TERMINATED to avoid problems At some point, after debugging, we can remove the reliable flag. Only responses to INVITEs are sent reliably. | |
| static int | transmit_response_using_temp (ast_string_field callid, struct sockaddr_in *sin, int useglobal_nat, const int intended_method, struct sip_request *req, const char *msg) |
| Transmit response, no retransmits, using a temporary pvt structure. | |
|
||||||||||||||||||||||||
|
For a reliable transmission, we need to get an reply to stop retransmission. Acknowledges receipt of a packet and stops retransmission.
Definition at line 261 of file sip3_dialog.c. References ast_clear_flag, ast_log(), ast_sched_del(), ast_test_flag, sip_request::dialog, dialog_lock(), FALSE, LOG_DEBUG, sip_request::method, sip_request::next, option_debug, sip_dialog::packets, parse_request(), sip_dialog::pendinginvite, sip_request::retransid, sip_request::seqno, SIP_PKT_CONNECTED, SIP_PKT_INITREQ, SIP_PKT_PARSED, SIP_PKT_RESPONSE, sipdebug, siprequest_free(), TRUE, and UNLINK. 00262 { 00263 struct sip_request *cur, *prev = NULL; 00264 int res = FALSE; 00265 00266 if (option_debug) { 00267 if (!resp) 00268 ast_log(LOG_DEBUG, "Trying to confirm pending invite %d Call ID %s\n", dialog->pendinginvite, dialog->callid); 00269 else 00270 ast_log(LOG_DEBUG, "Trying to confirm pending response on Call ID %s\n", dialog->callid); 00271 } 00272 00273 dialog_lock(dialog, TRUE); 00274 00275 /* Find proper transaction */ 00276 for (cur = dialog->packets; cur; prev = cur, cur = cur->next) { 00277 if (option_debug > 2) 00278 ast_log(LOG_DEBUG, "--Checking packet with seqno %d against response with seqno %d\n", cur->seqno, seqno); 00279 /* Match on seqno AND req/resp AND method? */ 00280 if ((cur->seqno == seqno) && ((ast_test_flag(cur, SIP_PKT_RESPONSE)) == resp) && 00281 ((ast_test_flag(cur, SIP_PKT_RESPONSE)) || (cur->method == sipmethod))) { 00282 if (!resp && (seqno == dialog->pendinginvite)) { 00283 if (sipdebug && option_debug && !reset) 00284 ast_log(LOG_DEBUG, "Got reply to pending invite %d - Call Id %s\n", dialog->pendinginvite, dialog->callid); 00285 dialog->pendinginvite = 0; 00286 } else { 00287 if (sipdebug && option_debug && !reset) 00288 ast_log(LOG_DEBUG, "Got ACK on INVITE response Cseq %d Call Id %s\n", cur->seqno, dialog->callid); 00289 } 00290 /* this is our baby */ 00291 res = TRUE; 00292 UNLINK(cur, dialog->packets, prev); 00293 if (cur->retransid > -1) { 00294 if (sipdebug && option_debug > 3 && !reset) 00295 ast_log(LOG_DEBUG, "Cancelling retransmit of packet (reply received) Retransid #%d\n", cur->retransid); 00296 ast_sched_del(sched, cur->retransid); 00297 cur->retransid = -1; 00298 } 00299 if (!reset) { 00300 if (!ast_test_flag(cur, SIP_PKT_INITREQ)) 00301 siprequest_free(cur); /* We might want to keep this somewhere else */ 00302 else { 00303 if (sipdebug && option_debug > 3 && !reset) 00304 ast_log(LOG_DEBUG, "This is the initial request, keeping it in memory - Cseq %d\n", cur->seqno); 00305 ast_clear_flag(cur, SIP_PKT_CONNECTED); 00306 if (!ast_test_flag(cur, SIP_PKT_PARSED)) 00307 parse_request(cur); /* Parse initreq now, after we have answer */ 00308 } 00309 } 00310 break; 00311 } 00312 } 00313 dialog_lock(dialog, FALSE); 00314 if (option_debug && sipdebug) 00315 ast_log(LOG_DEBUG, "Stopping retransmission on '%s' of %s %d: Match %s\n", dialog->callid, resp ? "Response" : "Request", seqno, res ? "Found" : "Not Found"); 00316 }
|
|
|
Kill a SIP dialog (called by scheduler).
Definition at line 496 of file sip3_dialog.c. References append_history, AST_EXTENSION_DEACTIVATED, ast_log(), ast_queue_hangup(), sip_dialog::autokillid, DEFAULT_TRANS_TIMEOUT, device_unref(), LOG_DEBUG, LOG_WARNING, sip_dialog::method, MWI_NOTIFICATION, NONE, option_debug, sip_dialog::owner, sip_dialog::refer, sip_dialog::relatedpeer, SIP_BYE, sip_destroy(), sip_method2txt(), sip_scheddestroy(), sip_dialog::subscribed, transmit_request_with_auth(), transmit_state_notify(), TRUE, and XMIT_RELIABLE. 00497 { 00498 struct sip_dialog *dialog = data; 00499 00500 /* If this is a subscription, tell the phone that we got a timeout */ 00501 if (dialog->subscribed) { 00502 transmit_state_notify(dialog, AST_EXTENSION_DEACTIVATED, 1, TRUE); /* Send last notification */ 00503 dialog->subscribed = NONE; 00504 append_history(dialog, "Subscribestatus", "timeout"); 00505 if (option_debug > 2) 00506 ast_log(LOG_DEBUG, "Re-scheduled destruction of SIP subsription %s\n", dialog->callid ? dialog->callid : "<unknown>"); 00507 return 10000; /* Reschedule this destruction so that we know that it's gone */ 00508 } 00509 00510 if (dialog->subscribed == MWI_NOTIFICATION && dialog->relatedpeer) 00511 device_unref(dialog->relatedpeer); 00512 00513 /* Reset schedule ID */ 00514 dialog->autokillid = -1; 00515 00516 append_history(dialog, "AutoDestroy", "%s", dialog->callid); 00517 if (dialog->owner) { 00518 ast_log(LOG_WARNING, "Autodestruct on dialog '%s' with owner in place (Method: %s)\n", dialog->callid, sip_method2txt(dialog->method)); 00519 ast_queue_hangup(dialog->owner); 00520 } else if (dialog->refer) { 00521 if (option_debug > 2) 00522 ast_log(LOG_DEBUG, "Finally hanging up channel after transfer: %s\n", dialog->callid); 00523 transmit_request_with_auth(dialog, SIP_BYE, 0, XMIT_RELIABLE, 1); 00524 append_history(dialog, "ReferBYE", "Sending BYE on transferer call leg %s", dialog->callid); 00525 sip_scheddestroy(dialog, DEFAULT_TRANS_TIMEOUT); 00526 } else { 00527 append_history(dialog, "AutoDestroy", "%s", dialog->callid); 00528 if (option_debug) 00529 ast_log(LOG_DEBUG, "Auto destroying SIP dialog '%s'\n", dialog->callid); 00530 sip_destroy(dialog); 00531 } 00532 return 0; 00533 }
|
|
||||||||||||||||
|
Execute destruction of SIP dialog structure, release memory.
Definition at line 366 of file sip3_dialog.c. References ast_channel_lock, ast_channel_unlock, ast_extension_state_del(), AST_LIST_REMOVE_HEAD, ast_log(), ast_rtp_destroy(), ast_sched_del(), ast_test_flag, ast_udptl_destroy(), ast_verbose(), ASTOBJ_UNREF, DEC_CALL_LIMIT, DEC_CALL_RINGING, sip_request::dialog, dialoglist, dialoglist_lock(), sip_globals::dumphistory, sip_dialog::flags, free, free_old_route(), global, LOG_DEBUG, sip_dialog::next, option_debug, sip_debug_test_pvt(), sip_dump_history(), SIP_INC_COUNT, sip_method2txt(), SIP_PAGE2_INC_RINGING, sip_registry_destroy(), UNLINK, and update_call_counter(). 00367 { 00368 struct sip_dialog *cur, *prev = NULL; 00369 struct sip_request *cp; 00370 00371 if (ast_test_flag(&dialog->flags[0], SIP_INC_COUNT)) /* This dialog has incremented call count */ 00372 update_call_counter(dialog, DEC_CALL_LIMIT); /* Since it was forgotten, decrement call count */ 00373 00374 if (ast_test_flag(&dialog->flags[1], SIP_PAGE2_INC_RINGING)) /* This dialog has incremented ring count */ 00375 update_call_counter(dialog, DEC_CALL_RINGING); /* Since it was forgotten, decrement ring count */ 00376 00377 if (sip_debug_test_pvt(dialog) || option_debug > 2) 00378 ast_verbose("Really destroying SIP dialog '%s' Method: %s\n", dialog->callid, sip_method2txt(dialog->method)); 00379 00380 00381 /* Remove link from peer to subscription of MWI */ 00382 if (dialog->relatedpeer && dialog->relatedpeer->mailbox.mwipvt) 00383 dialog->relatedpeer->mailbox.mwipvt = NULL; 00384 00385 if (global.dumphistory) 00386 sip_dump_history(dialog); 00387 00388 00389 if (dialog->stateid > -1) 00390 ast_extension_state_del(dialog->stateid, NULL); 00391 if (dialog->initid > -1) 00392 ast_sched_del(sched, dialog->initid); 00393 if (dialog->autokillid > -1) 00394 ast_sched_del(sched, dialog->autokillid); 00395 00396 if (dialog->inviteoptions) 00397 free(dialog->inviteoptions); 00398 00399 if (dialog->rtp) 00400 ast_rtp_destroy(dialog->rtp); 00401 if (dialog->vrtp) 00402 ast_rtp_destroy(dialog->vrtp); 00403 if (dialog->udptl) 00404 ast_udptl_destroy(dialog->udptl); 00405 if (dialog->refer) 00406 free(dialog->refer); 00407 if (dialog->route) { 00408 free_old_route(dialog->route); 00409 dialog->route = NULL; 00410 } 00411 if (dialog->registry) { 00412 if (dialog->registry->call == dialog) 00413 dialog->registry->call = NULL; 00414 ASTOBJ_UNREF(dialog->registry, sip_registry_destroy); 00415 } 00416 00417 /* Unlink us from the owner if we have one */ 00418 if (dialog->owner) { 00419 if (lockowner) 00420 ast_channel_lock(dialog->owner); 00421 if (option_debug) 00422 ast_log(LOG_DEBUG, "Detaching from %s\n", dialog->owner->name); 00423 dialog->owner->tech_pvt = NULL; 00424 if (lockowner) 00425 ast_channel_unlock(dialog->owner); 00426 } 00427 /* Clear history */ 00428 if (dialog->history) { 00429 struct sip_history *hist; 00430 while( (hist = AST_LIST_REMOVE_HEAD(dialog->history, list)) ) 00431 free(hist); 00432 free(dialog->history); 00433 dialog->history = NULL; 00434 } 00435 00436 00437 /* Unlink us from the dialog list */ 00438 if (lockdialoglist) 00439 dialoglist_lock(); 00440 for (prev = NULL, cur = dialoglist; cur; prev = cur, cur = cur->next) { 00441 if (cur == dialog) { 00442 UNLINK(cur, dialoglist, prev); 00443 break; 00444 } 00445 } 00446 if (lockdialoglist) 00447 dialoglist_unlock(); 00448 00449 if (!cur) { 00450 ast_log(LOG_WARNING, "Trying to destroy \"%s\", not found in dialog list?!?! \n", dialog->callid); 00451 return; 00452 } 00453 00454 /* remove all current packets in this dialog */ 00455 while((cp = dialog->packets)) { 00456 /* If one of the records in the packet list is the initreq, then release it */ 00457 if (cp == dialog->initreq) 00458 dialog->initreq = NULL; 00459 00460 dialog->packets = dialog->packets->next; 00461 if (cp->retransid > -1) 00462 ast_sched_del(sched, cp->retransid); 00463 free(cp); 00464 } 00465 00466 if (dialog->initreq) 00467 siprequest_free(dialog->initreq); 00468 00469 if (dialog->chanvars) { 00470 ast_variables_destroy(dialog->chanvars); 00471 dialog->chanvars = NULL; 00472 } 00473 ast_mutex_destroy(&dialog->lock); 00474 00475 ast_string_field_free_pools(dialog); 00476 00477 /* Finally, release the dialog */ 00478 free(dialog); 00479 00480 sipcounters.dialog_objects--; 00481 if (option_debug > 3) 00482 ast_log(LOG_DEBUG, "--DIALOGS-- Counter %d\n", sipcounters.dialog_objects); 00483 }
|
|
|
Pretend to ack all packets - nothing to do with SIP_ACK (the method) maybe the lock on p is not strictly necessary but there might be a race.
Definition at line 320 of file sip3_dialog.c. References __sip_ack(), ast_log(), ast_test_flag, sip_request::data, sip_request::dialog, FALSE, find_sip_method(), LOG_WARNING, sip_request::method, sip_dialog::packets, sip_request::seqno, sip_method2txt(), and SIP_PKT_RESPONSE. 00321 { 00322 struct sip_request *cur = NULL; 00323 00324 while (dialog->packets) { 00325 int method; 00326 if (cur == dialog->packets) { 00327 ast_log(LOG_WARNING, "Have a packet that doesn't want to give up! %s\n", sip_method2txt(cur->method)); 00328 return; 00329 } 00330 cur = dialog->packets; 00331 method = (cur->method) ? cur->method : find_sip_method(cur->data); 00332 __sip_ack(dialog, cur->seqno, ast_test_flag(cur, SIP_PKT_RESPONSE), method, FALSE); 00333 } 00334 }
|
|
||||||||||||||||||||
|
Acks receipt of packet, keep it around (used for provisional responses).
Definition at line 339 of file sip3_dialog.c. References ast_log(), ast_sched_del(), ast_test_flag, sip_request::data, sip_request::dialog, LOG_DEBUG, method_match(), sip_request::next, option_debug, sip_dialog::packets, sip_request::retransid, sip_request::seqno, sip_method2txt(), SIP_PKT_RESPONSE, and sipdebug. 00340 { 00341 struct sip_request *cur; 00342 int res = -1; 00343 00344 for (cur = dialog->packets; cur; cur = cur->next) { 00345 if (option_debug > 2) 00346 ast_log(LOG_DEBUG, "--Checking packet with seqno %d against response with seqno %d\n", cur->seqno, seqno); 00347 if (cur->seqno == seqno && ast_test_flag(cur, SIP_PKT_RESPONSE) == resp && 00348 (ast_test_flag(cur, SIP_PKT_RESPONSE) || method_match(sipmethod, cur->data))) { 00349 /* this is our baby */ 00350 if (cur->retransid > -1) { 00351 if (option_debug > 3 && sipdebug) 00352 ast_log(LOG_DEBUG, "Cancelling retransmission #%d - %s (got response)\n", cur->retransid, sip_method2txt(sipmethod)); 00353 ast_sched_del(sched, cur->retransid); 00354 } 00355 cur->retransid = -1; 00356 res = 0; 00357 break; 00358 } 00359 } 00360 if (option_debug) 00361 ast_log(LOG_DEBUG, "(Provisional) Stopping retransmission (but retaining packet) on '%s' %s %d: %s\n", dialog->callid, resp ? "Response" : "Request", seqno, res ? "Not Found" : "Found"); 00362 return res; 00363 }
|
|
|
Protect the SIP dialog list (of sip_dialog's).
|
|
||||||||||||||||
|
A per-thread temporary pvt structure.
|
|
||||||||||||
|
Build a Via header for a request.
Definition at line 1236 of file sip3_dialog.c. References ast_inet_ntoa(), ast_string_field_build, ast_test_flag, sip_dialog::flags, ourdialogbranch(), sip_dialog::ourip, SIP_NAT, SIP_NAT_RFC3581, sipnet, and sipnet_ourport(). 01237 { 01238 /* Work around buggy UNIDEN UIP200 firmware */ 01239 const char *rport = ast_test_flag(&dialog->flags[0], SIP_NAT) & SIP_NAT_RFC3581 ? ";rport" : ""; 01240 01241 /* z9hG4bK is a magic cookie. See RFC 3261 section 8.1.1.7 */ 01242 ast_string_field_build(dialog, via, "SIP/2.0/UDP %s:%d;branch=%s%s", 01243 ast_inet_ntoa(dialog->ourip), sipnet_ourport(&sipnet), 01244 ourdialogbranch(dialog, forcenewbranch), rport); 01245 }
|
|
||||||||||||
|
||||||||||||
|
|
Lock list of active SIP dialogs.
Definition at line 122 of file sip3_dialog.c. References ast_log(), ast_mutex_lock(), ast_mutex_trylock(), LOG_DEBUG, option_debug, and sipdebug. 00123 { 00124 int counter = 0; 00125 while (ast_mutex_trylock(&dialoglock) && counter < 100) { 00126 if (option_debug > 4) 00127 ast_log(LOG_DEBUG, "---Trying to lock dialoglist -- %d \n", ++counter); 00128 } 00129 if (counter == 100) 00130 ast_mutex_lock(&dialoglock); 00131 if (sipdebug && option_debug > 4) 00132 ast_log(LOG_DEBUG, "=== SIP dialog list: LOCKED\n"); 00133 }
|
|
|
Unlock list of active SIP dialogs.
Definition at line 136 of file sip3_dialog.c. References ast_log(), ast_mutex_unlock(), LOG_DEBUG, option_debug, and sipdebug. 00137 { 00138 ast_mutex_unlock(&dialoglock); 00139 if (sipdebug && option_debug > 4) 00140 ast_log(LOG_DEBUG, "=== SIP dialog list: UNLOCKED\n"); 00141 }
|
|
|
Convert SIP dialog states to string.
Definition at line 162 of file sip3_dialog.c. References DIALOG_STATE_CONFIRMED, DIALOG_STATE_CONFIRMED_HOLD, DIALOG_STATE_EARLY, DIALOG_STATE_PROCEEDING, DIALOG_STATE_TERMINATED, DIALOG_STATE_TERMINATED_AUTH, and DIALOG_STATE_TRYING. Referenced by dialogstatechange(), sip_hangup(), and sip_show_channel(). 00163 { 00164 const char *reply = "<unknown>"; 00165 switch (state) { 00166 case DIALOG_STATE_TRYING: 00167 reply = "Trying"; 00168 break; 00169 case DIALOG_STATE_PROCEEDING: 00170 reply = "Proceeding"; 00171 break; 00172 case DIALOG_STATE_EARLY: 00173 reply = "Early"; 00174 break; 00175 case DIALOG_STATE_CONFIRMED: 00176 reply = "Confirmed"; 00177 break; 00178 case DIALOG_STATE_CONFIRMED_HOLD: 00179 reply = "Confirmed, on hold"; 00180 break; 00181 case DIALOG_STATE_TERMINATED: 00182 reply = "Terminated"; 00183 break; 00184 case DIALOG_STATE_TERMINATED_AUTH: 00185 reply = "Terminated, auth"; 00186 break; 00187 } 00188 return reply; 00189 }
|
|
||||||||||||
|
Change dialog state for a SIP dialog and output to debug.
Definition at line 192 of file sip3_dialog.c. References append_history, ast_log(), dialogstate2str(), global, sip_dialog::icseq, LOG_DEBUG, sip_dialog::ocseq, option_debug, sip_globals::recordhistory, sipdebug, and sip_dialog::state. Referenced by handle_request(), handle_request_info(), handle_request_invite(), handle_request_subscribe(), handle_response_invite(), handle_response_notify(), handle_response_peerpoke(), sip_alloc(), sip_answer(), sip_hangup(), sip_indicate(), and transmit_final_response(). 00193 { 00194 if (dialog->state == newstate) { 00195 if (option_debug > 3) 00196 ast_log(LOG_DEBUG, "Asked to change state to dialog that already has requested state: %s State %s\n", dialog->callid, dialogstate2str(newstate)); 00197 } else { 00198 dialog->state = newstate; 00199 if (sipdebug && option_debug > 1) 00200 ast_log(LOG_DEBUG, "-- Dialog %s changed state to %s\n", dialog->callid, dialogstate2str(newstate)); 00201 if (global.recordhistory) 00202 append_history(dialog, "DialogState", "New state: %s O-Cseq %d I-Cseq %d", dialogstate2str(newstate), dialog->ocseq, dialog->icseq); 00203 } 00204 /* When state is terminated, keep it for 32 secs to allow for retransmits 00205 */ 00206 }
|
|
||||||||||||||||
|
Find via branch parameter.
Definition at line 1196 of file sip3_dialog.c. References ast_log(), ast_strdupa, ast_strlen_zero(), ast_test_flag, LOG_DEBUG, option_debug, SIP_PKT_DEBUG, strcasestr(), and sip_request::via. Referenced by match_or_create_dialog(). 01197 { 01198 char *dupvia; 01199 char *viabranch; 01200 char *sep; 01201 01202 if (ast_strlen_zero(req->via)) 01203 return; 01204 dupvia = ast_strdupa(req->via); 01205 if (!(viabranch = strcasestr(dupvia, ";branch="))) 01206 return; 01207 viabranch += 8; 01208 if ((sep = strchr(viabranch, ';'))) 01209 *sep = '\0'; 01210 if (ast_test_flag(req, SIP_PKT_DEBUG) && option_debug > 3) 01211 ast_log(LOG_DEBUG, "* Found via branch %s\n", viabranch); 01212 strncpy(viabuf, viabranch, vialen); 01213 }
|
|
|
Convert Asterisk hangup causes to SIP codes.
Possible values from causes.h
AST_CAUSE_NOTDEFINED AST_CAUSE_NORMAL AST_CAUSE_BUSY
AST_CAUSE_FAILURE AST_CAUSE_CONGESTION AST_CAUSE_UNALLOCATED
In addition to these, a lot of PRI codes is defined in causes.h
...should we take care of them too ?
Quote RFC 3398
ISUP Cause value SIP response
---------------- ------------
1 unallocated number 404 Not Found
2 no route to network 404 Not found
3 no route to destination 404 Not found
16 normal call clearing --- (*)
17 user busy 486 Busy here
18 no user responding 408 Request Timeout
19 no answer from the user 480 Temporarily unavailable
20 subscriber absent 480 Temporarily unavailable
21 call rejected 403 Forbidden (+)
22 number changed (w/o diagnostic) 410 Gone
22 number changed (w/ diagnostic) 301 Moved Permanently
23 redirection to new destination 410 Gone
26 non-selected user clearing 404 Not Found (=)
27 destination out of order 502 Bad Gateway
28 address incomplete 484 Address incomplete
29 facility rejected 501 Not implemented
31 normal unspecified 480 Temporarily unavailable
Definition at line 681 of file sip3_dialog.c. References AST_CAUSE_BEARERCAPABILITY_NOTAVAIL, AST_CAUSE_CALL_REJECTED, AST_CAUSE_CHAN_NOT_IMPLEMENTED, AST_CAUSE_CONGESTION, AST_CAUSE_DESTINATION_OUT_OF_ORDER, AST_CAUSE_FACILITY_REJECTED, AST_CAUSE_FAILURE, AST_CAUSE_INVALID_NUMBER_FORMAT, AST_CAUSE_NO_ANSWER, AST_CAUSE_NO_ROUTE_DESTINATION, AST_CAUSE_NO_ROUTE_TRANSIT_NET, AST_CAUSE_NO_USER_RESPONSE, AST_CAUSE_NORMAL_UNSPECIFIED, AST_CAUSE_NOTDEFINED, AST_CAUSE_NUMBER_CHANGED, AST_CAUSE_SWITCH_CONGESTION, AST_CAUSE_UNALLOCATED, AST_CAUSE_USER_BUSY, ast_log(), LOG_DEBUG, and option_debug. 00682 { 00683 switch (cause) { 00684 case AST_CAUSE_UNALLOCATED: /* 1 */ 00685 case AST_CAUSE_NO_ROUTE_DESTINATION: /* 3 IAX2: Can't find extension in context */ 00686 case AST_CAUSE_NO_ROUTE_TRANSIT_NET: /* 2 */ 00687 return "404 Not Found"; 00688 case AST_CAUSE_CONGESTION: /* 34 */ 00689 case AST_CAUSE_SWITCH_CONGESTION: /* 42 */ 00690 return "503 Service Unavailable"; 00691 case AST_CAUSE_NO_USER_RESPONSE: /* 18 */ 00692 return "408 Request Timeout"; 00693 case AST_CAUSE_NO_ANSWER: /* 19 */ 00694 return "480 Temporarily unavailable"; 00695 case AST_CAUSE_CALL_REJECTED: /* 21 */ 00696 return "403 Forbidden"; 00697 case AST_CAUSE_NUMBER_CHANGED: /* 22 */ 00698 return "410 Gone"; 00699 case AST_CAUSE_NORMAL_UNSPECIFIED: /* 31 */ 00700 return "480 Temporarily unavailable"; 00701 case AST_CAUSE_INVALID_NUMBER_FORMAT: 00702 return "484 Address incomplete"; 00703 case AST_CAUSE_USER_BUSY: 00704 return "486 Busy here"; 00705 case AST_CAUSE_FAILURE: 00706 return "500 Server internal failure"; 00707 case AST_CAUSE_FACILITY_REJECTED: /* 29 */ 00708 return "501 Not Implemented"; 00709 case AST_CAUSE_CHAN_NOT_IMPLEMENTED: 00710 return "503 Service Unavailable"; 00711 /* Used in chan_iax2 */ 00712 case AST_CAUSE_DESTINATION_OUT_OF_ORDER: 00713 return "502 Bad Gateway"; 00714 case AST_CAUSE_BEARERCAPABILITY_NOTAVAIL: /* Can't find codec to connect to host */ 00715 return "488 Not Acceptable Here"; 00716 00717 case AST_CAUSE_NOTDEFINED: 00718 default: 00719 if (option_debug) 00720 ast_log(LOG_DEBUG, "AST hangup cause %d (no match found in SIP)\n", cause); 00721 return NULL; 00722 } 00723 00724 /* Never reached */ 00725 return 0; 00726 }
|
|
|
Convert SIP hangup causes to Asterisk hangup causes.
Definition at line 567 of file sip3_dialog.c. References AST_CAUSE_BEARERCAPABILITY_NOTAVAIL, AST_CAUSE_BUSY, AST_CAUSE_CALL_REJECTED, AST_CAUSE_CONGESTION, AST_CAUSE_DESTINATION_OUT_OF_ORDER, AST_CAUSE_FACILITY_REJECTED, AST_CAUSE_FAILURE, AST_CAUSE_INTERWORKING, AST_CAUSE_INVALID_NUMBER_FORMAT, AST_CAUSE_NO_ANSWER, AST_CAUSE_NO_ROUTE_DESTINATION, AST_CAUSE_NO_USER_RESPONSE, AST_CAUSE_NORMAL, AST_CAUSE_NORMAL_TEMPORARY_FAILURE, AST_CAUSE_RECOVERY_ON_TIMER_EXPIRE, AST_CAUSE_UNALLOCATED, and AST_CAUSE_USER_BUSY. 00568 { 00569 /* Possible values taken from causes.h */ 00570 00571 switch(cause) { 00572 case 401: /* Unauthorized */ 00573 return AST_CAUSE_CALL_REJECTED; 00574 case 403: /* Not found */ 00575 return AST_CAUSE_CALL_REJECTED; 00576 case 404: /* Not found */ 00577 return AST_CAUSE_UNALLOCATED; 00578 case 405: /* Method not allowed */ 00579 return AST_CAUSE_INTERWORKING; 00580 case 407: /* Proxy authentication required */ 00581 return AST_CAUSE_CALL_REJECTED; 00582 case 408: /* No reaction */ 00583 return AST_CAUSE_NO_USER_RESPONSE; 00584 case 409: /* Conflict */ 00585 return AST_CAUSE_NORMAL_TEMPORARY_FAILURE; 00586 case 410: /* Gone */ 00587 return AST_CAUSE_UNALLOCATED; 00588 case 411: /* Length required */ 00589 return AST_CAUSE_INTERWORKING; 00590 case 413: /* Request entity too large */ 00591 return AST_CAUSE_INTERWORKING; 00592 case 414: /* Request URI too large */ 00593 return AST_CAUSE_INTERWORKING; 00594 case 415: /* Unsupported media type */ 00595 return AST_CAUSE_INTERWORKING; 00596 case 420: /* Bad extension */ 00597 return AST_CAUSE_NO_ROUTE_DESTINATION; 00598 case 480: /* No answer */ 00599 return AST_CAUSE_NO_ANSWER; 00600 case 481: /* No answer */ 00601 return AST_CAUSE_INTERWORKING; 00602 case 482: /* Loop detected */ 00603 return AST_CAUSE_INTERWORKING; 00604 case 483: /* Too many hops */ 00605 return AST_CAUSE_NO_ANSWER; 00606 case 484: /* Address incomplete */ 00607 return AST_CAUSE_INVALID_NUMBER_FORMAT; 00608 case 485: /* Ambigous */ 00609 return AST_CAUSE_UNALLOCATED; 00610 case 486: /* Busy everywhere */ 00611 return AST_CAUSE_BUSY; 00612 case 487: /* Request terminated */ 00613 return AST_CAUSE_INTERWORKING; 00614 case 488: /* No codecs approved */ 00615 return AST_CAUSE_BEARERCAPABILITY_NOTAVAIL; 00616 case 491: /* Request pending */ 00617 return AST_CAUSE_INTERWORKING; 00618 case 493: /* Undecipherable */ 00619 return AST_CAUSE_INTERWORKING; 00620 case 500: /* Server internal failure */ 00621 return AST_CAUSE_FAILURE; 00622 case 501: /* Call rejected */ 00623 return AST_CAUSE_FACILITY_REJECTED; 00624 case 502: 00625 return AST_CAUSE_DESTINATION_OUT_OF_ORDER; 00626 case 503: /* Service unavailable */ 00627 return AST_CAUSE_CONGESTION; 00628 case 504: /* Gateway timeout */ 00629 return AST_CAUSE_RECOVERY_ON_TIMER_EXPIRE; 00630 case 505: /* SIP version not supported */ 00631 return AST_CAUSE_INTERWORKING; 00632 case 600: /* Busy everywhere */ 00633 return AST_CAUSE_USER_BUSY; 00634 case 603: /* Decline */ 00635 return AST_CAUSE_CALL_REJECTED; 00636 case 604: /* Does not exist anywhere */ 00637 return AST_CAUSE_UNALLOCATED; 00638 case 606: /* Not acceptable */ 00639 return AST_CAUSE_BEARERCAPABILITY_NOTAVAIL; 00640 default: 00641 return AST_CAUSE_NORMAL; 00642 } 00643 /* Never reached */ 00644 return 0; 00645 }
|
|
||||||||||||
|
Initialize the initital request packet in the pvt structure. This packet is used for creating replies and future requests in a dialog.
Definition at line 239 of file sip3_dialog.c. References ast_log(), ast_test_flag, ast_verbose(), sip_request::headers, sip_dialog::initreq, sip_request::lines, LOG_DEBUG, option_debug, set_initreq(), SIP_PKT_CONNECTED, SIP_PKT_DEBUG, and siprequest_free(). 00240 { 00241 /* If we already have an initial req, free it if it's not waiting for an ACK */ 00242 if (dialog->initreq) { 00243 if (option_debug > 2) 00244 ast_log(LOG_DEBUG, "Initializing already initialized SIP dialog %s (presumably reinvite)\n", dialog->callid); 00245 if (!ast_test_flag(dialog->initreq, SIP_PKT_CONNECTED)) 00246 siprequest_free(dialog->initreq); 00247 } 00248 /* Use this as the basis */ 00249 set_initreq(dialog, req); 00250 //parse_request(dialog->initreq); 00251 if (ast_test_flag(req, SIP_PKT_DEBUG)) 00252 ast_verbose("Initreq: %d headers, %d lines\n", dialog->initreq->headers, dialog->initreq->lines); 00253 }
|
|
||||||||||||
|
Make our SIP dialog tag.
Definition at line 729 of file sip3_dialog.c. References ast_random(), and sipdebug. 00730 { 00731 if (sipdebug) 00732 snprintf(tagbuf, len, "asterisk%08lx", ast_random()); 00733 else 00734 snprintf(tagbuf, len, "%08lx", ast_random()); 00735 }
|
|
||||||||||||||||
|
Definition at line 1053 of file sip3_dialog.c. References ast_log(), ast_set_flag, ast_strlen_zero(), sip_request::callid, sip_request::cseqheader, dialoglist, dialoglist_lock(), FALSE, find_via_branch(), sip_request::from, get_header(), gettag(), LOG_DEBUG, sip_dialog::next, option_debug, SIP_ACK, SIP_BYE, SIP_INFO, sip_methods, SIP_PKT_WITH_TOTAG, SIP_REGISTER, SIP_RESPONSE, sip_dialog::tag, cfsip_methods::text, and sip_request::to. Referenced by process_sip_queue(). 01054 { 01055 struct sip_dialog *cur = NULL; 01056 char *tag = ""; /* note, tag is never NULL */ 01057 char totag[128]; 01058 char fromtag[128]; 01059 char branch[128]; 01060 01061 if (ast_strlen_zero(req->callid)) 01062 req->callid = get_header(req, "Call-ID"); 01063 if (ast_strlen_zero(req->from)) 01064 req->from = get_header(req, "From"); 01065 if (ast_strlen_zero(req->to)) 01066 req->to = get_header(req, "To"); 01067 if (ast_strlen_zero(req->cseqheader)) 01068 req->cseqheader = get_header(req, "Cseq"); 01069 01070 /* Call-ID, to, from and Cseq are required by RFC 3261. (Max-forwards and via too - ignored now) */ 01071 /* get_header always returns non-NULL so we must use ast_strlen_zero() */ 01072 if (ast_strlen_zero(req->callid) || ast_strlen_zero(req->to) || 01073 ast_strlen_zero(req->from) || ast_strlen_zero(req->cseqheader)) 01074 return NULL; /* Invalid packet */ 01075 01076 /* In principle Call-ID's uniquely identify a call, but with a forking SIP proxy 01077 we need more to identify a branch - so we have to check branch, from 01078 and to tags to identify a call leg. 01079 */ 01080 if (gettag(req->to, totag, sizeof(totag))) 01081 ast_set_flag(req, SIP_PKT_WITH_TOTAG); /* Used in handle_request/response */ 01082 gettag(req->from, fromtag, sizeof(fromtag)); 01083 01084 tag = (req->method == SIP_RESPONSE) ? totag : fromtag; 01085 01086 /* All messages must always have From: tag */ 01087 if (ast_strlen_zero(fromtag)) { 01088 if (option_debug > 4 ) 01089 ast_log(LOG_DEBUG, "%s request has no from tag, dropping callid: %s from: %s\n", sip_methods[req->method].text, req->callid, req->from ); 01090 return NULL; 01091 } 01092 /* reject requests that must always have a To: tag */ 01093 if (ast_strlen_zero(totag) && (req->method == SIP_ACK || req->method == SIP_BYE || req->method == SIP_INFO )) { 01094 if (option_debug > 4) 01095 ast_log(LOG_DEBUG, "%s must have a to tag. dropping callid: %s from: %s\n", sip_methods[req->method].text, req->callid, req->from ); 01096 return NULL; 01097 } 01098 01099 dialoglist_lock(); 01100 01101 if (option_debug > 4 ) 01102 ast_log(LOG_DEBUG, "= Looking for Call ID: %s (Checking %s) --From tag %s --To-tag %s \n", req->callid, req->method==SIP_RESPONSE ? "To" : "From", fromtag, totag); 01103 01104 find_via_branch(req, branch, sizeof(branch)); 01105 for (cur = dialoglist; cur; cur = cur->next) { 01106 /* we do not want packets with bad syntax to be connected to a PVT */ 01107 int found = FALSE; 01108 if (req->method == SIP_REGISTER) 01109 found = (!strcmp(cur->callid, req->callid)); 01110 else 01111 found = (!strcmp(cur->callid, req->callid) && 01112 (!tag || ast_strlen_zero(cur->theirtag) || !strcmp(cur->theirtag, tag))) ; 01113 01114 if (option_debug > 4) 01115 ast_log(LOG_DEBUG, "= %s Their Call ID: %s Their Tag %s Our tag: %s\n", found ? "Found" : "No match", cur->callid, cur->theirtag, cur->tag); 01116 01117 /* If we get a new request within an existing to-tag - check the to tag as well */ 01118 if (found && req->method != SIP_RESPONSE) { /* SIP Request */ 01119 if (cur->tag[0] == '\0' && totag[0]) { 01120 /* We have no to tag, but they have. Wrong dialog */ 01121 found = FALSE; 01122 } else if (totag[0]) { /* Both have tags, compare them */ 01123 if (strcmp(totag, cur->tag)) { 01124 found = FALSE; /* This is not our dialog */ 01125 } 01126 } 01127 if (!found && option_debug > 4) 01128 ast_log(LOG_DEBUG, "= Being pedantic: This is not our match on request: Call ID: %s Ourtag <null> Totag %s Method %s\n", cur->callid, totag, sip_method2txt(req->method)); 01129 } 01130 01131 /* We need to check the branch too, to make sure this is the proper reply */ 01132 /* If it is an INVITE from us coming back with a new branch, we need to 01133 do some masquerading trickery with the audio. 01134 We might also get several INVITEs with different branches 01135 and have to treat them as several calls 01136 */ 01137 if (found) { 01138 if (!strcmp(cur->ourbranch, branch)) { 01139 /* This is our own request coming back to us strangely enough */ 01140 /* Propably through DNS, but not a proxy */ 01141 /* Bad dialplan design... ; -) */ 01142 /* Any way we can handle this??? */ 01143 } 01144 /* If we have a remote branch already, and get a new branch with the 01145 same call ID, then something is happening. 01146 For responses - we might have a forking proxy and get responses 01147 from several UAs on one request. 01148 For requests, we might be getting a statelessly forked call to us. 01149 */ 01150 if (!ast_strlen_zero(cur->remotebranch) && strcmp(cur->remotebranch, branch)) { 01151 /* XXX What do we do here ? */ 01152 01153 } 01154 } 01155 01156 01157 if (found) { 01158 /* Found the dialog */ 01159 dialog_lock(cur, TRUE); /* Lock the dialog */ 01160 dialoglist_unlock(); /* Unlock the list */ 01161 return cur; 01162 } 01163 } 01164 dialoglist_unlock(); 01165 if (sip_methods[intended_method].creates_dialog != CAN_CREATE_DIALOG) { 01166 if (intended_method != SIP_RESPONSE && intended_method != SIP_ACK) 01167 transmit_response_using_temp(req->callid, sin, TRUE, intended_method, req, "481 Call leg/transaction does not exist"); 01168 else 01169 logdebug(2, "Got response or ACK to non-existing transaction. No action taken. Call-ID: %s\n", req->callid); 01170 return cur; 01171 } 01172 switch (intended_method) { 01173 case SIP_REFER: 01174 /* We do not support out-of-dialog REFERs yet */ 01175 transmit_response_using_temp(req->callid, sin, TRUE, intended_method, req, "603 Declined (no dialog)"); 01176 break; 01177 case SIP_NOTIFY: 01178 /* We do not support out-of-dialog NOTIFY either, 01179 like voicemail notification, so cancel that early */ 01180 transmit_response_using_temp(req->callid, sin, TRUE, intended_method, req, "489 Bad event"); 01181 break; 01182 default: 01183 /* ready to create a new dialog. */ 01184 if ((cur = sip_alloc(req->callid, sin, TRUE, intended_method))) { 01185 /* This method creates dialog */ 01186 /* Ok, we've created a dialog, let's go and process it */ 01187 dialog_lock(cur, TRUE); 01188 } 01189 break; 01190 } 01191 01192 return cur; 01193 }
|
|
||||||||||||
|
Make branch tag for via header if it does not exist yet.
Definition at line 1217 of file sip3_dialog.c. References ast_random(), ast_string_field_set, and ast_strlen_zero(). Referenced by build_via(). 01218 { 01219 char branch[20]; 01220 int seed = 0; 01221 01222 if (forcenewbranch || ast_strlen_zero(dialog->ourbranch)) { 01223 if (forcenewbranch) 01224 seed ^= ast_random(); 01225 else 01226 seed = ast_random(); 01227 snprintf(branch, sizeof(branch), "z9hG4bk%08x", seed); 01228 ast_string_field_set(dialog, ourbranch, branch); 01229 } 01230 01231 return((char *) dialog->ourbranch); 01232 01233 }
|
|
||||||||||||
|
Set packet to initreq status. Set flag to avoid de-allocation until dialog is destroyed.
Definition at line 229 of file sip3_dialog.c. References ast_set_flag, sip_dialog::initreq, and SIP_PKT_INITREQ. Referenced by handle_request_bye(), handle_request_invite(), handle_request_register(), handle_request_subscribe(), and initialize_initreq(). 00230 { 00231 dialog->initreq = req; 00232 ast_set_flag(dialog->initreq, SIP_PKT_INITREQ); 00233 00234 }
|
|
||||||||||||||||||||
|
Allocate SIP_PVT structure and set defaults.
Definition at line 803 of file sip3_dialog.c. References sip_network::__ourip, sip_globals::allowtransfer, ast_calloc, ast_copy_flags, ast_log(), ast_mutex_destroy(), ast_mutex_init(), AST_RTP_DTMF, ast_set2_flag, ast_string_field_init, ast_string_field_set, ast_test_flag, ast_variables_destroy(), build_callid_pvt(), build_via(), sip_globals::capability, context, sip_globals::default_context, sip_globals::default_fromdomain, sip_globals::default_mohinterpret, sip_globals::default_mohsuggest, sip_globals::default_prefs, dialog_activate_media(), channel_counters::dialog_objects, DIALOG_STATE_TRYING, dialoglist, dialoglist_lock(), dialoglist_unlock(), dialogstatechange(), do_setnat(), sip_globals::flags, free, global, INITIAL_CSEQ, LOG_DEBUG, make_our_tag(), mohinterpret, mohsuggest, NONE, option_debug, sip_globals::recordhistory, SIP_DTMF, SIP_DTMF_AUTO, SIP_DTMF_RFC2833, SIP_FLAGS_TO_COPY, sip_method2txt(), sip_method_needrtp(), SIP_NAT, SIP_NAT_ROUTE, SIP_NO_HISTORY, SIP_OPTIONS, sip_ouraddrfor(), SIP_PAGE2_FLAGS_TO_COPY, SIP_REGISTER, sipcounters, sipnet, sip_globals::t1default, and TRUE. 00805 { 00806 struct sip_dialog *dialog; 00807 00808 if (!(dialog = ast_calloc(1, sizeof(*dialog)))) 00809 return NULL; 00810 00811 if (ast_string_field_init(dialog, 512)) { 00812 free(dialog); 00813 return NULL; 00814 } 00815 sipcounters.dialog_objects++; 00816 if (option_debug > 3) 00817 ast_log(LOG_DEBUG, "--DIALOGS-- Counter %d\n", sipcounters.dialog_objects); 00818 00819 ast_mutex_init(&dialog->lock); 00820 00821 dialog->method = intended_method; 00822 dialog->initid = -1; 00823 dialog->autokillid = -1; 00824 dialog->subscribed = NONE; 00825 dialog->stateid = -1; 00826 dialog->prefs = global.default_prefs; /* Set default codecs for this call */ 00827 00828 if (intended_method != SIP_OPTIONS) /* Peerpoke has it's own system */ 00829 dialog->timer_t1 = global.t1default; /* 500 ms Default SIP retransmission timer T1 (RFC 3261) */ 00830 00831 if (sin) { 00832 dialog->sa = *sin; 00833 if (sip_ouraddrfor(&dialog->sa.sin_addr, &dialog->ourip)) 00834 dialog->ourip = sipnet.__ourip; 00835 } else 00836 dialog->ourip = sipnet.__ourip; 00837 00838 /* Copy global flags to this PVT at setup. */ 00839 ast_copy_flags(&dialog->flags[0], &global.flags[0], SIP_FLAGS_TO_COPY); 00840 ast_copy_flags(&dialog->flags[1], &global.flags[1], SIP_PAGE2_FLAGS_TO_COPY); 00841 00842 ast_set2_flag(&dialog->flags[0], !global.recordhistory, SIP_NO_HISTORY); 00843 00844 make_our_tag(dialog->tag, sizeof(dialog->tag)); 00845 dialog->ocseq = INITIAL_CSEQ; 00846 00847 /* Activate media streams */ 00848 if (sip_method_needrtp(intended_method)) { 00849 if (!dialog_activate_media(dialog, &sipnet)) { 00850 ast_mutex_destroy(&dialog->lock); 00851 if (dialog->chanvars) { 00852 ast_variables_destroy(dialog->chanvars); 00853 dialog->chanvars = NULL; 00854 } 00855 free(dialog); 00856 return NULL; 00857 } 00858 } 00859 00860 if (useglobal_nat && sin) { 00861 /* Setup NAT structure according to global settings if we have an address */ 00862 ast_copy_flags(&dialog->flags[0], &global.flags[0], SIP_NAT); 00863 dialog->recv = *sin; 00864 do_setnat(dialog, ast_test_flag(&dialog->flags[0], SIP_NAT) & SIP_NAT_ROUTE); 00865 } 00866 00867 if (dialog->method != SIP_REGISTER) 00868 ast_string_field_set(dialog, fromdomain, global.default_fromdomain); 00869 00870 build_via(dialog, TRUE); 00871 if (!callid) /* Make sure we have a unique call ID */ 00872 build_callid_pvt(dialog); 00873 else 00874 ast_string_field_set(dialog, callid, callid); 00875 00876 dialogstatechange(dialog, DIALOG_STATE_TRYING); /* Set dialog state */ 00877 00878 /* Assign default music on hold class */ 00879 ast_string_field_set(dialog, mohinterpret, global.default_mohinterpret); 00880 ast_string_field_set(dialog, mohsuggest, global.default_mohsuggest); 00881 00882 dialog->capability = global.capability; /* Set default codec settings */ 00883 00884 if ((ast_test_flag(&dialog->flags[0], SIP_DTMF) == SIP_DTMF_RFC2833) || 00885 (ast_test_flag(&dialog->flags[0], SIP_DTMF) == SIP_DTMF_AUTO)) 00886 dialog->noncodeccapability |= AST_RTP_DTMF; 00887 00888 ast_string_field_set(dialog, context, global.default_context); 00889 dialog->allowtransfer = global.allowtransfer; /* Default transfer mode */ 00890 00891 /* Add to active dialog list */ 00892 dialoglist_lock(); 00893 dialog->next = dialoglist; 00894 dialoglist = dialog; 00895 dialoglist_unlock(); 00896 if (option_debug) 00897 ast_log(LOG_DEBUG, "Allocating new SIP dialog for %s - %s (%s)\n", callid ? callid : "(No Call-ID)", sip_method2txt(intended_method), dialog->rtp ? "With RTP" : "No RTP"); 00898 return dialog; 00899 }
|
|
|
Cancel destruction of SIP dialog.
Definition at line 554 of file sip3_dialog.c. References append_history, ast_sched_del(), and sip_dialog::autokillid. 00555 { 00556 if (p->autokillid > -1) { 00557 ast_sched_del(sched, p->autokillid); 00558 append_history(p, "CancelDestroy", ""); 00559 p->autokillid = -1; 00560 } 00561 }
|
|
|
Destroy SIP call structure.
Definition at line 486 of file sip3_dialog.c. References __sip_destroy(), ast_log(), LOG_DEBUG, option_debug, and TRUE. 00487 { 00488 if (option_debug > 2) 00489 ast_log(LOG_DEBUG, "Destroying SIP dialog %s\n", dialog->callid); 00490 __sip_destroy(dialog, TRUE, TRUE); 00491 }
|
|
||||||||||||
|
Schedule destruction of SIP dialog.
Definition at line 536 of file sip3_dialog.c. References __sip_autodestruct(), append_history, ast_sched_add(), ast_sched_del(), ast_test_flag, ast_verbose(), sip_dialog::flags, sip_dialog::method, sip_debug_test_pvt(), sip_method2txt(), SIP_NO_HISTORY, and sip_dialog::timer_t1. 00537 { 00538 if (ms < 0) { 00539 if (p->timer_t1 == 0) 00540 p->timer_t1 = 500; /* Set timer T1 if not set (RFC 3261) */ 00541 ms = p->timer_t1 * 64; 00542 } 00543 if (sip_debug_test_pvt(p)) 00544 ast_verbose("Scheduling destruction of SIP dialog '%s' in %d ms (Method: %s)\n", p->callid, ms, sip_method2txt(p->method)); 00545 if (!ast_test_flag(&p->flags[0], SIP_NO_HISTORY)) 00546 append_history(p, "SchedDestroy", "%d ms", ms); 00547 00548 if (p->autokillid > -1) 00549 ast_sched_del(sched, p->autokillid); 00550 p->autokillid = ast_sched_add(sched, ms, __sip_autodestruct, p); 00551 }
|
|
|
Cleanup temporary PVT.
Definition at line 911 of file sip3_dialog.c. References ast_string_field_free_pools, and free. 00912 { 00913 struct sip_dialog *p = data; 00914 00915 ast_string_field_free_pools(p); 00916 00917 free(data); 00918 }
|
|
|
Initialize temporary PVT.
Definition at line 902 of file sip3_dialog.c. References ast_set_flag, ast_string_field_init, sip_dialog::flags, and SIP_NO_HISTORY. 00903 { 00904 struct sip_dialog *p = data; 00905 00906 ast_set_flag(&p->flags[0], SIP_NO_HISTORY); 00907 return ast_string_field_init(p, 512); 00908 }
|
|
||||||||||||||||||||
|
Transmit final response to a request and close dialog Set dialog state to TERMINATED to avoid problems At some point, after debugging, we can remove the reliable flag. Only responses to INVITEs are sent reliably.
Definition at line 213 of file sip3_dialog.c. References __transmit_response(), ast_log(), DIALOG_STATE_TERMINATED, dialogstatechange(), LOG_WARNING, sip_request::method, SIP_INVITE, sip_method2txt(), sip_scheddestroy(), and XMIT_RELIABLE. Referenced by handle_request_info(), handle_request_invite(), handle_request_message(), handle_request_subscribe(), and sip_indicate(). 00214 { 00215 int res; 00216 00217 /* If this is a final response to an INVITE */ 00218 if (reliable == XMIT_RELIABLE && req->method != SIP_INVITE) 00219 ast_log(LOG_WARNING, "Transmitting RELIABLE response to %s - Call ID %s (?? BUG ?? ) \n", sip_method2txt(req->method), dialog->callid); 00220 res = __transmit_response(dialog, msg, req, reliable); 00221 sip_scheddestroy(dialog, -1); /* Destroy by using T1 timer if available */ 00222 dialogstatechange(dialog, DIALOG_STATE_TERMINATED); 00223 return res; 00224 }
|
|
||||||||||||||||||||||||||||
|
Transmit response, no retransmits, using a temporary pvt structure.
Definition at line 921 of file sip3_dialog.c. References sip_network::__ourip, __transmit_response(), ast_copy_flags, ast_log(), ast_set_flag, ast_string_field_free_all, ast_string_field_init, ast_string_field_set, ast_test_flag, build_via(), sip_globals::default_fromdomain, do_setnat(), sip_globals::flags, global, INITIAL_CSEQ, LOG_NOTICE, make_our_tag(), SIP_NAT, SIP_NAT_ROUTE, SIP_NO_HISTORY, sip_ouraddrfor(), sipnet, TRUE, and XMIT_UNRELIABLE. 00922 { 00923 struct sip_dialog *p = NULL; 00924 00925 if (!(p = ast_threadstorage_get(&ts_temp_pvt, sizeof(*p)))) { 00926 ast_log(LOG_NOTICE, "Failed to get temporary pvt\n"); 00927 return -1; 00928 } 00929 00930 /* if the structure was just allocated, initialize it */ 00931 if (!ast_test_flag(&p->flags[0], SIP_NO_HISTORY)) { 00932 ast_set_flag(&p->flags[0], SIP_NO_HISTORY); 00933 if (ast_string_field_init(p, 512)) 00934 return -1; 00935 } 00936 00937 /* Initialize the bare minimum */ 00938 p->method = intended_method; 00939 00940 if (sin) { 00941 p->sa = *sin; 00942 if (sip_ouraddrfor(&p->sa.sin_addr, &p->ourip)) 00943 p->ourip = sipnet.__ourip; 00944 } else 00945 p->ourip = sipnet.__ourip; 00946 00947 make_our_tag(p->tag, sizeof(p->tag)); 00948 p->ocseq = INITIAL_CSEQ; 00949 00950 if (useglobal_nat && sin) { 00951 ast_copy_flags(&p->flags[0], &global.flags[0], SIP_NAT); 00952 p->recv = *sin; 00953 do_setnat(p, ast_test_flag(&p->flags[0], SIP_NAT) & SIP_NAT_ROUTE); 00954 } 00955 00956 ast_string_field_set(p, fromdomain, global.default_fromdomain); 00957 build_via(p, TRUE); 00958 ast_string_field_set(p, callid, callid); 00959 00960 /* Use this temporary pvt structure to send the message */ 00961 __transmit_response(p, msg, req, XMIT_UNRELIABLE); 00962 00963 /* Free the string fields, but not the pool space */ 00964 ast_string_field_free_all(p); 00965 00966 return 0; 00967 }
|