rendered paste bodyIndex: 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;
}