[asterisk-commits] oej: branch oej/peerfailover-trunk r216919 - in /team/oej/peerfailover-trunk:...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Mon Sep 7 13:41:29 CDT 2009


Author: oej
Date: Mon Sep  7 13:41:27 2009
New Revision: 216919

URL: http://svn.asterisk.org/svn-view/asterisk?view=rev&rev=216919
Log:
Uncommitted code found in a unknown corner of the universe.

Modified:
    team/oej/peerfailover-trunk/   (props changed)
    team/oej/peerfailover-trunk/channels/chan_sip.c

Propchange: team/oej/peerfailover-trunk/
------------------------------------------------------------------------------
--- automerge (original)
+++ automerge Mon Sep  7 13:41:27 2009
@@ -1,1 +1,1 @@
-Support chan_sip3 http://www.codename-pineapple.org
+http://www.codename-pineapple.org/

Modified: team/oej/peerfailover-trunk/channels/chan_sip.c
URL: http://svn.asterisk.org/svn-view/asterisk/team/oej/peerfailover-trunk/channels/chan_sip.c?view=diff&rev=216919&r1=216918&r2=216919
==============================================================================
--- team/oej/peerfailover-trunk/channels/chan_sip.c (original)
+++ team/oej/peerfailover-trunk/channels/chan_sip.c Mon Sep  7 13:41:27 2009
@@ -1,3 +1,8 @@
+/* PEER failover branch
+ *  - each peer is given a secondary hostname, configured as "failoverhost"
+ *  - when a transmission to a given host fails, we switch automatically over to failoverhost 
+ *	
+ */
 /*
  * Asterisk -- An open source telephony toolkit.
  *
@@ -850,6 +855,30 @@
 	char hop[0];
 };
 
+/*! \brief */
+enum failover_state {
+	NOT_CONFIGURED = 0,	/*!< This is not a failover server */
+	STANDBY,		/*!< This is a failover server in standby mode */
+	ACTIVE,			/*!< The primary server fails, so this server is active */
+};
+
+/*! \brief definition of a sip proxy server
+ *
+ * For outbound proxies, this is allocated in the SIP peer dynamically or
+ * statically as the global_outboundproxy. The pointer in a SIP message is just
+ * a pointer and should *not* be de-allocated.
+ */
+struct sip_proxy {
+	char name[MAXHOSTNAMELEN];      /*!< DNS name of domain/host or IP */
+	struct sockaddr_in ip;          /*!< Currently used IP address and port */
+	time_t last_dnsupdate;          /*!< When this was resolved */
+	int force;                      /*!< If it's an outbound proxy, Force use of this outbound proxy for all outbound requests */
+	enum failover_state failoverstate;	/*!< If this is a failover proxy, what's the state ? */
+
+	/* Room for a SRV record chain based on the name */
+};
+
+
 /*! \brief Modes for SIP domain handling in the PBX */
 enum domain_mode {
 	SIP_DOMAIN_AUTO,		/*!< This domain is auto-configured */
@@ -1180,6 +1209,7 @@
 		AST_STRING_FIELD(fromname);	/*!< Name to show in the user field */
 		AST_STRING_FIELD(tohost);	/*!< Host we should put in the "to" field */
 		AST_STRING_FIELD(todnid);	/*!< DNID of this call (overrides host) */
+		AST_STRING_FIELD(failoverhostname);	/*!< Host name of failover host if SIP signalling dies */
 		AST_STRING_FIELD(language);	/*!< Default language for this call */
 		AST_STRING_FIELD(mohinterpret);	/*!< MOH class to use when put on hold */
 		AST_STRING_FIELD(mohsuggest);	/*!< MOH class to suggest when putting a peer on hold */
@@ -1248,6 +1278,8 @@
 	int sessionversion_remote;		/*!< Remote UA's SDP Session Version */
 	int session_modify;			/*!< Session modification request true/false  */
 	struct sockaddr_in sa;			/*!< Our peer */
+	struct sockaddr_in failoveraddr;	/*!< Our failover IP address */
+	enum failover_state failoverstate;	/*!< Failover state for this peer */
 	struct sockaddr_in redirip;		/*!< Where our RTP should be going if not to us */
 	struct sockaddr_in vredirip;		/*!< Where our Video RTP should be going if not to us */
 	struct sockaddr_in tredirip;		/*!< Where our Text RTP should be going if not to us */
@@ -1436,6 +1468,7 @@
 	char accountcode[AST_MAX_ACCOUNT_CODE];	/*!< Account code */
 	int amaflags;			/*!< AMA Flags (for billing) */
 	char tohost[MAXHOSTNAMELEN];	/*!< If not dynamic, IP address */
+	char failoverhostname[MAXHOSTNAMELEN]; /*!< failover host name */
 	char regexten[AST_MAX_EXTENSION]; /*!< Extension to register (if regcontext is used) */
 	char fromuser[80];		/*!< From: user when calling this peer */
 	char fromdomain[MAXHOSTNAMELEN];	/*!< From: domain when calling this peer */
@@ -1478,6 +1511,7 @@
 	struct sip_proxy *outboundproxy;	/*!< Outbound proxy for this peer */
 	struct ast_dnsmgr_entry *dnsmgr;/*!<  DNS refresh manager for peer */
 	struct sockaddr_in addr;	/*!<  IP address of peer */
+	struct sockaddr_in failoveraddr;	/*!<  IP address of failover peer */
 	int maxcallbitrate;		/*!< Maximum Bitrate for a video call */
 	
 	/* Qualification */
@@ -1954,7 +1988,7 @@
 static const struct sockaddr_in *sip_real_dst(const struct sip_pvt *p);
 static void build_via(struct sip_pvt *p);
 static int create_addr_from_peer(struct sip_pvt *r, struct sip_peer *peer);
-static int create_addr(struct sip_pvt *dialog, const char *opeer);
+static int create_addr(struct sip_pvt *dialog, const char *opeer, int failover);
 static char *generate_random_string(char *buf, size_t size);
 static void build_callid_pvt(struct sip_pvt *pvt);
 static void build_callid_registry(struct sip_registry *reg, struct in_addr ourip, const char *fromdomain);
@@ -2531,6 +2565,16 @@
 			case ENETUNREACH:	/* Network failure */
 				res = XMIT_ERROR;	/* Don't bother with trying to transmit again */
 		}
