[asterisk-commits] oej: branch oej/oolong-path-support-1.8 r372133 - in /team/oej/oolong-path-su...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Tue Sep 4 05:03:52 CDT 2012


Author: oej
Date: Tue Sep  4 05:03:47 2012
New Revision: 372133

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=372133
Log:
Adding Klaus' patch for PATH header support 
- Added global support

Modified:
    team/oej/oolong-path-support-1.8/channels/chan_sip.c
    team/oej/oolong-path-support-1.8/channels/sip/include/sip.h
    team/oej/oolong-path-support-1.8/configs/sip.conf.sample

Modified: team/oej/oolong-path-support-1.8/channels/chan_sip.c
URL: http://svnview.digium.com/svn/asterisk/team/oej/oolong-path-support-1.8/channels/chan_sip.c?view=diff&rev=372133&r1=372132&r2=372133
==============================================================================
--- team/oej/oolong-path-support-1.8/channels/chan_sip.c (original)
+++ team/oej/oolong-path-support-1.8/channels/chan_sip.c Tue Sep  4 05:03:47 2012
@@ -1281,6 +1281,8 @@
 static void free_old_route(struct sip_route *route);
 static void list_route(struct sip_route *route);
 static void build_route(struct sip_pvt *p, struct sip_request *req, int backwards, int resp);
+static void build_path(struct sip_pvt *p, struct sip_peer *peer, struct sip_request *req, char *pathbuf);
+static void copy_route(struct sip_route **d, struct sip_route *s);
 static enum check_auth_result register_verify(struct sip_pvt *p, struct ast_sockaddr *addr,
 					      struct sip_request *req, const char *uri);
 static struct sip_pvt *get_sip_pvt_byid_locked(const char *callid, const char *totag, const char *fromtag);
@@ -1528,6 +1530,7 @@
 static int add_rpid(struct sip_request *req, struct sip_pvt *p);
 static int add_vidupdate(struct sip_request *req);
 static void add_route(struct sip_request *req, struct sip_route *route);
+static void make_route_list(struct sip_route *route, char *r, int rem);
 static int copy_header(struct sip_request *req, const struct sip_request *orig, const char *field);
 static int copy_all_header(struct sip_request *req, const struct sip_request *orig, const char *field);
 static int copy_via_headers(struct sip_pvt *p, struct sip_request *req, const struct sip_request *orig, const char *field);
@@ -4692,6 +4695,11 @@
 		peer->chanvars = NULL;
 	}
 	
+	if (peer->path) {
+		free_old_route(peer->path);
+		peer->path = NULL;
+	}
+
 	register_peer_exten(peer, FALSE);
 	ast_free_ha(peer->ha);
 	ast_free_ha(peer->directmediaha);
@@ -4720,6 +4728,7 @@
 /*! \brief Update peer data in database (if used) */
 static void update_peer(struct sip_peer *p, int expire)
 {
+/* klaus: TODO: store/read Path to/from realtime */
 	int rtcachefriends = ast_test_flag(&p->flags[1], SIP_PAGE2_RTCACHEFRIENDS);
 	if (sip_cfg.peer_rtupdate &&
 	    (p->is_realtime || rtcachefriends)) {
@@ -5290,6 +5299,8 @@
 	return 0;
 }
 
+static int __set_address_from_contact(const char *fullcontact, struct ast_sockaddr *addr, int tcp);
+
 /*! \brief Create address structure from peer reference.
  *	This function copies data from peer to the dialog, so we don't have to look up the peer
  *	again from memory or database during the life time of the dialog.
@@ -5319,6 +5330,11 @@
 	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);
 	ast_copy_flags(&dialog->flags[2], &peer->flags[2], SIP_PAGE3_FLAGS_TO_COPY);
+	copy_route(&dialog->route, peer->path);
+	if (dialog->route) {
+		/* Parse SIP URI of first route-set hop and use it as target address */
+		__set_address_from_contact(dialog->route->hop, &dialog->sa, dialog->socket.type == SIP_TRANSPORT_TLS ? 1 : 0);	
+	}
 	dialog->capability = peer->capability;
 	dialog->prefs = peer->prefs;
 	dialog->amaflags = peer->amaflags;
