[svn-commits] oej: branch oej/codename-pineapple r46900 - in /team/oej/codename-pineapple: ...

svn-commits at lists.digium.com svn-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 svn-commits mailing list