00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046 #include <stdio.h>
00047 #include <stdlib.h>
00048 #include <errno.h>
00049 #include <string.h>
00050
00051 #include "../../sr_module.h"
00052 #include "../../cfg/cfg_struct.h"
00053
00054 #include "xmpp.h"
00055 #include "xmpp_api.h"
00056 #include "network.h"
00057 #include "xode.h"
00058
00059 struct xmpp_private_data {
00060 int fd;
00061 int running;
00062 };
00063
00064 static int xode_send(int fd, xode x)
00065 {
00066 char *str = xode_to_str(x);
00067 int len = strlen(str);
00068
00069 LM_DBG("xode_send [%s]\n", str);
00070
00071 if (net_send(fd, str, len) != len) {
00072 LM_ERR("send() error: %s\n", strerror(errno));
00073 return -1;
00074 }
00075
00076 return len;
00077 }
00078
00079 static void stream_node_callback(int type, xode node, void *arg)
00080 {
00081 struct xmpp_private_data *priv = (struct xmpp_private_data *) arg;
00082 char *id, *hash, *tag;
00083 char buf[4096];
00084 xode x;
00085
00086 LM_DBG("stream callback: %d: %s\n", type, node ? xode_get_name(node) : "n/a");
00087 switch (type) {
00088 case XODE_STREAM_ROOT:
00089 id = xode_get_attrib(node, "id");
00090 snprintf(buf, sizeof(buf), "%s%s", id, xmpp_password);
00091 hash = shahash(buf);
00092
00093 x = xode_new_tag("handshake");
00094 xode_insert_cdata(x, hash, -1);
00095 xode_send(priv->fd, x);
00096 xode_free(x);
00097 break;
00098 case XODE_STREAM_NODE:
00099 tag = xode_get_name(node);
00100 if (!strcmp(tag, "handshake")) {
00101 LM_DBG("handshake succeeded\n");
00102 } else if (!strcmp(tag, "message")) {
00103 LM_DBG("XMPP IM received\n");
00104 char *from = xode_get_attrib(node, "from");
00105 char *to = xode_get_attrib(node, "to");
00106 char *type = xode_get_attrib(node, "type");
00107 xode body = xode_get_tag(node, "body");
00108 char *msg;
00109
00110 if (!type)
00111 type = "chat";
00112 if (!strcmp(type, "error")) {
00113 LM_DBG("received message error stanza\n");
00114 goto out;
00115 }
00116
00117 if (!from || !to || !body) {
00118 LM_DBG("invalid <message/> attributes\n");
00119 goto out;
00120 }
00121
00122 if (!(msg = xode_get_data(body)))
00123 msg = "";
00124 xmpp_send_sip_msg(
00125 encode_uri_xmpp_sip(from),
00126 decode_uri_xmpp_sip(to),
00127 msg);
00128 } else if (!strcmp(tag, "presence")) {
00129
00130 LM_DBG("XMPP Presence received\n");
00131 run_xmpp_callbacks(XMPP_RCV_PRESENCE, xode_to_str(node));
00132 }else if (!strcmp(tag, "iq")) {
00133
00134 LM_DBG("XMPP IQ received\n");
00135 run_xmpp_callbacks(XMPP_RCV_IQ, xode_to_str(node));
00136 }
00137 break;
00138 case XODE_STREAM_ERROR:
00139 LM_ERR("stream error\n");
00140
00141 case XODE_STREAM_CLOSE:
00142 priv->running = 0;
00143 break;
00144 }
00145 out:
00146 xode_free(node);
00147 }
00148
00152 static int do_send_message_component(struct xmpp_private_data *priv,
00153 struct xmpp_pipe_cmd *cmd)
00154 {
00155 xode x;
00156
00157 LM_DBG("do_send_message_component from=[%s] to=[%s] body=[%s]\n",
00158 cmd->from, cmd->to, cmd->body);
00159
00160 x = xode_new_tag("message");
00161 xode_put_attrib(x, "id", cmd->id);
00162 xode_put_attrib(x, "from", encode_uri_sip_xmpp(cmd->from));
00163 xode_put_attrib(x, "to", decode_uri_sip_xmpp(cmd->to));
00164 xode_put_attrib(x, "type", "chat");
00165 xode_insert_cdata(xode_insert_tag(x, "body"), cmd->body, -1);
00166
00167 xode_send(priv->fd, x);
00168 xode_free(x);
00169
00170
00171 return 0;
00172 }
00173
00174 static int do_send_bulk_message_component(struct xmpp_private_data *priv,
00175 struct xmpp_pipe_cmd *cmd)
00176 {
00177 int len;
00178
00179 LM_DBG("do_send_bulk_message_component from=[%s] to=[%s] body=[%s]\n",
00180 cmd->from, cmd->to, cmd->body);
00181 len = strlen(cmd->body);
00182 if (net_send(priv->fd, cmd->body, len) != len) {
00183 LM_ERR("do_send_bulk_message_component: %s\n",strerror(errno));
00184 return -1;
00185 }
00186 return 0;
00187 }
00188
00189
00190 int xmpp_component_child_process(int data_pipe)
00191 {
00192 int fd, maxfd, rv;
00193 fd_set fdset;
00194 xode_pool pool;
00195 xode_stream stream;
00196 struct xmpp_private_data priv;
00197 struct xmpp_pipe_cmd *cmd;
00198
00199 while (1) {
00200 fd = net_connect(xmpp_host, xmpp_port);
00201 if (fd < 0) {
00202 sleep(3);
00203 continue;
00204 }
00205
00206 priv.fd = fd;
00207 priv.running = 1;
00208
00209 pool = xode_pool_new();
00210 stream = xode_stream_new(pool, stream_node_callback, &priv);
00211
00212 net_printf(fd,
00213 "<?xml version='1.0'?>"
00214 "<stream:stream xmlns='jabber:component:accept' to='%s' "
00215 "version='1.0' xmlns:stream='http://etherx.jabber.org/streams'>",
00216 xmpp_domain);
00217
00218 while (priv.running) {
00219 FD_ZERO(&fdset);
00220 FD_SET(data_pipe, &fdset);
00221 FD_SET(fd, &fdset);
00222 maxfd = fd > data_pipe ? fd : data_pipe;
00223 rv = select(maxfd + 1, &fdset, NULL, NULL, NULL);
00224
00225
00226 cfg_update();
00227
00228 if (rv < 0) {
00229 LM_ERR("select() failed: %s\n", strerror(errno));
00230 } else if (!rv) {
00231
00232 } else if (FD_ISSET(fd, &fdset)) {
00233 char *buf = net_read_static(fd);
00234
00235 if (!buf)
00236
00237 break;
00238
00239 LM_DBG("server read\n[%s]\n", buf);
00240 xode_stream_eat(stream, buf, strlen(buf));
00241 } else if (FD_ISSET(data_pipe, &fdset)) {
00242 if (read(data_pipe, &cmd, sizeof(cmd)) != sizeof(cmd)) {
00243 LM_ERR("failed to read from command pipe: %s\n",
00244 strerror(errno));
00245 } else {
00246 LM_DBG("got pipe cmd %d\n", cmd->type);
00247 switch (cmd->type) {
00248 case XMPP_PIPE_SEND_MESSAGE:
00249 do_send_message_component(&priv, cmd);
00250 break;
00251 case XMPP_PIPE_SEND_PACKET:
00252 case XMPP_PIPE_SEND_PSUBSCRIBE:
00253 case XMPP_PIPE_SEND_PNOTIFY:
00254 do_send_bulk_message_component(&priv, cmd);
00255 break;
00256 }
00257 xmpp_free_pipe_cmd(cmd);
00258 }
00259 }
00260 }
00261
00262 xode_pool_free(pool);
00263
00264 close(fd);
00265 }
00266 return 0;
00267 }
00268