@@ -10109,11 +10125,20 @@
 /*! \brief Add route header into request per learned route */
 static void add_route(struct sip_request *req, struct sip_route *route)
 {
-	char r[SIPBUFSIZE*2], *p;
-	int n, rem = sizeof(r);
+	char r[SIPBUFSIZE*2];
 
 	if (!route)
 		return;
+
+	make_route_list(route, r, sizeof(r));
+	add_header(req, "Route", r);
+}
+
+/*! \brief Make the comma separated list of route headers from the route list */
+static void make_route_list(struct sip_route *route, char *r, int rem)
+{
+	char *p;
+	int n;
 
 	p = r;
 	for (;route ; route = route->next) {
@@ -10131,7 +10156,6 @@
 		rem -= (n+2);
 	}
 	*p = '\0';
-	add_header(req, "Route", r);
 }
 
 /*! \brief Set destination from SIP URI
@@ -13809,6 +13833,7 @@
 			ast_update_realtime(tablename, "name", peer->name, "fullcontact", "", "ipaddr", "", "port", "", "regseconds", "0", "regserver", "", "useragent", "", "lastms", "0", SENTINEL);
 		} else {
 			ast_db_del("SIP/Registry", peer->name);
+			ast_db_del("SIP/RegistryPath", peer->name);
 			ast_db_del("SIP/PeerMethods", peer->name);
 		}
 	}
@@ -13906,6 +13931,7 @@
 static void reg_source_db(struct sip_peer *peer)
 {
 	char data[256];
+	char path[SIPBUFSIZE*2];
 	struct ast_sockaddr sa;
 	int expire;
 	char full_addr[128];
@@ -13964,6 +13990,11 @@
 			unref_peer(peer, "remove registration ref"),
 			ref_peer(peer, "add registration ref"));
 	register_peer_exten(peer, TRUE);
+	if (ast_db_get("SIP/RegistryPath", peer->name, path, sizeof(path))) {
+		return;
+	}
+	build_path(0, peer, 0, path);
+
 }
 
 /*! \brief Save contact header for 200 OK on INVITE */
@@ -14258,11 +14289,16 @@
 		}
 	}
 	pvt->expiry = expire;
+	build_path(pvt, peer, req, 0);
 	snprintf(data, sizeof(data), "%s:%d:%s:%s", ast_sockaddr_stringify(&peer->addr),
 		 expire, peer->username, peer->fullcontact);
 	/* We might not immediately be able to reconnect via TCP, but try caching it anyhow */
-	if (!peer->rt_fromcontact || !sip_cfg.peer_rtupdate)
+	if (!peer->rt_fromcontact || !sip_cfg.peer_rtupdate) {
+		char path[SIPBUFSIZE*2];
+		make_route_list(peer->path, path, sizeof(path));
+		ast_db_put("SIP/RegistryPath", peer->name, path);
 		ast_db_put("SIP/Registry", peer->name, data);
+	}
 	manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "ChannelType: SIP\r\nPeer: SIP/%s\r\nPeerStatus: Registered\r\nAddress: %s\r\n", peer->name,  ast_sockaddr_stringify(&peer->addr));
 
 	/* Is this a new IP address for us? */
@@ -14298,10 +14334,10 @@
 static void list_route(struct sip_route *route)
 {
 	if (!route) {
-		ast_verbose("list_route: no route\n");
+		ast_verbose("list_route: no route/path\n");
 	} else {
 		for (;route; route = route->next)
-			ast_verbose("list_route: hop: <%s>\n", route->hop);
+			ast_verbose("list_route: route/path hop: <%s>\n", route->hop);
 	}
 }
 
