jabberd2
2.2.16
|
00001 /* 00002 * jabberd - Jabber Open Source Server 00003 * Copyright (c) 2002 Jeremie Miller, Thomas Muldowney, 00004 * Ryan Eatmon, Robert Norris 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 00021 #include "sx.h" 00022 00023 static void _sx_client_element_start(void *arg, const char *name, const char **atts) { 00024 sx_t s = (sx_t) arg; 00025 int tflag = 0, fflag = 0, vflag = 0, iflag = 0, i; 00026 const char **attr; 00027 sx_error_t sxe; 00028 00029 if(s->fail) return; 00030 00031 /* check element and namespace */ 00032 i = strlen(uri_STREAMS) + 7; 00033 if(strlen(name) < i || strncmp(name, uri_STREAMS "|stream", i) != 0 || (name[i] != '\0' && name[i] != '|')) { 00034 /* throw an error */ 00035 _sx_gen_error(sxe, SX_ERR_STREAM, "Stream error", "Expected stream start"); 00036 _sx_event(s, event_ERROR, (void *) &sxe); 00037 _sx_error(s, stream_err_BAD_FORMAT, NULL); 00038 s->fail = 1; 00039 return; 00040 } 00041 00042 /* pull interesting things out of the header */ 00043 attr = atts; 00044 while(attr[0] != NULL) { 00045 if(!tflag && strcmp(attr[0], "to") == 0) { 00046 s->res_to = strdup(attr[1]); 00047 tflag = 1; 00048 } 00049 00050 if(!fflag && strcmp(attr[0], "from") == 0) { 00051 s->res_from = strdup(attr[1]); 00052 fflag = 1; 00053 } 00054 00055 if(!vflag && strcmp(attr[0], "version") == 0) { 00056 s->res_version = strdup(attr[1]); 00057 vflag = 1; 00058 } 00059 00060 if(!iflag && strcmp(attr[0], "id") == 0) { 00061 s->id = strdup(attr[1]); 00062 iflag = 1; 00063 } 00064 00065 attr += 2; 00066 } 00067 00068 s->depth++; 00069 00070 _sx_debug(ZONE, "stream response: to %s from %s version %s id %s", s->res_to, s->res_from, s->res_version, s->id); 00071 00072 /* we're alive */ 00073 XML_SetElementHandler(s->expat, (void *) _sx_element_start, (void *) _sx_element_end); 00074 XML_SetCharacterDataHandler(s->expat, (void *) _sx_cdata); 00075 XML_SetStartNamespaceDeclHandler(s->expat, (void *) _sx_namespace_start); 00076 00077 /* get the plugins to setup */ 00078 if(s->env != NULL) 00079 for(i = 0; i < s->env->nplugins; i++) 00080 if(s->env->plugins[i]->stream != NULL) 00081 (s->env->plugins[i]->stream)(s, s->env->plugins[i]); 00082 00083 /* bump us to stream if a plugin didn't do it already */ 00084 if(s->state < state_STREAM) { 00085 _sx_state(s, state_STREAM); 00086 _sx_event(s, event_STREAM, NULL); 00087 } 00088 } 00089 00090 static void _sx_client_element_end(void *arg, const char *name) { 00091 sx_t s = (sx_t) arg; 00092 00093 if(s->fail) return; 00094 00095 s->depth--; 00096 } 00097 00098 static void _sx_client_notify_header(sx_t s, void *arg) { 00099 /* expat callbacks */ 00100 XML_SetElementHandler(s->expat, (void *) _sx_client_element_start, (void *) _sx_client_element_end); 00101 00102 /* state change */ 00103 _sx_state(s, state_STREAM_SENT); 00104 00105 _sx_debug(ZONE, "stream header sent, waiting for reply"); 00106 00107 /* waiting for a response */ 00108 s->want_read = 1; 00109 } 00110 00111 void sx_client_init(sx_t s, unsigned int flags, char *ns, char *to, char *from, char *version) { 00112 sx_buf_t buf; 00113 char *c; 00114 int i, len; 00115 00116 assert((int) (s != NULL)); 00117 00118 /* can't do anything if we're alive already */ 00119 if(s->state != state_NONE) 00120 return; 00121 00122 _sx_debug(ZONE, "doing client init for sx %d", s->tag); 00123 00124 s->type = type_CLIENT; 00125 s->flags = flags; 00126 00127 if(ns != NULL) s->ns = strdup(ns); 00128 if(to != NULL) s->req_to = strdup(to); 00129 if(from != NULL) s->req_from = strdup(from); 00130 if(version != NULL) s->req_version = strdup(version); 00131 00132 /* plugin */ 00133 if(s->env != NULL) 00134 for(i = 0; i < s->env->nplugins; i++) 00135 if(s->env->plugins[i]->client != NULL) 00136 (s->env->plugins[i]->client)(s, s->env->plugins[i]); 00137 00138 _sx_debug(ZONE, "stream request: ns %s to %s from %s version %s", ns, to, from, version); 00139 00140 /* build the stream start */ 00141 len = strlen(uri_STREAMS) + 52; 00142 00143 if(ns != NULL) len += 9 + strlen(ns); 00144 if(to != NULL) len += 6 + strlen(to); 00145 if(from != NULL) len += 8 + strlen(from); 00146 if(version != NULL) len += 11 + strlen(version); 00147 00148 buf = _sx_buffer_new(NULL, len+1, _sx_client_notify_header, NULL); 00149 c = buf->data; 00150 strcpy(c, "<?xml version='1.0'?><stream:stream xmlns:stream='" uri_STREAMS "'"); 00151 00152 if(ns != NULL) { c = strchr(c, '\0'); sprintf(c, " xmlns='%s'", ns); } 00153 if(to != NULL) { c = strchr(c, '\0'); sprintf(c, " to='%s'", to); } 00154 if(from != NULL) { c = strchr(c, '\0'); sprintf(c, " from='%s'", from); } 00155 if(version != NULL) { c = strchr(c, '\0'); sprintf(c, " version='%s'", version); } 00156 00157 c = strchr(c, '\0'); sprintf(c, ">"); 00158 00159 assert(buf->len == strlen(buf->data)+1); 00160 buf->len --; 00161 00162 /* plugins can mess with the header too */ 00163 if(s->env != NULL) 00164 for(i = 0; i < s->env->nplugins; i++) 00165 if(s->env->plugins[i]->header != NULL) 00166 (s->env->plugins[i]->header)(s, s->env->plugins[i], buf); 00167 00168 _sx_debug(ZONE, "prepared stream header: %.*s", buf->len, buf->data); 00169 00170 /* off it goes */ 00171 jqueue_push(s->wbufq, buf, 0); 00172 00173 /* we have stuff to write */ 00174 s->want_write = 1; 00175 _sx_event(s, event_WANT_WRITE, NULL); 00176 } 00177