All pastes #1716 Raw Edit

Anonymous

public text v1 · immutable
#1716 ·published 2004-10-26 04:09 UTC
rendered paste body
Index: pbx_dundi.c
===================================================================
RCS file: /usr/cvsroot/asterisk/pbx/pbx_dundi.c,v
retrieving revision 1.11
diff -u -r1.11 pbx_dundi.c
--- pbx_dundi.c	24 Oct 2004 17:53:10 -0000	1.11
+++ pbx_dundi.c	26 Oct 2004 04:07:20 -0000
@@ -112,6 +112,10 @@
 static dundi_eid global_eid;
 static int default_expiration = 60;
 static int global_storehistory = 0;
+static int map_update_interval = 0;
+static int map_updates_per_pkt = 45;
+static char map_context[80];
+static struct sockaddr_in map_addr;
 static char dept[80];
 static char org[80];
 static char locality[80];
@@ -2199,6 +2203,7 @@
 		}
 		ast_cli(fd, "Peer:    %s\n", dundi_eid_to_str(eid_str, sizeof(eid_str), &peer->eid));
 		ast_cli(fd, "Model:   %s\n", model2str(peer->model));
+		ast_cli(fd, "Order:   %s\n", order);
 		ast_cli(fd, "Host:    %s\n", peer->addr.sin_addr.s_addr ? ast_inet_ntoa(iabuf, sizeof(iabuf), peer->addr.sin_addr) : "<Unspecified>");
 		ast_cli(fd, "Dynamic: %s\n", peer->dynamic ? "yes" : "no");
 		ast_cli(fd, "KeyPend: %s\n", peer->keypending ? "yes" : "no");
@@ -2240,13 +2245,15 @@
 
 static int dundi_show_peers(int fd, int argc, char *argv[])
 {
-#define FORMAT2 "%-20.20s %-15.15s     %-10.10s %-8.8s %-15.15s\n"
-#define FORMAT "%-20.20s %-15.15s %s %-10.10s %-8.8s %-15.15s\n"
+#define FORMAT2 "%-20.20s %-15.15s     %-10.10s %-10.10s %-8.8s %-15.15s\n"
+#define FORMAT "%-20.20s %-15.15s %s %-10.10s %-10.10s %-8.8s %-15.15s\n"
 	struct dundi_peer *peer;
 	char iabuf[INET_ADDRSTRLEN];
 	int registeredonly=0;
 	char avgms[20];
 	char eid_str[20];
+	char *order = NULL;
+
 	if ((argc != 3) && (argc != 4) && (argc != 5))
 		return RESULT_SHOWUSAGE;
 	if ((argc == 4)) {
@@ -2256,7 +2263,7 @@
 			return RESULT_SHOWUSAGE;
  	}
 	ast_mutex_lock(&peerlock);
-	ast_cli(fd, FORMAT2, "EID", "Host", "Model", "AvgTime", "Status");
+	ast_cli(fd, FORMAT2, "EID", "Host", "Model", "Order", "AvgTime", "Status");
 	for (peer = peers;peer;peer = peer->next) {
 		char status[20] = "";
         int print_line = -1;
@@ -2278,9 +2285,25 @@
 			snprintf(avgms, sizeof(avgms), "%d ms", peer->avgms);
 		else
 			strcpy(avgms, "Unavail");
+		switch(peer->order) {
+		case 0:
+			order = "Primary";
+			break;
+		case 1:
+			order = "Secondary";
+			break;
+		case 2:
+			order = "Tertiary";
+			break;
+		case 3:
+			order = "Quartiary";
+			break;
+		default:
+			order = "Unknown";
+		}
 		snprintf(srch, sizeof(srch), FORMAT, dundi_eid_to_str(eid_str, sizeof(eid_str), &peer->eid), 
 					peer->addr.sin_addr.s_addr ? ast_inet_ntoa(iabuf, sizeof(iabuf), peer->addr.sin_addr) : "(Unspecified)",
-					peer->dynamic ? "(D)" : "(S)", model2str(peer->model), avgms, status);
+					peer->dynamic ? "(D)" : "(S)", model2str(peer->model), order, avgms, status);
 
                 if (argc == 5) {
                   if (!strcasecmp(argv[3],"include") && strstr(srch,argv[4])) {
@@ -2297,7 +2320,7 @@
         if (print_line) {
 			ast_cli(fd, FORMAT, dundi_eid_to_str(eid_str, sizeof(eid_str), &peer->eid), 
 					peer->addr.sin_addr.s_addr ? ast_inet_ntoa(iabuf, sizeof(iabuf), peer->addr.sin_addr) : "(Unspecified)",
-					peer->dynamic ? "(D)" : "(S)", model2str(peer->model), avgms, status);
+					peer->dynamic ? "(D)" : "(S)", model2str(peer->model), order, avgms, status);
 		}
 	}
 	ast_mutex_unlock(&peerlock);
@@ -2533,6 +2556,150 @@
 	return res;
 }
 