+		if (p->failoverstate == STANDBY) {	/* Time to switch to failover mode for this dialog */
+			p->failoverstate = ACTIVE;
+			if (!p->failoveraddr.sin_addr.s_addr)
+				create_addr(p, p->failoverhostname, TRUE);	/* Resolve to IP address */
+			if (option_debug > 2)
+				ast_log(LOG_DEBUG, "FAILOVER:: Switching to failover peer for this dialog :: %s\n", p->callid);
+			append_history(p, "FailOver", "Activated failover peer for non-responsive peer %s", p->tohost);
+			return __sip_xmit(p, data, len);
+		}
+		
 	}
 	if (res != len)
 		ast_log(LOG_WARNING, "sip_xmit of %p (len %d) to %s:%d returned %d: %s\n", data, len, ast_inet_ntoa(dst->sin_addr), ntohs(dst->sin_port), res, strerror(errno));
@@ -2690,10 +2734,12 @@
 
 		if (sip_debug_test_pvt(pkt->owner)) {
 			const struct sockaddr_in *dst = sip_real_dst(pkt->owner);
-			ast_verbose("Retransmitting #%d (%s) to %s:%d:\n%s\n---\n",
+			ast_verbose("Retransmitting #%d (%s) to %s%s:%d:\n%s\n---\n",
 				pkt->retrans, sip_nat_mode(pkt->owner),
-				ast_inet_ntoa(dst->sin_addr),
-				ntohs(dst->sin_port), pkt->data);
+				pkt->owner->failoverstate == ACTIVE ? "failover peer " : "",
+				pkt->owner->failoverstate == ACTIVE ? ast_inet_ntoa(pkt->owner->failoveraddr.sin_addr) : ast_inet_ntoa(dst->sin_addr),
+				pkt->owner->failoverstate == ACTIVE ? ntohs(pkt->owner->failoveraddr.sin_port) : ntohs(dst->sin_port),
+				pkt->data);
 		}
 
 		append_history(pkt->owner, "ReTx", "%d %s", reschedule, pkt->data);
@@ -2720,6 +2766,18 @@
 	} else 
 		append_history(pkt->owner, "MaxRetries", "%s", pkt->is_fatal ? "(Critical)" : "(Non-critical)");
  		
+
+	if (pkt->method != SIP_OPTIONS && pkt->owner->failoverstate == STANDBY) {
+		pkt->owner->failoverstate = ACTIVE;	/* Switching dialog to failover active mode */
+		append_history(pkt->owner, "FailOver", "Failover SIP host activated.");
+		pkt->retrans = 0;
+ 		pkt->timer_a = 2 ;
+		ast_mutex_unlock(&pkt->owner->lock);
+		if (option_debug > 2)
+			ast_log(LOG_DEBUG, "FAILOVER :: Switching to failover peer due to retransmits\n");
+		return 100;	/* Restart with failover peer after 100 ms */
+	}
+
 	pkt->retransid = -1;
 
 	if (pkt->is_fatal) {
@@ -2728,6 +2786,7 @@
 			usleep(1);
 			sip_pvt_lock(pkt->owner);
 		}
+
 
 		if (pkt->owner->owner && !pkt->owner->owner->hangupcause) 
 			pkt->owner->owner->hangupcause = AST_CAUSE_NO_USER_RESPONSE;
