Index: asterisk/channels/chan_sip.c =================================================================== RCS file: /usr/cvsroot/asterisk/channels/chan_sip.c,v retrieving revision 1.610 diff -u -r1.610 chan_sip.c --- asterisk/channels/chan_sip.c 3 Jan 2005 00:51:57 -0000 1.610 +++ asterisk/channels/chan_sip.c 3 Jan 2005 21:07:01 -0000 @@ -107,7 +107,7 @@ #define DEFAULT_RETRANS 1000 /* How frequently to retransmit */ #define MAX_RETRANS 5 /* Try only 5 times for retransmissions */ - /* SIP Debug */ + #define DEBUG_READ 0 /* Recieved data */ #define DEBUG_SEND 1 /* Transmit data */ @@ -4007,6 +4007,20 @@ return send_request(p, &req, 1, p->ocseq); } +static int transmit_sip_request(struct sip_pvt *p,struct sip_request *req) +{ + if (!p->initreq.headers) { + /* Use this as the basis */ + copy_request(&p->initreq, req); + parse(&p->initreq); + if (sip_debug_test_pvt(p)) + ast_verbose("%d headers, %d lines\n", p->initreq.headers, p->initreq.lines); + determine_firstline_parts(&p->initreq); + } + + return send_request(p, req, 1, p->ocseq); +} + /*--- transmit_notify_with_sipfrag: Notify a transferring party of the status of trasnfer ---*/ /* Apparently the draft SIP REFER structure was too simple, so it was decided that the * status of transfers also needed to be sent via NOTIFY instead of just the 202 Accepted @@ -6121,6 +6135,26 @@ return c; } +/*--- complete_sippeer: Support routine for 'sip reboot' CLI ---*/ +static char *complete_sippeer(char *line, char *word, int pos, int state) +{ + int which=0; + char *c = NULL; + + ASTOBJ_CONTAINER_TRAVERSE(&peerl, do { + /* locking of the ASTOBJ is not required because I only compare the name */ + if (!strncasecmp(word, iterator->name, strlen(word))) { + if (++which > state) { + c = strdup(iterator->name); + break; + } + } + + } while(0) ); + + return c; +} + /*--- sip_show_channel: Show details of one call ---*/ static int sip_show_channel(int fd, int argc, char *argv[]) { @@ -6371,6 +6405,76 @@ return RESULT_SUCCESS; } +static int sip_notify(int fd, int argc, char *argv[]) +{ + struct sip_pvt *p; + struct sip_request req; + struct ast_config *cfg; + struct ast_variable *var; + char *cat; + char name[256] = ""; + char type[256] = ""; + char iabuf[INET_ADDRSTRLEN]; + char foundtype = 0; + + if (argc != 4) { + return RESULT_SHOWUSAGE; + } else { + p = sip_alloc(NULL, NULL, 0); + if (!p) { + ast_log(LOG_WARNING, "Unable to build sip pvt data for reboot\n"); + return -1; + } + strncpy(type,argv[2],sizeof(type) - 1); + cfg = ast_load("sip_notify.conf"); + + if (!cfg) { + ast_log(LOG_WARNING, "No sip_notify.conf file :\n"); + return RESULT_SUCCESS; + } + + initreqprep(&req, p, "NOTIFY", NULL); + + cat = ast_category_browse(cfg, NULL); + while(cat) { + if (!strcasecmp(cat, type)) { + foundtype = 1; + + var = ast_variable_browse(cfg, cat); + while (var) { + add_header(&req, var->name, var->value); + var = var->next; + } + } + cat = ast_category_browse(cfg, cat); + } + ast_destroy(cfg); + + if (foundtype == 0) { + ast_log(LOG_WARNING, "Unable to find notify enter '%s'\n",argv[2]); + return RESULT_SUCCESS; + } + + strncpy(name, argv[3], sizeof(name) - 1); + if (create_addr(p, name)) { + /* Maybe they're not registered, etc. */ + sip_destroy(p); + return 0; + } + /* Recalculate our side, and recalculate Call ID */ + if (ast_sip_ouraddrfor(&p->sa.sin_addr,&p->ourip)) + memcpy(&p->ourip, &__ourip, sizeof(p->ourip)); + /* z9hG4bK is a magic cookie. See RFC 3261 section 8.1.1.7 */ + if (ast_test_flag(p, SIP_NAT) & SIP_NAT_RFC3581) + snprintf(p->via, sizeof(p->via), "SIP/2.0/UDP %s:%d;branch=z9hG4bK%08x;rport", ast_inet_ntoa(iabuf, sizeof(iabuf), p->ourip), ourport, p->branch); + else /* UNIDEN UIP200 bug */ + snprintf(p->via, sizeof(p->via), "SIP/2.0/UDP %s:%d;branch=z9hG4bK%08x", ast_inet_ntoa(iabuf, sizeof(iabuf), p->ourip), ourport, p->branch); + build_callid(p->callid, sizeof(p->callid), p->ourip, p->fromdomain); + transmit_sip_request(p,&req); + sip_scheddestroy(p, 15000); + } + return RESULT_SUCCESS; +} /*--- sip_do_history: Enable SIP History logging (CLI) ---*/ static int sip_do_history(int fd, int argc, char *argv[]) { @@ -6590,6 +6694,9 @@ +static char notify_usage[] = +"Usage: sip notify \n" +" Send a notify command to a remote SIP peer\n"; static char show_users_usage[] = "Usage: sip show users\n" @@ -6657,7 +6764,8 @@ "Usage: sip show objects\n" " Shows status of known SIP objects\n"; - +static struct ast_cli_entry cli_notify = + { { "sip", "notify", NULL }, sip_notify, "Send a notify packet to a SIP peer", notify_usage, complete_sippeer }; static struct ast_cli_entry cli_show_objects = { { "sip", "show", "objects", NULL }, sip_show_objects, "Show all SIP object allocations", show_objects_usage }; static struct ast_cli_entry cli_show_users = @@ -9391,6 +9499,7 @@ ast_log(LOG_ERROR, "Unable to register channel class %s\n", channeltype); return -1; } + ast_cli_register(&cli_notify); ast_cli_register(&cli_show_users); ast_cli_register(&cli_show_objects); ast_cli_register(&cli_show_subscriptions); @@ -9433,6 +9542,7 @@ ast_unregister_application(app_dtmfmode); ast_unregister_application(app_sipaddheader); ast_unregister_application(app_sipgetheader); + ast_cli_unregister(&cli_notify); ast_cli_unregister(&cli_show_users); ast_cli_unregister(&cli_show_objects); ast_cli_unregister(&cli_show_channels); --- ../../src/orig/asterisk/configs 1969-12-31 19:00:00.000000000 -0500 +++ asterisk/configs/sip_notify.conf.sample 2005-01-03 15:39:07.000000000 -0500 @@ -0,0 +1,17 @@ +[reboot-polycom] +Event=>check-sync +Content-Length=>0 + +; Untested +[reboot-sipura] +Event=>resync +Content-Length=>0 + +; Untested +[reboot-grandstream] +Event=>sys-control + +; Untested +[reboot-cisco] +Event=>check-sync +Content-Length=>0