+static int dundi_xmit_peering(void *data)
+{
+	char buf[1500];
+	char *ptr = buf;
+	short seq = 1, totseq = 0;
+	int need_send = 0, peer_count = 0;
+	struct dundi_peer *peer;
+	time_t send_t = time(NULL);
+
+	/* Used in the memory copies */
+	short shorttmp;
+	int inttmp;
+
+	if(!map_addr.sin_addr.s_addr) {
+		if(option_verbose)
+			ast_verbose(VERBOSE_PREFIX_1 "No server to send mapping update to...\n");
+		ast_sched_add(sched, map_update_interval, dundi_xmit_peering, 0);
+		return 0;
+	}
+
+	/* Start with the protocol version */
+	*ptr++ = '\001';
+   
+	/* Provide a sequence number for the packet and totals */
+	ast_mutex_lock(&peerlock);
+	peer_count = 0;
+	for (peer = peers;peer;peer = peer->next) {
+		if(has_permission(peer->include, map_context) || has_permission(peer->permit, map_context)) {
+			peer_count++;
+			if(peer_count > map_updates_per_pkt) { /* Peer count = MTU - 64 - header / peerlen -- yeah. really.*/
+				totseq++;
+				peer_count = 1;
+			}
+		}
+	}
+	totseq++;
+
+	/* Timestamp this sequence */
+	inttmp = htonl(send_t);
+	memcpy(ptr, &inttmp, sizeof(time_t));
+	ptr += sizeof(time_t);
+
+	/* Include our update interval, in seconds */
+	shorttmp = htons(map_update_interval/1000);
+	memcpy(ptr, &shorttmp, sizeof(short));
+	ptr += sizeof(short);
+
+	/* Include peers/packet configured */
+	*ptr++ = (unsigned char)map_updates_per_pkt;
+
+	/* Setup sequence headers */
+	shorttmp = htons(seq);
+	memcpy(ptr, &shorttmp, sizeof(short));
+	ptr += sizeof(short);
+
+	shorttmp = htons(totseq);
+	memcpy(ptr, &shorttmp, sizeof(short));
+	ptr += sizeof(short);
+
+	/* Append our global EID */
+	memcpy(ptr, &global_eid, sizeof(global_eid));
+	ptr+= sizeof(global_eid);
+
+	peer_count = 0;
+	for (peer = peers;peer;peer = peer->next) {
+		if(!has_permission(peer->include, map_context) && !has_permission(peer->permit, map_context))
+			continue;
+		peer_count++;
+		need_send = 1;
+
+		/* Copy the peers EID */
+		memcpy(ptr, &peer->eid, sizeof(peer->eid));
+		ptr += sizeof(peer->eid);
+
+		/* This is the remote peer */
+		(unsigned char)*ptr = (unsigned char)(peer->dynamic?0:1);
+		ptr++;
+		memcpy(ptr, &peer->addr.sin_addr.s_addr, sizeof(peer->addr.sin_addr.s_addr));
+		ptr += sizeof(peer->addr.sin_addr.s_addr);
+
+		/* Append the model and order */
+		(unsigned char)*ptr = (unsigned char)peer->model; ptr++;
+		(unsigned char)*ptr = (unsigned char)peer->order; ptr++;
+
+		/* Do some long encoding of the timings */
+		inttmp = htonl(peer->maxms);
+		memcpy(ptr, &inttmp, sizeof(long));
+		ptr += sizeof(long);
+		inttmp = htonl(peer->lastms);
+		memcpy(ptr, &inttmp, sizeof(long));
+		ptr += sizeof(long);
+		inttmp = htonl(peer->avgms);
+		memcpy(ptr, &inttmp, sizeof(long));
+		ptr += sizeof(long);
+
+		if(peer_count == map_updates_per_pkt) { /* Okay, it's actually arbitrary */
+			sendto(netsocket, buf, ptr - buf, 0, (struct sockaddr *)&map_addr, sizeof(map_addr));
+
+			peer_count = 0;
+			need_send = 0;
+			seq++; /* We sent one, so move on */
+
+			/* Recreate the packet header */
+			ptr = buf + 1;
+
+			/* Use the same timestamp header */
+			inttmp = htonl(send_t);
+			memcpy(ptr, &inttmp, sizeof(time_t));
+			ptr += sizeof(time_t);
+
+			/* Include our update interval, in seconds */
+			shorttmp = htons(map_update_interval/1000);
+			memcpy(ptr, &shorttmp, sizeof(short));
+			ptr += sizeof(short);
+
+			/* Include peers/packet configured */
+			*ptr++ = map_updates_per_pkt;
+
+			shorttmp = htons(seq);
+			memcpy(ptr, &shorttmp, sizeof(short));
+			ptr += sizeof(short);
+
+			shorttmp = htons(totseq);
+			memcpy(ptr, &shorttmp, sizeof(short));
+			ptr += sizeof(short);
+
+			memcpy(ptr, &global_eid, sizeof(global_eid));
+			ptr += sizeof(global_eid);
+		}      
+
+	}
+
+	/* If we get here, and haven't sent the packet, send it now */
+	if(need_send) 
+		sendto(netsocket, buf, ptr - buf, 0, (struct sockaddr *)&map_addr, sizeof(map_addr));
+   
+	/* Unlock */
+	ast_mutex_unlock(&peerlock);
+
+	/* Reschedule yourselves */
+	ast_sched_add(sched, map_update_interval, dundi_xmit_peering, 0);
+	return RESULT_SUCCESS;   
+}
+
 static void destroy_packet(struct dundi_packet *pack, int needfree)
 {
 	struct dundi_packet *prev, *cur;
@@ -3969,6 +4136,34 @@
 			strncpy(phone, v->value, sizeof(phone) - 1);
 		} else if (!strcasecmp(v->name, "storehistory")) {
 			global_storehistory = ast_true(v->value);
+		} else if (!strcasecmp(v->name, "mapserver")) {
+			hp = ast_gethostbyname(v->value, &he);
+			if (hp) {
+				memcpy(&map_addr.sin_addr, hp->h_addr, sizeof(map_addr.sin_addr));
+				if (option_verbose > 1)
+					ast_verbose(VERBOSE_PREFIX_2 "Using mapping server at %s\n", v->value);
+			} else {
+				memset(&map_addr.sin_addr, 0, sizeof(map_addr.sin_addr));
+				ast_log(LOG_WARNING, "Could not find host '%s' for mapping host\n", v->value);
+			}
+		} else if (!strcasecmp(v->name, "mappeers_per_pkt")) {
+			map_updates_per_pkt = atoi(v->value);
+			if(map_updates_per_pkt < 1 || map_updates_per_pkt > 45) {
+				ast_log(LOG_WARNING, "Map updates must be between 1 and 45 inclusive. Setting to 45.\n");
+				map_updates_per_pkt = 45;
+			}
+		} else if (!strcasecmp(v->name, "mapport")) {
+			if (option_verbose > 1)
+				ast_verbose(VERBOSE_PREFIX_2 "Using mapping server at port %d\n", atoi(v->value));
+			map_addr.sin_port = htons(atoi(v->value));
+		} else if (!strcasecmp(v->name, "mapinterval")) {
+			map_update_interval = atoi(v->value) * 1000;
+			if(map_update_interval < 5000 && map_update_interval != 0)
+				map_update_interval = 5000;
+			if (option_verbose > 1)
+				ast_verbose(VERBOSE_PREFIX_2 "Using mapping update interval of %d ms\n", map_update_interval);
+		} else if(!strcasecmp(v->name, "mapcontext")) {
+			strncpy(map_context, v->value, sizeof(map_context) - 1);
 		}
 		v = v->next;
 	}
@@ -3995,6 +4190,7 @@
 	prune_peers();
 	ast_destroy(cfg);
 	load_password();
+   
 	return 0;
 }
 
@@ -4043,6 +4239,12 @@
 	sin.sin_port = ntohs(DUNDI_PORT);
 	sin.sin_addr.s_addr = INADDR_ANY;
 
+	/* INADDR_ANY should be 0.0.0.0 */
+	map_addr.sin_family = AF_INET;
+	map_addr.sin_port = ntohs(4525);
+	map_addr.sin_addr.s_addr = INADDR_ANY;
+	strncpy(map_context, "e164", sizeof(map_context) - 1);
+
 	/* Make a UDP socket */
 	io = io_context_create();
 	sched = sched_context_create();
@@ -4096,6 +4298,10 @@
 		close(netsocket);
 	}
 	res = ast_register_application(app, dundi_lookup_exec, synopsis, descrip);
+   
+	if(map_update_interval) 
+		ast_sched_add(sched, map_update_interval, dundi_xmit_peering, 0);
+   
 	return 0;
 }