jabberd2
2.2.16
|
00001 /* vim: set noet ts=4 sw=4: */ 00002 /* 00003 * jabberd - Jabber Open Source Server 00004 * Copyright (c) 2009 Tomasz Sterna 00005 * 00006 * This program is free software; you can redistribute it and/or modify 00007 * it under the terms of the GNU General Public License as published by 00008 * the Free Software Foundation; either version 2 of the License, or 00009 * (at your option) any later version. 00010 * 00011 * This program is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 * GNU General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU General Public License 00017 * along with this program; if not, write to the Free Software 00018 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA02111-1307USA 00019 */ 00020 00037 #include "c2s.h" 00038 00039 static int _pbx_command_part_len(char *cmd) 00040 { 00041 int i; 00042 for(i=0; *cmd != ' ' && *cmd != '\t' && *cmd != '\n' && *cmd != '\0'; cmd++, i++); 00043 return i; 00044 } 00045 00046 static nad_t _pbx_presence_nad(int available, char *cmd) 00047 { 00048 nad_t nad; 00049 int ns; 00050 char *show = NULL; 00051 00052 nad = nad_new(); 00053 ns = nad_add_namespace(nad, uri_CLIENT, NULL); 00054 nad_append_elem(nad, ns, "presence", 0); 00055 00056 if(!available) { 00057 nad_append_attr(nad, -1, "type", "unavailable"); 00058 } 00059 else { 00060 char *cont; 00061 long int priority; 00062 char prioritystr[5]; // -128 to +127 + \0 00063 00064 priority = strtol(cmd, &cont, 10); 00065 log_debug(ZONE, "Read %ld priority", priority); 00066 if(cmd == cont) priority = -1; // use -1 priority if not given 00067 if(priority < -128) priority = -128; 00068 if(priority > 127) priority = 127; 00069 nad_append_elem(nad, -1, "priority", 1); 00070 snprintf(prioritystr, 5, "%ld", priority); 00071 nad_append_cdata(nad, prioritystr, strlen(prioritystr), 2); 00072 if(cmd != cont) { 00073 cmd = cont; 00074 while(*cmd == ' ') { cmd++; } 00075 } 00076 00077 00078 if(!strncmp("CHAT", cmd, 4)) { 00079 cmd += 4; 00080 show = "chat"; 00081 } 00082 if(!strncmp("ONLINE", cmd, 6)) { 00083 cmd += 6; 00084 } 00085 if(!strncmp("DND", cmd, 3)) { 00086 cmd += 3; 00087 show = "dnd"; 00088 } 00089 if(!strncmp("AWAY", cmd, 4)) { 00090 cmd += 4; 00091 show = "away"; 00092 } 00093 if(!strncmp("XA", cmd, 2)) { 00094 cmd += 2; 00095 show = "xa"; 00096 } 00097 if(show) { 00098 nad_append_elem(nad, -1, "show", 1); 00099 nad_append_cdata(nad, show, strlen(show), 2); 00100 } 00101 } 00102 00103 while(*cmd == ' ') { cmd++; } 00104 00105 if(*cmd != '\0' && *cmd != '\n') { 00106 int len = strlen(cmd); 00107 nad_append_elem(nad, -1, "status", 1); 00108 nad_append_cdata(nad, cmd, len - (cmd[len-1] == '\n' ? 1 : 0), 2); 00109 } 00110 00111 return nad; 00112 } 00113 00118 int _pbx_process_command(c2s_t c2s, char *cmd) 00119 { 00120 jid_t jid; 00121 int action = 0, len; 00122 sess_t sess; 00123 unsigned char hashbuf[44] = "PBX"; 00124 unsigned char *sesshash; 00125 00126 sesshash = hashbuf+3; 00127 00128 /* get command */ 00129 if(!strncasecmp("START ", cmd, 6)) { 00130 cmd += 6; 00131 action = 1; 00132 } 00133 if(!strncasecmp("STOP ", cmd, 5)) { 00134 cmd += 5; 00135 action = 2; 00136 } 00137 if(action != 0) { 00138 len = _pbx_command_part_len(cmd); 00139 if(len > 0) { 00140 jid = jid_new(cmd, len); 00141 if(jid) { 00142 cmd += len; 00143 if(*cmd != '\0') cmd++; 00144 00145 shahash_r(jid_full(jid), sesshash); 00146 sess = xhash_get(c2s->sessions, hashbuf); 00147 00148 switch(action) { 00149 case 1: 00150 log_debug(ZONE, "STARTing session for %s/%s (%s) with commandline: %s", jid_user(jid), jid->resource, hashbuf, cmd); 00151 00152 if(sess == NULL) { 00153 /* create new session */ 00154 sess = (sess_t) calloc(1, sizeof(struct sess_st)); 00155 sess->c2s = c2s; 00156 sess->last_activity = time(NULL); 00157 /* put into sessions hash */ 00158 snprintf(sess->skey, sizeof(sess->skey), "%s", hashbuf); 00159 xhash_put(c2s->sessions, sess->skey, (void *) sess); 00160 /* generate bound resource */ 00161 sess->resources = (bres_t) calloc(1, sizeof(struct bres_st)); 00162 snprintf(sess->resources->c2s_id, sizeof(sess->resources->c2s_id), "%s", hashbuf); 00163 sess->resources->jid = jid; 00164 /* open SM session */ 00165 log_write(sess->c2s->log, LOG_NOTICE, "[PBX] requesting session: jid=%s", jid_full(jid)); 00166 sm_start(sess, sess->resources); 00167 00168 /* generate presence packet to get session online */ 00169 /* a bit hacky, but we need to emulate _some_ of the client behavior */ 00170 sess->result = _pbx_presence_nad(1, cmd); 00171 } 00172 else { 00173 /* just send the presence */ 00174 sm_packet(sess, sess->resources, _pbx_presence_nad(1, cmd)); 00175 } 00176 00177 break; 00178 00179 case 2: 00180 log_debug(ZONE, "STOPping session for %s/%s with commandline: %s", jid_user(jid), jid->resource, cmd); 00181 00182 if(sess != NULL) { 00183 /* send unavailable presence */ 00184 sm_packet(sess, sess->resources, _pbx_presence_nad(0, cmd)); 00185 /* end the session */ 00186 sm_end(sess, sess->resources); 00187 xhash_zap(c2s->sessions, sess->skey); 00188 jqueue_push(c2s->dead_sess, (void *) sess, 0); 00189 } 00190 00191 break; 00192 } 00193 00194 /* TODO: respond with "OK", return 0 */ 00195 return -1; 00196 } 00197 } 00198 /* TODO: generate "ERR" response, return 0 */ 00199 return -1; 00200 } 00201 if(!strncasecmp("STATUS", cmd, 6)) { 00202 log_write(c2s->log, LOG_INFO, "STATUS PBX command not implemented yet"); 00203 return -1; 00204 } 00205 return -1; 00206 }