@@ -14411,6 +14447,107 @@
 	/* For debugging dump what we ended up with */
 	if (sip_debug_test_pvt(p)) {
 		list_route(p->route);
+	}
+}
+
+/*! \brief copy route-set */
+static void copy_route(struct sip_route **d, struct sip_route *s)
+{
+	struct sip_route *thishop, *head, *tail;
+	/* Build a tailq, then assign it to **d when done.
+	 */
+	head = NULL;
+	tail = head;
+	while (s) {
+		int len = strlen(s->hop) + 1;
+		if ((thishop = ast_malloc(sizeof(*thishop) + len))) {
+			/* ast_calloc is not needed because all fields are initialized in this block */
+			ast_copy_string(thishop->hop, s->hop, len);
+			ast_debug(2, "copy_route: copied hop: <%s>\n", thishop->hop);
+			thishop->next = NULL;
+			/* Link in at the end */
+			if (tail) {
+				tail->next = thishop;
+			} else {
+				head = thishop;
+			}
+			tail = thishop;
+		}
+		s = s->next;
+	}
+	*d = head;
+}
+/*! \brief Build route list from Path header 
+ *  RFC 3327 requires that the Path header contains SIP URIs with lr paramter.
+ *  Thus, we do not care about strict routers 
+ */
+static void build_path(struct sip_pvt *p, struct sip_peer *peer, struct sip_request *req, char *pathbuf)
+{
+	struct sip_route *thishop, *head, *tail;
+	int start = 0;
+	int len;
+	const char *rr;
+
+	if (peer->path) {
+		free_old_route(peer->path);
+		peer->path = NULL;
+	}
+
+	if (!ast_test_flag(&peer->flags[0], SIP_USEPATH)) {
+		ast_debug(2, "build_path: do not use Path headers\n");
+		return;
+	}
+	ast_debug(2, "build_path: try to build pre-loaded route-set by parsing Path headers\n");
+
+	/* Build a tailq, then assign it to peer->path when done.
+	 */
+	head = NULL;
+	tail = head;
+	/* 1st we pass through all the hops in any Path headers */
+	for (;;) {
+		/* Either loop over the request's Path headers or parse the buffer */
+		if (req) {
+			rr = __get_header(req, "Path", &start);
+			if (*rr == '\0') {
+				break;
+			}
+		} else if (pathbuf) {
+			if (start == 0) {
+				rr = pathbuf;
+				start++;
+			} else {
+				break;
+			}
+		} else {
+			break;
+		}
+		for (; (rr = strchr(rr, '<')) ; rr += len) { /* Each route entry */
+			++rr;
+			len = strcspn(rr, ">") + 1;
+			/* Make a struct route */
+			if ((thishop = ast_malloc(sizeof(*thishop) + len))) {
+				/* ast_calloc is not needed because all fields are initialized in this block */
+				ast_copy_string(thishop->hop, rr, len);
+				ast_debug(2, "build_path: Path hop: <%s>\n", thishop->hop);
+				/* Link in */
+				thishop->next = NULL;
+				/* Link in at the end */
+				if (tail) {
+					tail->next = thishop;
+				} else {
+					head = thishop;
+				}
+				tail = thishop;
+			}
+		}
+	}
+
+	/* Store as new route */
+	peer->path = head;
+
+	/* For debugging dump what we ended up with */
+	if (p && sip_debug_test_pvt(p)) {
+		list_route(peer->path);
 	}
 }
 
@@ -17664,6 +17801,20 @@
 		ast_cli(fd, "  Ign SDP ver  : %s\n", AST_CLI_YESNO(ast_test_flag(&peer->flags[1], SIP_PAGE2_IGNORESDPVERSION)));
 		ast_cli(fd, "  Trust RPID   : %s\n", AST_CLI_YESNO(ast_test_flag(&peer->flags[0], SIP_TRUSTRPID)));
 		ast_cli(fd, "  Send RPID    : %s\n", AST_CLI_YESNO(ast_test_flag(&peer->flags[0], SIP_SENDRPID)));
+		ast_cli(fd, "  Path support : %s\n", AST_CLI_YESNO(ast_test_flag(&peer->flags[0], SIP_USEPATH)));
+		ast_cli(fd, "  Path         : ");
+		if (!peer->path) {
+			ast_cli(fd, "N/A\n");
+		} else {
+			struct sip_route *r=peer->path;
+			int first = 1;
+			while (r) {
+				ast_cli(fd, "%s<%s>", first ? "" : ", ", r->hop);
+				first = 0;
+				r=r->next;
+			}
+			ast_cli(fd, "\n");
+		}
 		ast_cli(fd, "  Subscriptions: %s\n", AST_CLI_YESNO(ast_test_flag(&peer->flags[1], SIP_PAGE2_ALLOWSUBSCRIBE)));
 		ast_cli(fd, "  Overlap dial : %s\n", allowoverlap2str(ast_test_flag(&peer->flags[1], SIP_PAGE2_ALLOWOVERLAP)));
 		if (peer->outboundproxy)
@@ -26522,6 +26673,7 @@
 	ast_copy_flags(&p->flags[0], &peer->flags[0], SIP_FLAGS_TO_COPY);
 	ast_copy_flags(&p->flags[1], &peer->flags[1], SIP_PAGE2_FLAGS_TO_COPY);
 	ast_copy_flags(&p->flags[2], &peer->flags[2], SIP_PAGE3_FLAGS_TO_COPY);
