--- channels/chan_sip.c 2004-09-02 23:51:06.000000000 +0200
+++ channels/chan_sip.c        2004-09-02 23:49:04.000000000 +0200
@@ -62,6 +62,8 @@
 #include <mysql/mysql.h>
 #endif

+#define SIPGSNOTIFY
+
 #ifndef DEFAULT_USERAGENT
 #define DEFAULT_USERAGENT "Asterisk PBX"
 #endif
@@ -5451,6 +5453,129 @@
        }
 }

+
+#ifdef SIPGSNOTIFY
+/* sip_gsnotify: Send reboot packet to grandstream phone. Requires knowledge
+       of file format to send to Grandstream.
+
+       Content-Type: application/octet-stream
+       Event: sys-control
+       Content-Length: 24
+       then it goes 24 bytes binary
+
+       Syntax:
+       sip gsnotify <peername> <filename> [delete]
+*/
+static int sip_gsnotify(int fd, int argc, char *argv[])
+{
+       char *s;
+       char *peername;                 /* Peer to send information to */
+       char *filename;                 /* File to read and send */
+       int deletefileafternotify = 0;  /* Whether or not to delete file */
+        struct sip_request req;
+       struct sip_peer *peer;
+        struct sip_pvt *p;
+        char name[256] = "";
+       char tmp[256];
+       char tmp2[256] = "";
+       char clen[20] = "";
+        char iabuf[INET_ADDRSTRLEN];
+       int rebootfile, len;
+
+
+       if (argc < 4) {
+               return RESULT_SHOWUSAGE;
+       }
+
+       /* Get peer, filename, deleteoption */
+       peername = argv[2];
+       filename = argv[3];
+       if (argc == 5)
+               if (strcasecmp(argv[4], "delete"))
+                       deletefileafternotify = 1;
+
+       /* Find peer */
+       ast_mutex_lock(&peerl.lock);
+       peer = find_peer(peername, NULL);
+
+       ast_mutex_unlock(&peerl.lock);
+
+       if (!peer) {
+               ast_cli(fd, "GSNotify: Unable to find  PEER %s\n", peername);
+               return -1;
+       }
+
+       if ((rebootfile = open(filename, O_RDONLY)) < 0) {
+               ast_cli(fd, "GSNotify: Unable to open file %s\n", filename);
+               return -1;
+       }
+
+       /* It's only 24 bytes, so we should be able to read it in one read */
+       len = read(rebootfile, tmp, sizeof(tmp));
+       if (len < 0) {
+               ast_cli (fd, "GSNotify: Read failed on file %s\n", filename);
+               close(rebootfile);
+               ast_mutex_unlock(&peerl.lock);
+               return -1;
+
+               }
+       close(rebootfile);
+       if (deletefileafternotify)
+               unlink(filename);
+
+       /* Allocate SIP packet */
+       p = sip_alloc(NULL, NULL, 0);
+        if (!p) {
+               ast_log(LOG_WARNING, "Unable to build sip pvt data for GSNotify\n");
+               return -1;
+        }
+
+       /* Get peer name */
+        strncpy(name, peer->name, sizeof(name) - 1);
+
+
+       /* Notify to full contact */
+        ast_log(LOG_DEBUG, "GSNOTIFY: Checking if  %s is available? \n", peer->name);
+
+        if (create_addr(p, name) ){
+                /* Maybe they're not registered, etc. */
+               ast_cli(fd, "SIP GSNOTIFY: %s is not available. (Unreachable, not registred) \n", name);
+                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 (p->nat != SIP_NAT_NEVER)
+                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 /* Avoid RPORT */
+                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);
+
+        /* Send NOTIFY */
+        p->outgoing = 1;
+
+        sip_scheddestroy(p, 15000);
+
+        initreqprep(&req, p, "NOTIFY", NULL);
+        add_header(&req, "Event", "sys-control");
+        add_header(&req, "Content-Type", "application/octet-stream");
+
+        snprintf(clen, sizeof(clen), "%d", (int)strlen(tmp));
+
+       /* READ FILE HERE */
+        add_header(&req, "Content-Length", clen);
+        add_line(&req, tmp);
+
+        return send_request(p, &req, 1, p->ocseq);
+
+}
+#endif
+
 /*--- sip_show_inuse: CLI Command to show calls within limits set by
       outgoinglimit and incominglimit ---*/
 static int sip_show_inuse(int fd, int argc, char *argv[]) {
@@ -6393,6 +6518,20 @@
        { { "sip", "no", "history", NULL }, sip_no_history, "Disable SIP history", no_history_usage };
 static struct ast_cli_entry  cli_no_debug =
        { { "sip", "no", "debug", NULL }, sip_no_debug, "Disable SIP debugging", no_debug_usage };
+#ifdef SIPGSNOTIFY
+
+/* Forward declaration */
+static int sip_gsnotify(int fd, int argc, char *argv[]);
+
+static char sip_gsnotify_usage[] =
+"Usage: sip gsnotify  <peername> <filename> [delete]\n"
+"       Send special NOTIFY message to Grandstream phone to force reboot\n"
+"       (Requires knowledge on GS admin kit \n";
+
+static struct ast_cli_entry  cli_gsnotify =
+       { { "sip", "gsnotify", NULL }, sip_gsnotify, "Send reboot notify to grandstream IP Phone", sip_gsnotify_usage };
+
+#endif

 static int sip_poke_peer_s(void *data)
 {
@@ -8928,7 +9067,8 @@
                ast_cli_register(&cli_no_history);
                ast_cli_register(&cli_sip_reload);
                ast_cli_register(&cli_inuse_show);
-               sip_rtp.type = type;
+               ast_cli_register(&cli_gsnotify);
+               sip_rtp.type = type;
                ast_rtp_proto_register(&sip_rtp);
                ast_register_application(app_dtmfmode, sip_dtmfmode, synopsis_dtmfmode, descrip_dtmfmode);
                ast_mutex_lock(&peerl.lock);