@@ -3033,10 +3092,13 @@
 	if (sip_debug_test_pvt(p)) {
 		const struct sockaddr_in *dst = sip_real_dst(p);
 
-		ast_verbose("\n<--- %sTransmitting (%s) to %s:%d --->\n%s\n<------------>\n",
+		ast_verbose("\n<--- %sTransmitting (%s) to %s%s:%d --->\n%s\n<------------>\n",
 			reliable ? "Reliably " : "", sip_nat_mode(p),
-			ast_inet_ntoa(dst->sin_addr),
-			ntohs(dst->sin_port), req->data);
+			p->failoverstate == ACTIVE ? "failover peer " : "",
+			p->failoverstate == ACTIVE ? ast_inet_ntoa(p->failoveraddr.sin_addr) : ast_inet_ntoa(dst->sin_addr),
+			p->failoverstate == ACTIVE ? ntohs(p->failoveraddr.sin_port) : ntohs(dst->sin_port),
+			req->data);
+
 	}
 	if (p->do_history) {
 		struct sip_request tmp;
@@ -3066,10 +3128,16 @@
 
 	add_blank(req);
 	if (sip_debug_test_pvt(p)) {
+		struct sockaddr_in *toaddr = ast_test_flag(&p->flags[0], SIP_NAT_ROUTE) ? &p->recv : &p->sa;
+		char *natstate = "";
+		if (p->failoverstate == ACTIVE)
+			toaddr = &p->failoveraddr;
+
 		if (ast_test_flag(&p->flags[0], SIP_NAT_ROUTE))
-			ast_verbose("%sTransmitting (NAT) to %s:%d:\n%s\n---\n", reliable ? "Reliably " : "", ast_inet_ntoa(p->recv.sin_addr), ntohs(p->recv.sin_port), req->data);
-		else
-			ast_verbose("%sTransmitting (no NAT) to %s:%d:\n%s\n---\n", reliable ? "Reliably " : "", ast_inet_ntoa(p->sa.sin_addr), ntohs(p->sa.sin_port), req->data);
+			natstate = "(NAT)";
+		ast_verbose("\n---> %sTransmitting %s to %s%s:%d:\n%s\n---\n", reliable ? "Reliably " : "", natstate, 
+			p->failoverstate == ACTIVE ? "failover peer " : "",
+			ast_inet_ntoa(toaddr->sin_addr), ntohs(toaddr->sin_port), req->data);
 	}
 	if (p->do_history) {
 		struct sip_request tmp;
@@ -3803,8 +3871,18 @@
 	    (!peer->maxms || ((peer->lastms >= 0)  && (peer->lastms <= peer->maxms)))) {
 		dialog->sa = (peer->addr.sin_addr.s_addr) ? peer->addr : peer->defaddr;
 		dialog->recv = dialog->sa;
-	} else 
+	} else if (peer->failoveraddr.sin_addr.s_addr || !ast_strlen_zero(peer->failoverhostname)) {
+		/* There's a problem with the primary peer (unreachable) and we do have a failver
+		   peer definition. Activate that at the start of the dialog */
+		if (!peer->failoveraddr.sin_addr.s_addr) {
+			create_addr(dialog, peer->failoverhostname, TRUE);
+		}
+		dialog->failoverstate = ACTIVE;
+	} else {
 		return -1;
+	}
+
+	dialog->failoveraddr = peer->failoveraddr;
 
 	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);
@@ -3861,6 +3939,7 @@
 	ast_string_field_set(dialog, mohsuggest, peer->mohsuggest);
 	ast_string_field_set(dialog, mohinterpret, peer->mohinterpret);
 	ast_string_field_set(dialog, tohost, peer->tohost);
+	ast_string_field_set(dialog, failoverhostname, peer->failoverhostname);
 	ast_string_field_set(dialog, fullcontact, peer->fullcontact);
 	ast_string_field_set(dialog, context, peer->context);
 	dialog->outboundproxy = obproxy_get(dialog, peer);
@@ -8985,7 +9064,7 @@
 		p->outboundproxy = obproxy_get(p, NULL);
 
 		/* Find address to hostname */
-		if (create_addr(p, r->hostname)) {
+		if (create_addr(p, r->hostname, FALSE)) {
 			/* we have what we hope is a temporary network error,
 			 * probably DNS.  We need to reschedule a registration try */
 			sip_destroy(p);
@@ -12454,6 +12533,8 @@
 		astman_append(s, "SIP-DTMFmode: %s\r\n", dtmfmode2str(ast_test_flag(&peer->flags[0], SIP_DTMF)));
 		astman_append(s, "ToHost: %s\r\n", peer->tohost);
 		astman_append(s, "Address-IP: %s\r\nAddress-Port: %d\r\n",  peer->addr.sin_addr.s_addr ? ast_inet_ntoa(peer->addr.sin_addr) : "", ntohs(peer->addr.sin_port));
+		astman_append(s, "FailoverHostName: %s\r\n", peer->failoverhostname);
+		astman_append(s, "FailoverAddress-IP: %s\r\nAddress-Port: %d\r\n",  peer->failoveraddr.sin_addr.s_addr ? ast_inet_ntoa(peer->failoveraddr.sin_addr) : "", ntohs(peer->failoveraddr.sin_port));
 		astman_append(s, "Default-addr-IP: %s\r\nDefault-addr-port: %d\r\n", ast_inet_ntoa(peer->defaddr.sin_addr), ntohs(peer->defaddr.sin_port));
 		astman_append(s, "Default-Username: %s\r\n", peer->username);
 		if (!ast_strlen_zero(global_regcontext))




More information about the asterisk-commits mailing list