+	copy_route(&p->route, peer->path);
 
 	/* Send OPTIONs to peer's fullcontact */
 	if (!ast_strlen_zero(peer->fullcontact)) {
@@ -26954,6 +27106,9 @@
 	if (!strcasecmp(v->name, "trustrpid")) {
 		ast_set_flag(&mask[0], SIP_TRUSTRPID);
 		ast_set2_flag(&flags[0], ast_true(v->value), SIP_TRUSTRPID);
+	} else if (!strcasecmp(v->name, "supportpath")) {
+		ast_set_flag(&mask[0], SIP_USEPATH);
+		ast_set2_flag(&flags[0], ast_true(v->value), SIP_USEPATH);
 	} else if (!strcasecmp(v->name, "sendrpid")) {
 		ast_set_flag(&mask[0], SIP_SENDRPID);
 		if (!strcasecmp(v->value, "pai")) {

Modified: team/oej/oolong-path-support-1.8/channels/sip/include/sip.h
URL: http://svnview.digium.com/svn/asterisk/team/oej/oolong-path-support-1.8/channels/sip/include/sip.h?view=diff&rev=372133&r1=372132&r2=372133
==============================================================================
--- team/oej/oolong-path-support-1.8/channels/sip/include/sip.h (original)
+++ team/oej/oolong-path-support-1.8/channels/sip/include/sip.h Tue Sep  4 05:03:47 2012
@@ -283,6 +283,7 @@
 #define SIP_PROG_INBAND_NO     (1 << 25)
 #define SIP_PROG_INBAND_YES    (2 << 25)
 
+#define SIP_USEPATH          (1 << 27) /*!< P: Trust and use incoming Path headers? */
 #define SIP_SENDRPID         (3 << 29) /*!< DP: Remote Party-ID Support */
 #define SIP_SENDRPID_NO      (0 << 29)
 #define SIP_SENDRPID_PAI     (1 << 29) /*!< Use "P-Asserted-Identity" for rpid */
@@ -293,7 +294,7 @@
 #define SIP_FLAGS_TO_COPY \
 	(SIP_PROMISCREDIR | SIP_TRUSTRPID | SIP_SENDRPID | SIP_DTMF | SIP_REINVITE | \
 	 SIP_PROG_INBAND | SIP_USECLIENTCODE | SIP_NAT_FORCE_RPORT | SIP_G726_NONSTANDARD | \
-	 SIP_USEREQPHONE | SIP_INSECURE)
+	 SIP_USEREQPHONE | SIP_INSECURE | SIP_USEPATH)
 /*@}*/
 
 /*! \name SIPflags2
@@ -1265,6 +1266,7 @@
 	int timer_t1;                   /*!<  The maximum T1 value for the peer */
 	int timer_b;                    /*!<  The maximum timer B (transaction timeouts) */
 	int fromdomainport;             /*!<  The From: domain port */
+	struct sip_route *path;         /*!<  Head of linked list of out-of-dialog outgoing routing steps (fm Path headers) */
 
 	/*XXX Seems like we suddenly have two flags with the same content. Why? To be continued... */
 	enum sip_peer_type type; /*!< Distinguish between "user" and "peer" types. This is used solely for CLI and manager commands */

Modified: team/oej/oolong-path-support-1.8/configs/sip.conf.sample
URL: http://svnview.digium.com/svn/asterisk/team/oej/oolong-path-support-1.8/configs/sip.conf.sample?view=diff&rev=372133&r1=372132&r2=372133
==============================================================================
--- team/oej/oolong-path-support-1.8/configs/sip.conf.sample (original)
+++ team/oej/oolong-path-support-1.8/configs/sip.conf.sample Tue Sep  4 05:03:47 2012
@@ -414,6 +414,15 @@
 ;outboundproxy=[2001:db8::1]:5062               ; IPv6 address literal with explicit port
 ;                                               ; (could also be tcp,udp) - defining transports on the proxy line only
 ;                                               ; applies for the global proxy, otherwise use the transport= option
+;supportpath=yes		; This activates parsing and handling of Path header as defined in RFC 3327. This enables
+				; Asterisk to route outgoing out-of-dialog requests via a set of proxies by using a pre-loaded
+				; route-set defined by the Path headers in the REGISTER request. NOTE: As this influences routing 
+				; of SIP requests make sure to not trust Path headers provided by the user's SIP client (the proxy
+				; in front of Asterisk should remove existing user provided Path headers). NOTE: when a peer has a
+				; path and outboundproxy set, the path will be added to Router header but routing to next hop is
+				; done using the outboundproxy. 
+				; NOTE: Path support does not work with realtime registrations yet.
+
 ;matchexternaddrlocally = yes     ; Only substitute the externaddr or externhost setting if it matches
                                 ; your localnet setting. Unless you have some sort of strange network
                                 ; setup you will not need to enable this.




More information about the asterisk-commits mailing list