[asterisk-commits] oej: branch oej/codename-pineapple r46900 - in
/team/oej/codename-pineapple: ...
asterisk-commits at lists.digium.com
asterisk-commits at lists.digium.com
Thu Nov 2 08:19:34 MST 2006
Author: oej
Date: Thu Nov 2 09:19:34 2006
New Revision: 46900
URL: http://svn.digium.com/view/asterisk?rev=46900&view=rev
Log:
Updates
Modified:
team/oej/codename-pineapple/channels/chan_sip3.c
team/oej/codename-pineapple/channels/sip3/sip3.h
team/oej/codename-pineapple/channels/sip3/sip3_auth.c
team/oej/codename-pineapple/channels/sip3/sip3_cliami.c
team/oej/codename-pineapple/channels/sip3/sip3_config.c
team/oej/codename-pineapple/channels/sip3/sip3_dialog.c
team/oej/codename-pineapple/channels/sip3/sip3_network.c
team/oej/codename-pineapple/channels/sip3/sip3_parse.c
team/oej/codename-pineapple/channels/sip3/sip3_services.c
team/oej/codename-pineapple/channels/sip3/sip3funcs.h
team/oej/codename-pineapple/configs/sip3.conf.sample
Modified: team/oej/codename-pineapple/channels/chan_sip3.c
URL: http://svn.digium.com/view/asterisk/team/oej/codename-pineapple/channels/chan_sip3.c?rev=46900&r1=46899&r2=46900&view=diff
==============================================================================
--- team/oej/codename-pineapple/channels/chan_sip3.c (original)
+++ team/oej/codename-pineapple/channels/chan_sip3.c Thu Nov 2 09:19:34 2006
@@ -49,6 +49,8 @@
* \todo Transaction support
*
* \ingroup channel_drivers
+ */
+/*! \page Chan_sip3_overview Chan_SIP3:: Overview
*
* \par Overview of the handling of SIP sessions
* The SIP channel handles several types of SIP sessions, or dialogs,
@@ -93,6 +95,19 @@
* \par Hanging up
* The PBX issues a hangup on both incoming and outgoing calls through
* the sip_hangup() function
+ *
+ * \title Dialogs, packets, transactions
+ *
+ * This version of chan_sip has a concept of a SIP dialog (\ref sip_dialog) that
+ * lives throughut a session - a call (INVITE), a registration (REGISTER)
+ * or a subscription for status (SUBSCRIBE)... We do save new requests we
+ * send in a queue (sip_dialog->packets) until they're acknowledged by the
+ * remote party, when we remove them (sip_ack() )
+ *
+ * For requests and responses, we store them in a structure called \ref sip_request
+ * and process them. The matching between a response or a new request and an
+ * existing dialog is done in match_or_create_dialog().
+ *
*/
/*! \page chan_sip3_00index Chan_sip3: Index over docs
@@ -103,6 +118,7 @@
- \ref chan_sip3_files
- \ref chan_sip3_auth
- \ref chan_sip3_dialogs
+ - \ref chan_sip3_overview
\par todo Things to do, ideas
- \ref chan_sip3_todo
@@ -132,12 +148,20 @@
- removed "type=user"
- change "sip nodebug" to "sip debug off" and "sip debug" to "sip debug on" - done
- change "sip history" and "nohistory" to "on/off" - done
+ - "sip show/list peers" is now "sip show/list phones"
+ - manager command renamed - SIPdevices and SIPshowdevice
+ - Added "authuser" configuration option for trunks and services
+ - Added "domain" configuration option for all devices
Halfdone
- Added separate TOS setting for presence. Need to run setsockopt
in a locked socket for that to work on the SIP interface.
Todo
+ - Make show devices and the completion support domains too
+ - Fix realtime caching and optional loading
+ - Clean up the authuser/username/peername mess!
+ - authuser as a separate config option, please, please
- Split up source code file
- Add astum
- Add T1 configuration settings
@@ -241,6 +265,56 @@
- \b sip3_services.c Outbound registrations (services)
*/
+/*!
+ * \page chan_sip3_transactions Implementing transactions
+ *
+ * A SIP transaction is a request and one or several responses.
+ * The INVITE transaction is special, it's a three-way handshake
+ * request - response - ack
+ *
+ * Responses are divided into temporary responses and final responses.
+ * A final response closes the transaction, temporary responses
+ * just updates the transaction.
+ *
+ * Some transactions will open a new SIP dialog, some will not.
+ * Some transactions are allowed within an active dialog, some
+ * are not.
+ *
+ * \title Transactions and chan_sip
+ * The current version of chan_sip.c does not have much notion
+ * of a SIP transaction or a dialog. Each transaction will update
+ * the dialog, so only the last request is remembered and the
+ * direction of the last request.
+ *
+ * While this can be seen as effective, it does not allow
+ * for situations with multiple concurrent transactions.
+ * Most importantly, the INVITE transaction can be open for
+ * a long time (Ringing) and other things may happen at
+ * the same time.
+ *
+ * We do need to change chan_sip3 so that the transaction
+ * state engine works properly.
+
+ * \title Random thoughts
+ * - Integrate sip_pkt and sip_request
+ * - Use sip-request as "transaction holders" within sip_dialog
+ * - Keep them in Cseq order
+ * - Add transaction state
+ * - When do you delete them - 32 secs after first transmit
+ * - Then we finally can fix the "ignore" ignorant stuff and resend last response
+ * - The first transaction that opened in a dialog needs to be saved for the
+ * CANCEL/BYE (in an INVITE transaction)
+ * - For SUBSCRIBE dialogs, we need to keep the initial SUBSCRIBE
+ * Then unacknowledged NOTIFY transactions. Keep the transaction
+ * until timer expires
+ *
+ * SIP_dialog
+ * - sip_trans
+ * Request (our or remote)
+ * response (our or remote)
+ * - sip_trans
+ *
+ */
/* -END- documentation pages */
#define CHAN_SIP3_MAIN
@@ -394,13 +468,8 @@
static int does_peer_need_mwi(struct sip_peer *peer);
/*--- Dialog management */
-GNURK void sip_destroy(struct sip_dialog *p);
-static void __sip_destroy(struct sip_dialog *p, int lockowner);
-static void __sip_ack(struct sip_dialog *dialog, int seqno, int resp, int sipmethod, int reset);
-static int __sip_semi_ack(struct sip_dialog *p, int seqno, int resp, int sipmethod);
static int auto_congest(void *nothing);
static int update_call_counter(struct sip_dialog *fup, int event);
-static void free_old_route(struct sip_route *route);
static void list_route(struct sip_route *route);
static void build_route(struct sip_dialog *p, struct sip_request *req, int backwards);
static enum check_auth_result register_verify(struct sip_dialog *p, struct sockaddr_in *sin,
@@ -457,9 +526,8 @@
Functions for enabling debug per IP or fully, or enabling history logging for
a SIP dialog
*/
-static void sip_dump_history(struct sip_dialog *dialog); /* Dump history to LOG_DEBUG at end of dialog, before destroying data */
+GNURK void sip_dump_history(struct sip_dialog *dialog); /* Dump history to LOG_DEBUG at end of dialog, before destroying data */
static inline int sip_debug_test_pvt(struct sip_dialog *p);
-static void sip_dump_history(struct sip_dialog *dialog);
/*--- Device object handling */
static struct sip_peer *temp_peer(const char *name);
@@ -482,7 +550,6 @@
static int get_rdnis(struct sip_dialog *p, struct sip_request *oreq);
static int get_destination(struct sip_dialog *p, struct sip_request *oreq);
static int get_msg_text(char *buf, int len, struct sip_request *req);
-static void free_old_route(struct sip_route *route);
/*--- Constructing requests and responses */
static void initreqprep(struct sip_request *req, struct sip_dialog *p, int sipmethod);
@@ -491,23 +558,22 @@
static void build_rpid(struct sip_dialog *p);
/*------Request handling functions */
-static int handle_request_invite(struct sip_dialog *p, struct sip_request *req, int debug, int seqno, struct sockaddr_in *sin, int *recount, char *e);
+static int handle_request_invite(struct sip_dialog *p, struct sip_request *req, int debug, struct sockaddr_in *sin, int *recount, char *e);
static int handle_request_bye(struct sip_dialog *p, struct sip_request *req);
static int handle_request_register(struct sip_dialog *p, struct sip_request *req, struct sockaddr_in *sin, char *e);
static int handle_request_cancel(struct sip_dialog *p, struct sip_request *req);
static int handle_request_message(struct sip_dialog *p, struct sip_request *req);
-static int handle_request_subscribe(struct sip_dialog *p, struct sip_request *req, struct sockaddr_in *sin, int seqno, char *e);
+static int handle_request_subscribe(struct sip_dialog *p, struct sip_request *req, struct sockaddr_in *sin, char *e);
static void handle_request_info(struct sip_dialog *p, struct sip_request *req);
static int handle_request_options(struct sip_dialog *p, struct sip_request *req);
-static int handle_invite_replaces(struct sip_dialog *p, struct sip_request *req, int debug, int ignore, int seqno, struct sockaddr_in *sin);
-static int handle_request_notify(struct sip_dialog *p, struct sip_request *req, struct sockaddr_in *sin, int seqno, char *e);
-static int handle_invite_replaces(struct sip_dialog *p, struct sip_request *req, int debug, int ignore, int seqno, struct sockaddr_in *sin);
+static int handle_invite_replaces(struct sip_dialog *p, struct sip_request *req, int debug, struct sockaddr_in *sin);
+static int handle_request_notify(struct sip_dialog *p, struct sip_request *req, struct sockaddr_in *sin, char *e);
/*------Response handling functions */
-static void handle_response_invite(struct sip_dialog *p, int resp, char *rest, struct sip_request *req, int seqno);
-static void handle_response_refer(struct sip_dialog *p, int resp, char *rest, struct sip_request *req, int seqno);
+static void handle_response_invite(struct sip_dialog *p, int resp, char *rest, struct sip_request *req);
+static void handle_response_refer(struct sip_dialog *p, int resp, char *rest, struct sip_request *req);
static void handle_response_peerpoke(struct sip_dialog *p, int resp, struct sip_request *req);
-static void handle_response(struct sip_dialog *p, int resp, char *rest, struct sip_request *req, int seqno);
+static void handle_response(struct sip_dialog *p, int resp, char *rest, struct sip_request *req);
/*----- RTP interface functions */
static void stop_media_flows(struct sip_dialog *p);
@@ -542,35 +608,37 @@
/*! \brief Initialize the initital request packet in the pvt structure.
This packet is used for creating replies and future requests in
a dialog */
-GNURK void initialize_initreq(struct sip_dialog *p, struct sip_request *req)
-{
- if (p->initreq.headers && option_debug) {
- ast_log(LOG_DEBUG, "Initializing already initialized SIP dialog %s (presumably reinvite)\n", p->callid);
+GNURK void initialize_initreq(struct sip_dialog *dialog, struct sip_request *req)
+{
+ if (dialog->initreq.headers && option_debug) {
+ ast_log(LOG_DEBUG, "Initializing already initialized SIP dialog %s (presumably reinvite)\n", dialog->callid);
}
/* Use this as the basis */
- copy_request(&p->initreq, req);
- parse_request(&p->initreq);
+ copy_request(&dialog->initreq, req);
+ /* XX Instead -allocate this request in the dialog->packets linked list */
+ ast_set_flag(&dialog->initreq, SIP_PKT_INITREQ);
+ parse_request(&dialog->initreq);
if (ast_test_flag(req, SIP_PKT_DEBUG))
- ast_verbose("%d headers, %d lines\n", p->initreq.headers, p->initreq.lines);
+ ast_verbose("Initreq: %d headers, %d lines\n", dialog->initreq.headers, dialog->initreq.lines);
}
/*! \brief Test PVT for debugging output */
-inline int sip_debug_test_pvt(struct sip_dialog *p)
+inline int sip_debug_test_pvt(struct sip_dialog *dialog)
{
if (!sipdebug)
return 0;
- return sip_debug_test_addr(sip_real_dst(p));
+ return sip_debug_test_addr(sip_real_dst(dialog));
}
/*! \brief Build a Via header for a request */
-GNURK void build_via(struct sip_dialog *p)
+GNURK void build_via(struct sip_dialog *dialog)
{
/* Work around buggy UNIDEN UIP200 firmware */
- const char *rport = ast_test_flag(&p->flags[0], SIP_NAT) & SIP_NAT_RFC3581 ? ";rport" : "";
+ const char *rport = ast_test_flag(&dialog->flags[0], SIP_NAT) & SIP_NAT_RFC3581 ? ";rport" : "";
/* z9hG4bK is a magic cookie. See RFC 3261 section 8.1.1.7 */
- ast_string_field_build(p, via, "SIP/2.0/UDP %s:%d;branch=z9hG4bK%08x%s",
- ast_inet_ntoa(p->ourip), sipnet_ourport(), p->branch, rport);
+ ast_string_field_build(dialog, via, "SIP/2.0/UDP %s:%d;branch=z9hG4bK%08x%s",
+ ast_inet_ntoa(dialog->ourip), sipnet_ourport(), dialog->branch, rport);
}
GNURK void append_history_full(struct sip_dialog *p, const char *fmt, ...)
@@ -610,89 +678,6 @@
return;
}
-/*! \brief Acknowledges receipt of a packet and stops retransmission */
-static void __sip_ack(struct sip_dialog *dialog, int seqno, int resp, int sipmethod, int reset)
-{
- struct sip_pkt *cur, *prev = NULL;
-
- /* Just in case... */
- char *msg;
- int res = FALSE;
-
- msg = sip_method2txt(sipmethod);
-
- ast_mutex_lock(&dialog->lock);
- for (cur = dialog->packets; cur; prev = cur, cur = cur->next) {
- if ((cur->seqno == seqno) && ((ast_test_flag(cur, FLAG_RESPONSE)) == resp) &&
- ((ast_test_flag(cur, FLAG_RESPONSE)) ||
- (!strncasecmp(msg, cur->data, strlen(msg)) && (cur->data[strlen(msg)] < 33)))) {
- if (!resp && (seqno == dialog->pendinginvite)) {
- if (option_debug)
- ast_log(LOG_DEBUG, "Acked pending invite %d\n", dialog->pendinginvite);
- dialog->pendinginvite = 0;
- }
- /* this is our baby */
- res = TRUE;
- UNLINK(cur, dialog->packets, prev);
- if (cur->retransid > -1) {
- if (sipdebug && option_debug > 3)
- ast_log(LOG_DEBUG, "** SIP TIMER: Cancelling retransmit of packet (reply received) Retransid #%d\n", cur->retransid);
- ast_sched_del(sched, cur->retransid);
- }
- if (!reset)
- free(cur);
- break;
- }
- }
- ast_mutex_unlock(&dialog->lock);
- if (option_debug)
- ast_log(LOG_DEBUG, "Stopping retransmission on '%s' of %s %d: Match %s\n", dialog->callid, resp ? "Response" : "Request", seqno, res ? "Not Found" : "Found");
-}
-
-/*! \brief 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 */
-GNURK void __sip_pretend_ack(struct sip_dialog *dialog)
-{
- struct sip_pkt *cur = NULL;
-
- while (dialog->packets) {
- int method;
- if (cur == dialog->packets) {
- ast_log(LOG_WARNING, "Have a packet that doesn't want to give up! %s\n", sip_method2txt(cur->method));
- return;
- }
- cur = dialog->packets;
- method = (cur->method) ? cur->method : find_sip_method(cur->data);
- __sip_ack(dialog, cur->seqno, ast_test_flag(cur, FLAG_RESPONSE), method, FALSE);
- }
-}
-
-/*! \brief Acks receipt of packet, keep it around (used for provisional responses) */
-static int __sip_semi_ack(struct sip_dialog *p, int seqno, int resp, int sipmethod)
-{
- struct sip_pkt *cur;
- int res = -1;
-
- for (cur = p->packets; cur; cur = cur->next) {
- if (cur->seqno == seqno && ast_test_flag(cur, FLAG_RESPONSE) == resp &&
- (ast_test_flag(cur, FLAG_RESPONSE) || method_match(sipmethod, cur->data))) {
- /* this is our baby */
- if (cur->retransid > -1) {
- if (option_debug > 3 && sipdebug)
- ast_log(LOG_DEBUG, "*** SIP TIMER: Cancelling retransmission #%d - %s (got response)\n", cur->retransid, sip_method2txt(sipmethod));
- ast_sched_del(sched, cur->retransid);
- }
- cur->retransid = -1;
- res = 0;
- break;
- }
- }
- if (option_debug)
- ast_log(LOG_DEBUG, "(Provisional) Stopping retransmission (but retaining packet) on '%s' %s %d: %s\n", p->callid, resp ? "Response" : "Request", seqno, res ? "Not Found" : "Found");
- return res;
-}
-
-
/*! \brief Copy SIP request, pre-parse it */
GNURK void parse_copy(struct sip_request *dst, const struct sip_request *src)
{
@@ -716,18 +701,18 @@
Called from PBX core sendtext() application */
static int sip_sendtext(struct ast_channel *ast, const char *text)
{
- struct sip_dialog *p = ast->tech_pvt;
- int debug = sip_debug_test_pvt(p);
+ struct sip_dialog *dialog = ast->tech_pvt;
+ int debug = sip_debug_test_pvt(dialog);
if (debug)
ast_verbose("Sending text %s on %s\n", text, ast->name);
- if (!p)
+ if (!dialog)
return -1;
if (ast_strlen_zero(text))
return 0;
if (debug)
ast_verbose("Really sending text %s on %s\n", text, ast->name);
- transmit_message_with_text(p, text);
+ transmit_message_with_text(dialog, text);
return 0;
}
@@ -760,15 +745,15 @@
if (fc)
ast_update_realtime("sippeers", "name", peername, "ipaddr", ipaddr,
"port", port, "regseconds", regseconds,
- "username", username, fc, fullcontact, syslabel, sysname, NULL); /* note fc and syslabel _can_ be NULL */
+ "defaultuser", username, fc, fullcontact, syslabel, sysname, NULL); /* note fc and syslabel _can_ be NULL */
else
ast_update_realtime("sippeers", "name", peername, "ipaddr", ipaddr,
"port", port, "regseconds", regseconds,
- "username", username, syslabel, sysname, NULL); /* note syslabel _can_ be NULL */
+ "defaultuser", username, syslabel, sysname, NULL); /* note syslabel _can_ be NULL */
}
/*! \brief Automatically add peer extension to dial plan */
-static void register_peer_exten(struct sip_peer *peer, int onoff)
+static void register_peer_exten(struct sip_peer *device, int onoff)
{
char multi[256];
char *stringp, *ext, *context;
@@ -780,7 +765,7 @@
if (ast_strlen_zero(global.regcontext))
return;
- ast_copy_string(multi, S_OR(peer->regexten, peer->name), sizeof(multi));
+ ast_copy_string(multi, S_OR(device->regexten, device->name), sizeof(multi));
stringp = multi;
while ((ext = strsep(&stringp, "&"))) {
if ((context = strchr(ext, '@'))) {
@@ -794,7 +779,7 @@
}
if (onoff)
ast_add_extension(context, 1, ext, 1, NULL, NULL, "Noop",
- ast_strdup(peer->name), ast_free, "SIP");
+ ast_strdup(device->name), ast_free, "SIP");
else
ast_context_remove_extension(context, ext, 1, NULL);
}
@@ -850,12 +835,12 @@
}
/*! \brief Update peer data in database (if used) */
-static void update_peer(struct sip_peer *peer, int expiry)
-{
- int rtcachefriends = ast_test_flag(&peer->flags[1], SIP_PAGE2_RTCACHEFRIENDS);
+static void update_peer(struct sip_peer *device, int expiry)
+{
+ int rtcachefriends = ast_test_flag(&device->flags[1], SIP_PAGE2_RTCACHEFRIENDS);
if (ast_test_flag(&global.flags[1], SIP_PAGE2_RTUPDATE) &&
- (ast_test_flag(&peer->flags[0], SIP_REALTIME) || rtcachefriends)) {
- realtime_update_peer(peer->name, &peer->addr, peer->username, rtcachefriends ? peer->fullcontact : NULL, expiry);
+ (ast_test_flag(&device->flags[0], SIP_REALTIME) || rtcachefriends)) {
+ realtime_update_peer(device->name, &device->addr, device->defaultuser, rtcachefriends ? device->fullcontact : NULL, expiry);
}
}
@@ -909,26 +894,26 @@
}
}
-/*! \brief Create address structure from peer reference.
+/*! \brief Create address structure from device reference.
* return -1 on error, 0 on success.
*/
-static int create_addr_from_peer(struct sip_dialog *dialog, struct sip_peer *peer)
-{
- if ((peer->addr.sin_addr.s_addr || peer->defaddr.sin_addr.s_addr) &&
- (!peer->maxms || ((peer->lastms >= 0) && (peer->lastms <= peer->maxms)))) {
- dialog->sa = (peer->addr.sin_addr.s_addr) ? peer->addr : peer->defaddr;
+static int create_addr_from_peer(struct sip_dialog *dialog, struct sip_peer *device)
+{
+ if ((device->addr.sin_addr.s_addr || device->defaddr.sin_addr.s_addr) &&
+ (!device->maxms || ((device->lastms >= 0) && (device->lastms <= device->maxms)))) {
+ dialog->sa = (device->addr.sin_addr.s_addr) ? device->addr : device->defaddr;
dialog->recv = dialog->sa;
} else
return -1;
- ast_copy_flags(&dialog->flags[0], &peer->flags[0], SIP_FLAGS_TO_COPY);
- ast_copy_flags(&dialog->flags[1], &peer->flags[1], SIP_PAGE2_FLAGS_TO_COPY);
- dialog->capability = peer->capability;
+ ast_copy_flags(&dialog->flags[0], &device->flags[0], SIP_FLAGS_TO_COPY);
+ ast_copy_flags(&dialog->flags[1], &device->flags[1], SIP_PAGE2_FLAGS_TO_COPY);
+ dialog->capability = device->capability;
if (!ast_test_flag(&dialog->flags[1], SIP_PAGE2_VIDEOSUPPORT) && dialog->vrtp) {
ast_rtp_destroy(dialog->vrtp);
dialog->vrtp = NULL;
}
- dialog->prefs = peer->prefs;
+ dialog->prefs = device->prefs;
if (ast_test_flag(&dialog->flags[1], SIP_PAGE2_T38SUPPORT)) {
dialog->t38.capability = global.t38_capability;
if (dialog->udptl) {
@@ -961,51 +946,60 @@
/* Set Frame packetization */
if (dialog->rtp) {
ast_rtp_codec_setpref(dialog->rtp, &dialog->prefs);
- dialog->autoframing = peer->autoframing;
- }
- ast_string_field_set(dialog, peername, peer->username);
- ast_string_field_set(dialog, authname, peer->username);
- ast_string_field_set(dialog, username, peer->username);
- ast_string_field_set(dialog, peersecret, peer->secret);
- ast_string_field_set(dialog, peermd5secret, peer->md5secret);
- ast_string_field_set(dialog, tohost, peer->tohost);
- ast_string_field_set(dialog, fullcontact, peer->fullcontact);
- if (!dialog->initreq.headers && !ast_strlen_zero(peer->fromdomain)) {
+ dialog->autoframing = device->autoframing;
+ }
+
+ /* XXX Why use username for all of this? */
+ //ast_string_field_set(dialog, peername, device->defaultuser);
+
+ ast_string_field_set(dialog, peername, device->name);
+ /* Authuser is fromuser, and if that not is set, it's the defaultuser, if that's set */
+
+ if (ast_strlen_zero(device->fromuser))
+ ast_string_field_set(dialog, authname, device->defaultuser);
+ else
+ ast_string_field_set(dialog, authname, device->fromuser);
+ ast_string_field_set(dialog, defaultuser, device->defaultuser);
+ ast_string_field_set(dialog, peersecret, device->secret);
+ ast_string_field_set(dialog, peermd5secret, device->md5secret);
+ ast_string_field_set(dialog, tohost, device->tohost);
+ ast_string_field_set(dialog, fullcontact, device->fullcontact);
+ if (!dialog->initreq.headers && !ast_strlen_zero(device->fromdomain)) {
char *tmpcall;
char *c;
tmpcall = ast_strdupa(dialog->callid);
c = strchr(tmpcall, '@');
if (c) {
*c = '\0';
- ast_string_field_build(dialog, callid, "%s@%s", tmpcall, peer->fromdomain);
+ ast_string_field_build(dialog, callid, "%s@%s", tmpcall, device->fromdomain);
}
}
if (ast_strlen_zero(dialog->tohost))
ast_string_field_set(dialog, tohost, ast_inet_ntoa(dialog->sa.sin_addr));
- if (!ast_strlen_zero(peer->fromdomain))
- ast_string_field_set(dialog, fromdomain, peer->fromdomain);
- if (!ast_strlen_zero(peer->fromuser))
- ast_string_field_set(dialog, fromuser, peer->fromuser);
- dialog->maxtime = peer->maxms;
- dialog->callgroup = peer->callgroup;
- dialog->pickupgroup = peer->pickupgroup;
- dialog->allowtransfer = peer->allowtransfer;
+ if (!ast_strlen_zero(device->fromdomain))
+ ast_string_field_set(dialog, fromdomain, device->fromdomain);
+ if (!ast_strlen_zero(device->fromuser))
+ ast_string_field_set(dialog, fromuser, device->fromuser);
+ dialog->maxtime = device->maxms;
+ dialog->callgroup = device->callgroup;
+ dialog->pickupgroup = device->pickupgroup;
+ dialog->allowtransfer = device->allowtransfer;
/* Set timer T1 to RTT for this peer (if known by qualify=) */
/* Minimum is settable or default to 100 ms */
- if (peer->maxms && peer->lastms)
- dialog->timer_t1 = peer->lastms < global.t1min ? global.t1min : peer->lastms;
+ if (device->maxms && device->lastms)
+ dialog->timer_t1 = device->lastms < global.t1min ? global.t1min : device->lastms;
if ((ast_test_flag(&dialog->flags[0], SIP_DTMF) == SIP_DTMF_RFC2833) ||
(ast_test_flag(&dialog->flags[0], SIP_DTMF) == SIP_DTMF_AUTO))
dialog->noncodeccapability |= AST_RTP_DTMF;
else
dialog->noncodeccapability &= ~AST_RTP_DTMF;
- ast_string_field_set(dialog, context, peer->context);
- dialog->rtptimeout = peer->rtptimeout;
- dialog->rtpholdtimeout = peer->rtpholdtimeout;
- dialog->rtpkeepalive = peer->rtpkeepalive;
- if (peer->call_limit)
+ ast_string_field_set(dialog, context, device->context);
+ dialog->rtptimeout = device->rtptimeout;
+ dialog->rtpholdtimeout = device->rtpholdtimeout;
+ dialog->rtpkeepalive = device->rtpkeepalive;
+ if (device->call_limit)
ast_set_flag(&dialog->flags[0], SIP_CALL_LIMIT);
- dialog->maxcallbitrate = peer->maxcallbitrate;
+ dialog->maxcallbitrate = device->maxcallbitrate;
return 0;
}
@@ -1021,29 +1015,29 @@
char *port;
int portno;
char host[MAXHOSTNAMELEN], *hostn;
- char peer[256];
-
- ast_copy_string(peer, opeer, sizeof(peer));
- port = strchr(peer, ':');
+ char peername[256];
+
+ ast_copy_string(peername, opeer, sizeof(peername));
+ port = strchr(peername, ':');
if (port)
*port++ = '\0';
dialog->sa.sin_family = AF_INET;
- dialog->timer_t1 = 500; /* Default SIP retransmission timer T1 (RFC 3261) */
- p = find_device(peer, NULL, 1);
+ dialog->timer_t1 = SIP_TIMER_T1_DEFAULT; /* Default SIP retransmission timer T1 (RFC 3261) */
+ p = find_device(peername, NULL, 1);
if (p) {
int res = create_addr_from_peer(dialog, p);
ASTOBJ_UNREF(p, sip_destroy_device);
return res;
}
- hostn = peer;
+ hostn = peername;
portno = port ? atoi(port) : STANDARD_SIP_PORT;
if (global.srvlookup) {
char service[MAXHOSTNAMELEN];
int tportno;
int ret;
- snprintf(service, sizeof(service), "_sip._udp.%s", peer);
+ snprintf(service, sizeof(service), "_sip._udp.%s", peername);
ret = ast_get_srv(NULL, host, sizeof(host), &tportno, service);
if (ret > 0) {
hostn = host;
@@ -1051,13 +1045,13 @@
}
hp = ast_gethostbyname(hostn, &ahp);
if (hp) {
- ast_string_field_set(dialog, tohost, peer);
+ ast_string_field_set(dialog, tohost, peername);
memcpy(&dialog->sa.sin_addr, hp->h_addr, sizeof(dialog->sa.sin_addr));
dialog->sa.sin_port = htons(portno);
dialog->recv = dialog->sa;
return 0;
} else {
- ast_log(LOG_WARNING, "No such host: %s\n", peer);
+ ast_log(LOG_WARNING, "No such host: %s\n", peername);
return -1;
}
} else {
@@ -1066,10 +1060,10 @@
}
hp = ast_gethostbyname(hostn, &ahp);
if (!hp) {
- ast_log(LOG_WARNING, "No such host: %s\n", peer);
+ ast_log(LOG_WARNING, "No such host: %s\n", peername);
return -1;
}
- ast_string_field_set(dialog, tohost, peer);
+ ast_string_field_set(dialog, tohost, peername);
memcpy(&dialog->sa.sin_addr, hp->h_addr, sizeof(dialog->sa.sin_addr));
dialog->sa.sin_port = htons(portno);
dialog->recv = dialog->sa;
@@ -1149,14 +1143,14 @@
if (referer) {
if (sipdebug && option_debug > 2)
- ast_log(LOG_DEBUG, "Call for %s transfered by %s\n", p->username, referer);
+ ast_log(LOG_DEBUG, "Call for %s transfered by %s\n", p->peername, referer);
snprintf(buf, sizeof(buf)-1, "-> %s (via %s)", p->cid_name, referer);
} else
snprintf(buf, sizeof(buf)-1, "-> %s", p->cid_name);
ast_string_field_set(p, cid_name, buf);
}
if (option_debug)
- ast_log(LOG_DEBUG, "Outgoing Call for %s\n", p->username);
+ ast_log(LOG_DEBUG, "Outgoing Call for %s\n", p->peername);
res = update_call_counter(p, INC_CALL_RINGING);
if ( res != -1 ) {
@@ -1173,98 +1167,6 @@
p->initid = ast_sched_add(sched, SIP_TRANS_TIMEOUT, auto_congest, p);
}
return res;
-}
-
-/*! \brief Execute destruction of SIP dialog structure, release memory */
-static void __sip_destroy(struct sip_dialog *p, int lockowner)
-{
- struct sip_dialog *cur, *prev = NULL;
- struct sip_pkt *cp;
-
- if (sip_debug_test_pvt(p) || option_debug > 2)
- ast_verbose("Really destroying SIP dialog '%s' Method: %s\n", p->callid, sip_method2txt(p->method));
-
- /* Remove link from peer to subscription of MWI */
- if (p->relatedpeer && p->relatedpeer->mwipvt)
- p->relatedpeer->mwipvt = NULL;
-
- if (global.dumphistory)
- sip_dump_history(p);
-
- if (p->options)
- free(p->options);
-
- if (p->stateid > -1)
- ast_extension_state_del(p->stateid, NULL);
- if (p->initid > -1)
- ast_sched_del(sched, p->initid);
- if (p->autokillid > -1)
- ast_sched_del(sched, p->autokillid);
-
- if (p->rtp)
- ast_rtp_destroy(p->rtp);
- if (p->vrtp)
- ast_rtp_destroy(p->vrtp);
- if (p->udptl)
- ast_udptl_destroy(p->udptl);
- if (p->refer)
- free(p->refer);
- if (p->route) {
- free_old_route(p->route);
- p->route = NULL;
- }
- if (p->registry) {
- if (p->registry->call == p)
- p->registry->call = NULL;
- ASTOBJ_UNREF(p->registry, sip_registry_destroy);
- }
-
- /* Unlink us from the owner if we have one */
- if (p->owner) {
- if (lockowner)
- ast_channel_lock(p->owner);
- if (option_debug)
- ast_log(LOG_DEBUG, "Detaching from %s\n", p->owner->name);
- p->owner->tech_pvt = NULL;
- if (lockowner)
- ast_channel_unlock(p->owner);
- }
- /* Clear history */
- if (p->history) {
- struct sip_history *hist;
- while( (hist = AST_LIST_REMOVE_HEAD(p->history, list)) )
- free(hist);
- free(p->history);
- p->history = NULL;
- }
-
- for (prev = NULL, cur = dialoglist; cur; prev = cur, cur = cur->next) {
- if (cur == p) {
- UNLINK(cur, dialoglist, prev);
- break;
- }
- }
- if (!cur) {
- ast_log(LOG_WARNING, "Trying to destroy \"%s\", not found in dialog list?!?! \n", p->callid);
- return;
- }
-
- /* remove all current packets in this dialog */
- while((cp = p->packets)) {
- p->packets = p->packets->next;
- if (cp->retransid > -1)
- ast_sched_del(sched, cp->retransid);
- free(cp);
- }
- if (p->chanvars) {
- ast_variables_destroy(p->chanvars);
- p->chanvars = NULL;
- }
- ast_mutex_destroy(&p->lock);
-
- ast_string_field_free_pools(p);
-
- free(p);
}
/*! \brief update_call_counter: Handle call_limit for SIP users
@@ -1294,7 +1196,7 @@
if (!ast_test_flag(&fup->flags[0], SIP_CALL_LIMIT))
return 0;
- ast_copy_string(name, fup->username, sizeof(name));
+ ast_copy_string(name, fup->peername, sizeof(name));
/* Check the list of devices */
device = find_device(fup->peername, NULL, 1);
@@ -1303,7 +1205,6 @@
ast_log(LOG_DEBUG, "%s is not a local device, no call limit\n", name);
return 0;
}
- ast_copy_string(name, fup->peername, sizeof(name));
switch(event) {
/* incoming and outgoing affects the inUse counter */
@@ -1364,16 +1265,6 @@
return 0;
}
-/*! \brief Destroy SIP call structure */
-GNURK void sip_destroy(struct sip_dialog *p)
-{
- dialoglist_lock();
- if (option_debug > 2)
- ast_log(LOG_DEBUG, "Destroying SIP dialog %s\n", p->callid);
- __sip_destroy(p, 1);
- dialoglist_unlock();
-}
-
/*! \brief sip_hangup: Hangup SIP call
* Part of PBX interface, called from ast_hangup */
static int sip_hangup(struct ast_channel *ast)
@@ -1414,7 +1305,7 @@
ast_mutex_lock(&p->lock);
if (option_debug && sipdebug)
- ast_log(LOG_DEBUG, "update_call_counter(%s) - decrement call limit counter on hangup\n", p->username);
+ ast_log(LOG_DEBUG, "update_call_counter(%s) - decrement call limit counter on hangup\n", p->peername);
update_call_counter(p, DEC_CALL_LIMIT);
/* Determine how to disconnect */
@@ -2002,6 +1893,7 @@
{
char *c = req->data, **dst = req->header;
int i = 0, lim = SIP_MAX_HEADERS - 1;
+ int seqno = 0;
req->header[0] = c;
req->headers = -1; /* mark that we are working on the header */
@@ -2039,6 +1931,12 @@
ast_log(LOG_WARNING, "Too many lines, skipping <%s>\n", c);
/* Split up the first line parts */
determine_firstline_parts(req);
+ /* Determine the seqno of this request once and for all */
+
+ /* Seqno can be zero, but anyway... */
+ req->cseqheader = get_header(req, "CSeq");
+ if (!req->seqno && sscanf(req->cseqheader, "%d ", &seqno) != 1)
+ req->seqno = seqno;
}
/*! \brief Add header to SIP message */
@@ -2113,6 +2011,7 @@
ast_log(LOG_WARNING, "Unable to determine sequence number from '%s'\n", get_header(req, "CSeq"));
return -1;
}
+ resp.seqno = seqno;
respprep(&resp, p, msg, req);
add_header_contentLength(&resp, 0);
/* If we are cancelling an incoming invite for some reason, add information
@@ -2577,10 +2476,10 @@
/* If we have full contact, trust it */
ast_build_string(&invite, &invite_max, "%s", p->fullcontact);
} else {
- /* Otherwise, use the username while waiting for registration */
+ /* Otherwise, use the defaultuser while waiting for registration */
ast_build_string(&invite, &invite_max, "sip:");
- if (!ast_strlen_zero(p->username)) {
- n = p->username;
+ if (!ast_strlen_zero(p->defaultuser)) {
+ n = p->defaultuser;
ast_uri_encode(n, tmp, sizeof(tmp), 0);
n = tmp;
ast_build_string(&invite, &invite_max, "%s@", n);
@@ -3111,7 +3010,7 @@
{
if (!ast_test_flag(&global.flags[1], SIP_PAGE2_IGNOREREGEXPIRE)) {
if (ast_test_flag(&peer->flags[1], SIP_PAGE2_RT_FROMCONTACT))
- ast_update_realtime("sippeers", "name", peer->name, "fullcontact", "", "ipaddr", "", "port", "", "regseconds", "0", "username", "", "regserver", "", NULL);
+ ast_update_realtime("sippeers", "name", peer->name, "fullcontact", "", "ipaddr", "", "port", "", "regseconds", "0", "defaultuser", "", "regserver", "", NULL);
else
ast_db_del("SIP/Registry", peer->name);
}
@@ -3191,13 +3090,13 @@
return;
if (username)
- ast_copy_string(peer->username, username, sizeof(peer->username));
+ ast_copy_string(peer->defaultuser, username, sizeof(peer->defaultuser));
if (contact)
ast_copy_string(peer->fullcontact, contact, sizeof(peer->fullcontact));
if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_3 "SIP Seeding peer from astdb: '%s' at %s@%s:%d for %d\n",
- peer->name, peer->username, ast_inet_ntoa(in), port, expiry);
+ peer->name, peer->defaultuser, ast_inet_ntoa(in), port, expiry);
memset(&peer->addr, 0, sizeof(peer->addr));
peer->addr.sin_family = AF_INET;
@@ -3410,10 +3309,10 @@
/* Save SIP options profile */
peer->sipoptions = pvt->sipoptions;
- if (curi) /* Overwrite the default username from config at registration */
- ast_copy_string(peer->username, curi, sizeof(peer->username));
- else
- peer->username[0] = '\0';
+ if (curi) { /* Overwrite the default username from config at registration */
+ ast_copy_string(peer->defaultuser, curi, sizeof(peer->defaultuser));
+ } else
+ peer->defaultuser[0] = '\0';
if (peer->expire > -1)
ast_sched_del(sched, peer->expire);
@@ -3424,7 +3323,7 @@
peer->expire = ast_test_flag(&peer->flags[0], SIP_REALTIME) ? -1 :
ast_sched_add(sched, (localexpiry + 10) * 1000, expire_register, peer);
pvt->expiry = localexpiry;
- snprintf(data, sizeof(data), "%s:%d:%d:%s:%s", ast_inet_ntoa(peer->addr.sin_addr), ntohs(peer->addr.sin_port), localexpiry, peer->username, peer->fullcontact);
+ snprintf(data, sizeof(data), "%s:%d:%d:%s:%s", ast_inet_ntoa(peer->addr.sin_addr), ntohs(peer->addr.sin_port), localexpiry, peer->defaultuser, peer->fullcontact);
if (!ast_test_flag(&peer->flags[1], SIP_PAGE2_RT_FROMCONTACT))
ast_db_put("SIP/Registry", peer->name, data);
manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "Peer: SIP/%s\r\nPeerStatus: Registered\r\n", peer->name);
@@ -3448,7 +3347,7 @@
}
/*! \brief Remove route from route list */
-static void free_old_route(struct sip_route *route)
+void free_old_route(struct sip_route *route)
{
struct sip_route *next;
@@ -3608,7 +3507,7 @@
if (p->autokillid > -1)
sip_cancel_destroy(p); /* Remove subscription expiry for renewals */
sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); /* Delete subscription in 32 secs */
- ast_verbose(VERBOSE_PREFIX_2 "Extension state: Watcher for hint %s %s. Notify User %s\n", exten, state == AST_EXTENSION_DEACTIVATED ? "deactivated" : "removed", p->username);
+ ast_verbose(VERBOSE_PREFIX_2 "Extension state: Watcher for hint %s %s. Notify User %s\n", exten, state == AST_EXTENSION_DEACTIVATED ? "deactivated" : "removed", p->peername);
p->stateid = -1;
p->subscribed = NONE;
append_history(p, "Subscribestatus", "%s", state == AST_EXTENSION_REMOVED ? "HintRemoved" : "Deactivated");
@@ -3620,7 +3519,7 @@
transmit_state_notify(p, state, 1, FALSE);
if (option_verbose > 1)
- ast_verbose(VERBOSE_PREFIX_1 "Extension Changed %s new state %s for Notify User %s\n", exten, ast_extension_state2str(state), p->username);
+ ast_verbose(VERBOSE_PREFIX_1 "Extension Changed %s new state %s for Notify User %s\n", exten, ast_extension_state2str(state), p->peername);
return 0;
}
@@ -4263,9 +4162,9 @@
}
/* save the URI part of the From header */
ast_string_field_set(p, from, of);
- if (strncmp(of, "sip:", 4)) {
+ if (strncmp(of, "sip:", 4))
ast_log(LOG_NOTICE, "From address missing 'sip:', using it anyway\n");
- } else
+ else
of += 4;
/* Get just the username part */
if ((c = strchr(of, '@'))) {
@@ -4374,27 +4273,24 @@
}
if (!ast_strlen_zero(device->cid_name) && !ast_strlen_zero(p->cid_num))
ast_string_field_set(p, cid_name, device->cid_name);
- if (devicematch == SIP_USER) {
- ast_string_field_set(p, username, device->name);
- } else { /* SIP_PEER */
- ast_string_field_set(p, peersecret, device->secret);
- ast_string_field_set(p, peermd5secret, device->md5secret);
- ast_string_field_set(p, fullcontact, device->fullcontact);
- ast_string_field_set(p, peername, device->name);
- ast_string_field_set(p, authname, device->name);
- if (!ast_strlen_zero(device->username)) {
- ast_string_field_set(p, username, device->username);
- /* Use the default username for authentication on outbound calls */
- ast_string_field_set(p, authname, device->username);
- }
- if (p->t38.peercapability)
- p->t38.jointcapability &= p->t38.peercapability;
- p->maxcallbitrate = device->maxcallbitrate;
- /* If we do not support video, remove video from call structure */
- if (!ast_test_flag(&p->flags[1], SIP_PAGE2_VIDEOSUPPORT) && p->vrtp) {
- ast_rtp_destroy(p->vrtp);
- p->vrtp = NULL;
- }
+ ast_string_field_set(p, peersecret, device->secret);
+ ast_string_field_set(p, peermd5secret, device->md5secret);
+ ast_string_field_set(p, fullcontact, device->fullcontact);
+ ast_string_field_set(p, peername, device->name);
+ ast_string_field_set(p, authname, device->name);
+ if (!ast_strlen_zero(device->defaultuser)) {
+ ast_string_field_set(p, peername, device->defaultuser);
+ /* Use the default username for authentication on outbound calls */
+ if(!ast_strlen_zero(device->authuser))
+ ast_string_field_set(p, authname, device->authuser);
+ }
+ if (p->t38.peercapability)
+ p->t38.jointcapability &= p->t38.peercapability;
+ p->maxcallbitrate = device->maxcallbitrate;
+ /* If we do not support video, remove video from call structure */
+ if (!ast_test_flag(&p->flags[1], SIP_PAGE2_VIDEOSUPPORT) && p->vrtp) {
+ ast_rtp_destroy(p->vrtp);
+ p->vrtp = NULL;
}
ast_string_field_set(p, subscribecontext, device->subscribecontext);
ast_string_field_set(p, accountcode, device->accountcode);
@@ -4619,7 +4515,7 @@
/*! \brief Dump SIP history to debug log file at end of lifespan for SIP dialog */
-static void sip_dump_history(struct sip_dialog *dialog)
+GNURK void sip_dump_history(struct sip_dialog *dialog)
{
int x = 0;
struct sip_history *hist;
@@ -5082,7 +4978,7 @@
}
/*! \brief Handle SIP response to INVITE dialogue */
-static void handle_response_invite(struct sip_dialog *p, int resp, char *rest, struct sip_request *req, int seqno)
+static void handle_response_invite(struct sip_dialog *p, int resp, char *rest, struct sip_request *req)
{
int outgoing = ast_test_flag(&p->flags[0], SIP_OUTGOING);
int res = 0;
@@ -5251,14 +5147,14 @@
ast_set_flag(&p->flags[0], SIP_PENDINGBYE);
}
/* If I understand this right, the branch is different for a non-200 ACK only */
- transmit_request(p, SIP_ACK, seqno, XMIT_UNRELIABLE, TRUE);
+ transmit_request(p, SIP_ACK, req->seqno, XMIT_UNRELIABLE, TRUE);
ast_set_flag(&p->flags[0], SIP_CAN_BYE);
check_pendings(p);
break;
case 407: /* Proxy authentication */
case 401: /* Www auth */
/* First we ACK */
- transmit_request(p, SIP_ACK, seqno, XMIT_UNRELIABLE, FALSE);
+ transmit_request(p, SIP_ACK, req->seqno, XMIT_UNRELIABLE, FALSE);
if (p->options)
p->options->auth_type = resp;
@@ -5276,7 +5172,7 @@
break;
case 403: /* Forbidden */
/* First we ACK */
- transmit_request(p, SIP_ACK, seqno, XMIT_UNRELIABLE, FALSE);
+ transmit_request(p, SIP_ACK, req->seqno, XMIT_UNRELIABLE, FALSE);
ast_log(LOG_WARNING, "Received response: \"Forbidden\" from '%s'\n", get_header(&p->initreq, "From"));
[... 1983 lines stripped ...]
More information about the asterisk-commits
mailing list