Index: channels/chan_iax2.c =================================================================== RCS file: /usr/cvsroot/asterisk/channels/chan_iax2.c,v retrieving revision 1.253 diff -u -r1.253 chan_iax2.c --- channels/chan_iax2.c 28 Feb 2005 06:40:20 -0000 1.253 +++ channels/chan_iax2.c 1 Mar 2005 16:08:23 -0000 @@ -1678,9 +1678,24 @@ return RESULT_SUCCESS; } + +static int _iax2_show_peer(int type, int fd, struct mansession *s, struct message *m, int argc, char *argv[]); + /*--- iax2_show_peer: Show one peer in detail ---*/ static int iax2_show_peer(int fd, int argc, char *argv[]) { + return _iax2_show_peer(0, fd, NULL, NULL, argc, argv); +} + +/*--- iax2_xshow_peer: Show one peer in detail (XML format) ---*/ +static int iax2_xshow_peer(int fd, int argc, char *argv[]) +{ + return _iax2_show_peer(1, fd, NULL, NULL, argc, argv); +} + +/*--- _iax2_xshow_peer: Show one peer in detail (where it really happens) ---*/ +static int _iax2_show_peer(int type, int fd, struct mansession *s, struct message *m, int argc, char *argv[]) +{ char status[30] = ""; char cbuf[256]; char iabuf[INET_ADDRSTRLEN]; @@ -1694,7 +1709,17 @@ load_realtime = (argc == 5 && !strcmp(argv[4], "load")) ? 1 : 0; peer = find_peer(argv[3], load_realtime); - if (peer) { + + if (s) { /* Manager */ + if (peer) + ast_cli(s->fd, "Response: Success\r\n"); + else { + snprintf (cbuf, sizeof(cbuf), "Peer %s not found.\n", argv[3]); + astman_send_error(s, m, cbuf); + return 0; + } + } + if (peer && type == 0) { ast_cli(fd,"\n\n"); ast_cli(fd, " * Name : %s\n", peer->name); ast_cli(fd, " Secret : %s\n", ast_strlen_zero(peer->secret)?"":""); @@ -1739,6 +1764,51 @@ ast_cli(fd,"\n"); if (ast_test_flag(peer, IAX_TEMPONLY)) destroy_peer(peer); + } else if (peer && type == 1) { + ast_cli(fd,"\n"); + ast_cli(fd,"\n"); + ast_cli(fd,"\n"); + ast_cli(fd, "\n%s\n", peer->name); + ast_cli(fd, "%smd5\n", ast_strlen_zero(peer->secret)?"no":"yes"); + ast_cli(fd, "%s\n", peer->context); + ast_cli(fd, "%s\n", peer->mailbox); + ast_cli(fd, "%s\n", (ast_test_flag(peer, IAX_DYNAMIC)?"yes":"no")); + ast_cli(fd, "%s%s\n", peer->cid_name, peer->cid_num); + ast_cli(fd, "%d\n", peer->expire); + ast_cli(fd, "%s\n", (peer->ha?"yes":"no")); + ast_cli(fd, "%s%d\n", peer->addr.sin_addr.s_addr ? ast_inet_ntoa(iabuf, sizeof(iabuf), peer->addr.sin_addr) : "", ntohs(peer->addr.sin_port)); + ast_cli(fd, "%s%d\n", ast_inet_ntoa(iabuf, sizeof(iabuf), peer->defaddr.sin_addr), ntohs(peer->defaddr.sin_port)); + + ast_cli(fd, "%s\n", peer->username); + ast_cli(fd, ""); + ast_getformatname_multiple(codec_buf, sizeof(codec_buf) -1, peer->capability); + ast_cli(fd, "%s\n", codec_buf); + ast_cli(fd, ""); + for(x = 0; x < 32 ; x++) { + codec = ast_codec_pref_index(&peer->prefs,x); + if(!codec) + break; + ast_cli(fd, "%s", ast_getformatname(codec)); + if(x < 31 && ast_codec_pref_index(&peer->prefs,x+1)) + ast_cli(fd, ","); + } + + ast_cli(fd, "\n\n"); + + + ast_cli(fd, ""); + if (peer->lastms < 0) + strncpy(status, "UNREACHABLE", sizeof(status) - 1); + else if (peer->lastms > peer->maxms) + snprintf(status, sizeof(status), "LAGGED (%d ms)", peer->lastms); + else if (peer->lastms) + snprintf(status, sizeof(status), "OK (%d ms)", peer->lastms); + else + strncpy(status, "UNKNOWN", sizeof(status) - 1); + ast_cli(fd, "%s\n",status); + ast_cli(fd,"\n"); + if (ast_test_flag(peer, IAX_TEMPONLY)) + destroy_peer(peer); } else { ast_cli(fd,"Peer %s not found.\n", argv[3]); ast_cli(fd,"\n"); @@ -1855,6 +1925,10 @@ "Usage: iax show peer \n" " Display details on specific IAX peer\n"; +static char xshow_peer_usage[] = +"Usage: iax xshow peer \n" +" Display details on specific IAX peer (XML format)\n"; + static char prune_realtime_usage[] = "Usage: iax2 prune realtime [|all]\n" " Prunes object(s) from the cache\n"; @@ -1868,6 +1942,9 @@ static struct ast_cli_entry cli_show_cache = { { "iax2", "show", "cache", NULL }, iax2_show_cache, "Display IAX cached dialplan", show_cache_usage }; +static struct ast_cli_entry cli_xshow_peer = + { { "iax2", "xshow", "peer", NULL }, iax2_xshow_peer, "Show details on specific IAX peer (XML)", xshow_peer_usage, complete_iax2_show_peer }; + static struct ast_cli_entry cli_show_peer = { { "iax2", "show", "peer", NULL }, iax2_show_peer, "Show details on specific IAX peer", show_peer_usage, complete_iax2_show_peer }; @@ -3680,8 +3757,23 @@ #undef FORMAT2 } +static int _iax2_show_peers(int type, int fd, struct mansession *s, struct message *m, int argc, char *argv[]); + +/*--- iax2_xshow_peers: List all IAX2 peers to CLI or manager in XML format*/ +static int iax2_xshow_peers(int fd, int argc, char *argv[]) +{ + return _iax2_show_peers(1, fd, NULL, NULL, argc, argv); +} + +/*--- iax2_show_peers: List all IAX2 peers to CLI or manager */ static int iax2_show_peers(int fd, int argc, char *argv[]) { + return _iax2_show_peers(0, fd, NULL, NULL, argc, argv); +} + +/*--- _iax2_show_peers: Do the real job here */ +static int _iax2_show_peers(int type, int fd, struct mansession *s, struct message *m, int argc, char *argv[]) +{ regex_t regexbuf; int havepattern = 0; int total_peers = 0; @@ -3691,7 +3783,7 @@ #define FORMAT2 "%-15.15s %-15.15s %s %-15.15s %-8s %s %-10s\n" #define FORMAT "%-15.15s %-15.15s %s %-15.15s %-5d%s %s %-10s\n" - +#define FORMATXML "%s%s%d%s%s%s%s%s%s/>\n" struct iax2_peer *peer; char name[256] = ""; char iabuf[INET_ADDRSTRLEN]; @@ -3729,12 +3821,19 @@ } ast_mutex_lock(&peerl.lock); - ast_cli(fd, FORMAT2, "Name/Username", "Host", " ", "Mask", "Port", " ", "Status"); + if (type == 0) { /* Normal list */ + ast_cli(fd, FORMAT2, "Name/Username", "Host", " ", "Mask", "Port", " ", "Status"); + } else { + ast_cli(fd, "\n", havepattern?"on":"off"); + } for (peer = peerl.peers;peer;peer = peer->next) { char nm[20]; char status[20] = ""; char srch[2000] = ""; total_peers++; + if (total_peers == 1 && s) { + ast_cli(s->fd, "Response: Success\r\n"); + } if (registeredonly && !peer->addr.sin_addr.s_addr) continue; @@ -3775,16 +3874,37 @@ ntohs(peer->addr.sin_port), ast_test_flag(peer, IAX_TRUNK) ? "(T)" : " ", peer->encmethods ? "(E)" : " ", status); - ast_cli(fd, FORMAT, name, + if (type == 0) { /* Normal format */ + ast_cli(fd, FORMAT, name, peer->addr.sin_addr.s_addr ? ast_inet_ntoa(iabuf, sizeof(iabuf), peer->addr.sin_addr) : "(Unspecified)", ast_test_flag(peer, IAX_DYNAMIC) ? "(D)" : "(S)", nm, ntohs(peer->addr.sin_port), ast_test_flag(peer, IAX_TRUNK) ? "(T)" : " ", peer->encmethods ? "(E)" : " ", status); + } else { /* XML format */ + ast_cli(fd, FORMATXML, name, + peer->addr.sin_addr.s_addr ? ast_inet_ntoa(iabuf, sizeof(iabuf), peer->addr.sin_addr) : "", + ntohs(peer->addr.sin_port), + ast_test_flag(peer, IAX_TRUNK) ? "yes" : "no", + ast_test_flag(peer, IAX_DYNAMIC) ? "yes" : "no", + nm, + peer->ha ? "yes" : "no", + status, + peer->encmethods ? "yes" : "no" + ); + } } ast_mutex_unlock(&peerl.lock); - ast_cli(fd,"%d iax2 peers [%d online, %d offline, %d unmonitored]\n", total_peers, online_peers, offline_peers, unmonitored_peers); + if (total_peers == 0 && s) { + astman_send_error(s, m, "No IAX2 peers found.\n"); + return 0; + } + if (type == 0) /* Normal list */ + ast_cli(fd,"%d iax2 peers [%d online, %d offline, %d unmonitored]\n", total_peers, online_peers, offline_peers, unmonitored_peers); + else { /* XML list */ + ast_cli(fd,"\n"); + } if (havepattern) regfree(®exbuf); @@ -3815,15 +3935,82 @@ #undef FORMAT2 } -/* JDG: callback to display iax peers in manager */ +static char mandescr_show_peers[] = +"Description: Lists all peers in memory, with details on current status.\n" +" The XML format is under development, feedback welcome! /oej\n" +"Variables: \n" +" ActionID: Action ID for this transaction. Will be returned. (optional)\n" +" Accept: Indication of accepted output. (optional)\n" +" Default: text/plain\n" +" text/xml will give XML output.\n"; + +/*--- manager_iax2_show_peers: callback to display iax peers in manager */ static int manager_iax2_show_peers( struct mansession *s, struct message *m ) { - char *a[] = { "iax2", "show", "users" }; + char *id = astman_get_header(m,"ActionID"); + char *format = astman_get_header(m,"Accept"); + char *a[] = { "iax2", "show", "peers" }; int ret; - ret = iax2_show_peers( s->fd, 3, a ); - ast_cli( s->fd, "\r\n" ); + int type = 0; /* Default format */ + + if (format && strstr(format, "text/xml")) + type = 1; /* Client accepts XML */ + + ast_mutex_lock(&s->lock); + if (id && !ast_strlen_zero(id)) + ast_cli(s->fd, "ActionID: %s\r\n",id); + if (type == 1) + ast_cli(s->fd, "Content-type: text/xml\r\n"); + ret = _iax2_show_peers(type, s->fd, s, m, 3, a ); + ast_cli( s->fd, "\r\n\r\n" ); + ast_mutex_unlock(&s->lock); return ret; -} /* /JDG */ +} + +static char mandescr_iax2_peer[] = +"Description: Show one IAX2 peer with details on current status.\n" +" The XML format is under development, feedback welcome! /oej\n" +"Variables: \n" +" Peer: The peer name you want to check.\n" +" ActionID: Optional action ID for this AMI transaction. (optional) \n" +" Accept: text/xml Indicates that we can send the listing in XML format. (optional) \n" +" Accept: text/plain The default format (as in the CLI.) (optional) \n"; + + +/*--- manager_iax2_show_peer: callback to display iax peer in manager */ +static int manager_iax2_show_peer( struct mansession *s, struct message *m ) +{ + char *id = astman_get_header(m,"ActionID"); + char *format = astman_get_header(m,"Accept"); + char *peer; + char *a[4]; + int ret; + int type = 0; /* Default format */ + + peer = astman_get_header(m,"Peer"); + if (!peer || ast_strlen_zero(peer)) { + astman_send_error(s, m, "Peer: missing.\n"); + return 0; + } + ast_mutex_lock(&s->lock); + a[0] = "sip"; + a[1] = "show"; + a[2] = "peer"; + a[3] = peer; + + if (format && strstr(format, "text/xml")) + type = 1; /* Client accepts XML */ + + ast_mutex_lock(&s->lock); + if (id && !ast_strlen_zero(id)) + ast_cli(s->fd, "ActionID: %s\n",id); + if (type == 1) + ast_cli(s->fd, "Content-type: text/xml\n"); + ret = _iax2_show_peer(type, s->fd, s, m, 4, a ); + ast_cli( s->fd, "\r\n\r\n" ); + ast_mutex_unlock(&s->lock); + return ret; +} static char *regstate2str(int regstate) { @@ -4024,6 +4211,12 @@ " Optional 'registered' argument lists only peers with known addresses.\n" " Optional regular expression pattern is used to filter the peer list.\n"; +static char xshow_peers_usage[] = +"Usage: iax2 xshow peers [registered] [pattern]\n" +" Lists all known IAX2 peers in XML format.\n" +" Optional 'registered' argument lists only peers with known addresses.\n" +" Optional regular expression pattern is used to filter the peer list.\n"; + static char show_firmware_usage[] = "Usage: iax2 show firmware\n" " Lists all known IAX firmware images.\n"; @@ -4054,6 +4247,8 @@ { { "iax2", "show", "netstats", NULL }, iax2_show_netstats, "Show active IAX channel netstats", show_netstats_usage }; static struct ast_cli_entry cli_show_peers = { { "iax2", "show", "peers", NULL }, iax2_show_peers, "Show defined IAX peers", show_peers_usage }; +static struct ast_cli_entry cli_xshow_peers = + { { "iax2", "xshow", "peers", NULL }, iax2_xshow_peers, "Show defined IAX peers in XML", xshow_peers_usage }; static struct ast_cli_entry cli_show_registry = { { "iax2", "show", "registry", NULL }, iax2_show_registry, "Show IAX registration status", show_reg_usage }; static struct ast_cli_entry cli_debug = @@ -5202,7 +5397,7 @@ return send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_REGREQ, 0, ied.buf, ied.pos, -1); } else return -1; - ast_log(LOG_WARNING, "Registry acknowledge on unknown registery '%s'\n", peer); + ast_log(LOG_WARNING, "IAX2 Registry acknowledge on unknown registery '%s'\n", peer); } else ast_log(LOG_NOTICE, "Can't reregister without a reg\n"); return -1; @@ -6685,7 +6880,7 @@ if (f.subclass == IAX_COMMAND_REGREL) memset(&sin, 0, sizeof(sin)); if (update_registry(iaxs[fr.callno]->peer, &sin, fr.callno, ies.devicetype, fd)) - ast_log(LOG_WARNING, "Registry error\n"); + ast_log(LOG_WARNING, "IAX2 Registry error\n"); if (ies.provverpres && ies.serviceident && sin.sin_addr.s_addr) check_provisioning(&sin, ies.serviceident, ies.provver); break; @@ -6694,7 +6889,7 @@ break; case IAX_COMMAND_REGACK: if (iax2_ack_registry(&ies, &sin, fr.callno)) - ast_log(LOG_WARNING, "Registration failure\n"); + ast_log(LOG_WARNING, "IAX2 Registration failure\n"); /* Send ack immediately, before we destroy */ send_command_immediate(iaxs[fr.callno], AST_FRAME_IAX, IAX_COMMAND_ACK, fr.ts, NULL, 0,fr.iseqno); iax2_destroy_nolock(fr.callno); @@ -8406,15 +8601,17 @@ pthread_join(netthreadid, NULL); } ast_netsock_release(&netsock); - for (x=0;x