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