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 00024 void _sx_process_read(sx_t s, sx_buf_t buf) { 00025 sx_error_t sxe; 00026 nad_t nad; 00027 char *errstring; 00028 int i; 00029 int ns, elem; 00030 00031 /* Note that buf->len can validly be 0 here, if we got data from 00032 the socket but the plugin didn't return anything to us (e.g. a 00033 SSL packet was split across a tcp segment boundary) */ 00034 00035 /* count bytes read */ 00036 s->rbytes += buf->len; 00037 00038 /* parse it */ 00039 if(XML_Parse(s->expat, buf->data, buf->len, 0) == 0) { 00040 /* only report error we haven't already */ 00041 if(!s->fail) { 00042 /* parse error */ 00043 errstring = (char *) XML_ErrorString(XML_GetErrorCode(s->expat)); 00044 00045 _sx_debug(ZONE, "XML parse error: %s; line: %d, column: %d", errstring, XML_GetCurrentLineNumber(s->expat), XML_GetCurrentColumnNumber(s->expat)); 00046 _sx_gen_error(sxe, SX_ERR_XML_PARSE, "XML parse error", errstring); 00047 _sx_event(s, event_ERROR, (void *) &sxe); 00048 00049 _sx_error(s, stream_err_XML_NOT_WELL_FORMED, errstring); 00050 _sx_close(s); 00051 00052 _sx_buffer_free(buf); 00053 00054 return; 00055 } 00056 00057 /* !!! is this the right thing to do? we should probably set 00058 * s->fail and let the code further down handle it. */ 00059 _sx_buffer_free(buf); 00060 00061 return; 00062 } 00063 00064 /* check if the stanza size limit is exceeded (it wasn't reset by parser) */ 00065 if(s->rbytesmax && s->rbytes > s->rbytesmax) { 00066 /* parse error */ 00067 _sx_debug(ZONE, "maximum stanza size (%d) exceeded by reading %d bytes", s->rbytesmax, s->rbytes); 00068 00069 errstring = (char *) XML_ErrorString(XML_GetErrorCode(s->expat)); 00070 00071 _sx_gen_error(sxe, SX_ERR_XML_PARSE, "stream read error", "Maximum stanza size exceeded"); 00072 _sx_event(s, event_ERROR, (void *) &sxe); 00073 00074 _sx_error(s, stream_err_POLICY_VIOLATION, errstring); 00075 _sx_close(s); 00076 00077 _sx_buffer_free(buf); 00078 00079 return; 00080 } 00081 00082 /* done with the buffer */ 00083 _sx_buffer_free(buf); 00084 00085 /* process completed nads */ 00086 if(s->state >= state_STREAM) 00087 while((nad = jqueue_pull(s->rnadq)) != NULL) { 00088 int plugin_error; 00089 #ifdef SX_DEBUG 00090 char *out; int len; 00091 nad_print(nad, 0, &out, &len); 00092 _sx_debug(ZONE, "completed nad: %.*s", len, out); 00093 #endif 00094 00095 /* check for errors */ 00096 if(NAD_ENS(nad, 0) >= 0 && NAD_NURI_L(nad, NAD_ENS(nad, 0)) == strlen(uri_STREAMS) && strncmp(NAD_NURI(nad, NAD_ENS(nad, 0)), uri_STREAMS, strlen(uri_STREAMS)) == 0 && NAD_ENAME_L(nad, 0) == 5 && strncmp(NAD_ENAME(nad, 0), "error", 5) == 0) { 00097 00098 errstring = NULL; 00099 00100 /* get text error description if available - XMPP 4.7.2 */ 00101 if((ns = nad_find_scoped_namespace(nad, uri_STREAM_ERR, NULL)) >= 0) 00102 if((elem = nad_find_elem(nad, 0, ns, "text", 1)) >= 0) 00103 if(NAD_CDATA_L(nad, elem) > 0) { 00104 errstring = (char *) malloc(sizeof(char) * (NAD_CDATA_L(nad, elem) + 1)); 00105 sprintf(errstring, "%.*s", NAD_CDATA_L(nad, elem), NAD_CDATA(nad, elem)); 00106 } 00107 00108 /* if not available, look for legacy error text as in <stream:error>description</stream:error> */ 00109 if (errstring == NULL && NAD_CDATA_L(nad, 0) > 0) { 00110 errstring = (char *) malloc(sizeof(char) * (NAD_CDATA_L(nad, 0) + 1)); 00111 sprintf(errstring, "%.*s", NAD_CDATA_L(nad, 0), NAD_CDATA(nad, 0)); 00112 } 00113 00114 /* if not available, log the whole packet for debugging */ 00115 if (errstring == NULL) { 00116 char *xml; 00117 int xlen; 00118 00119 nad_print(nad, 0, &xml, &xlen); 00120 errstring = (char *) malloc(sizeof(char) * (xlen + 1)); 00121 sprintf(errstring, "%.*s", xlen, xml); 00122 } 00123 00124 if(s->state < state_CLOSING) { 00125 _sx_gen_error(sxe, SX_ERR_STREAM, "Stream error", errstring); 00126 _sx_event(s, event_ERROR, (void *) &sxe); 00127 _sx_state(s, state_CLOSING); 00128 } 00129 00130 if(errstring != NULL) free(errstring); 00131 00132 nad_free(nad); 00133 00134 break; 00135 } 00136 00137 /* run it by the plugins */ 00138 if(_sx_chain_nad_read(s, nad) == 0) 00139 return; 00140 00141 /* now let the plugins process the completed nad */ 00142 plugin_error = 0; 00143 if(s->env != NULL) 00144 for(i = 0; i < s->env->nplugins; i++) 00145 if(s->env->plugins[i]->process != NULL) { 00146 int plugin_ret; 00147 plugin_ret = (s->env->plugins[i]->process)(s, s->env->plugins[i], nad); 00148 if(plugin_ret == 0) { 00149 plugin_error ++; 00150 break; 00151 } 00152 } 00153 00154 /* hand it to the app */ 00155 if ((plugin_error == 0) && (s->state < state_CLOSING)) 00156 _sx_event(s, event_PACKET, (void *) nad); 00157 } 00158 00159 /* something went wrong, bail */ 00160 if(s->fail) { 00161 _sx_close(s); 00162 00163 return; 00164 } 00165 00166 /* stream was closed */ 00167 if(s->depth < 0 && s->state < state_CLOSING) { 00168 /* close the stream if necessary */ 00169 if(s->state >= state_STREAM_SENT) { 00170 jqueue_push(s->wbufq, _sx_buffer_new("</stream:stream>", 16, NULL, NULL), 0); 00171 s->want_write = 1; 00172 } 00173 00174 _sx_state(s, state_CLOSING); 00175 00176 return; 00177 } 00178 } 00179 00181 int sx_can_read(sx_t s) { 00182 sx_buf_t in, out; 00183 int read, ret; 00184 00185 assert((int) (s != NULL)); 00186 00187 /* do we care? */ 00188 if(!s->want_read && s->state < state_CLOSING) 00189 return 0; /* no more thanks */ 00190 00191 _sx_debug(ZONE, "%d ready for reading", s->tag); 00192 00193 /* new buffer */ 00194 in = _sx_buffer_new(NULL, 1024, NULL, NULL); 00195 00196 /* get them to read stuff */ 00197 read = _sx_event(s, event_READ, (void *) in); 00198 00199 /* bail if something went wrong */ 00200 if(read < 0) { 00201 _sx_buffer_free(in); 00202 s->want_read = 0; 00203 s->want_write = 0; 00204 return 0; 00205 } 00206 00207 if(read == 0) { 00208 /* nothing to read 00209 * should never happen because we did get a read event, 00210 * thus there is something to read, or error handled 00211 * via (read < 0) block before (errors return -1) */ 00212 _sx_debug(ZONE, "decoded 0 bytes read data - this should not happen"); 00213 _sx_buffer_free(in); 00214 00215 } else { 00216 _sx_debug(ZONE, "passed %d read bytes", in->len); 00217 00218 /* make a copy for processing */ 00219 out = _sx_buffer_new(in->data, in->len, in->notify, in->notify_arg); 00220 00221 /* run it by the plugins */ 00222 ret = _sx_chain_io_read(s, out); 00223 if(ret <= 0) { 00224 if(ret < 0) { 00225 /* permanent failure, its all over */ 00226 /* !!! shut down */ 00227 s->want_read = s->want_write = 0; 00228 } 00229 00230 _sx_buffer_free(in); 00231 _sx_buffer_free(out); 00232 00233 /* done */ 00234 if(s->want_write) _sx_event(s, event_WANT_WRITE, NULL); 00235 return s->want_read; 00236 } 00237 00238 _sx_buffer_free(in); 00239 00240 _sx_debug(ZONE, "decoded read data (%d bytes): %.*s", out->len, out->len, out->data); 00241 00242 /* into the parser with you */ 00243 _sx_process_read(s, out); 00244 } 00245 00246 /* if we've written everything, and we're closed, then inform the app it can kill us */ 00247 if(s->want_write == 0 && s->state == state_CLOSING) { 00248 _sx_state(s, state_CLOSED); 00249 _sx_event(s, event_CLOSED, NULL); 00250 return 0; 00251 } 00252 00253 if(s->state == state_CLOSED) 00254 return 0; 00255 00256 if(s->want_write) _sx_event(s, event_WANT_WRITE, NULL); 00257 return s->want_read; 00258 } 00259 00261 static int _sx_get_pending_write(sx_t s) { 00262 sx_buf_t in, out; 00263 int ret; 00264 00265 assert(s != NULL); 00266 00267 if (s->wbufpending != NULL) { 00268 /* there's already a pending buffer ready to write */ 00269 return 0; 00270 } 00271 00272 /* get the first buffer off the queue */ 00273 in = jqueue_pull(s->wbufq); 00274 if(in == NULL) { 00275 /* if there was a write event, and something is interested, 00276 we still have to tell the plugins */ 00277 in = _sx_buffer_new(NULL, 0, NULL, NULL); 00278 } 00279 00280 /* if there's more to write, we want to make sure we get it */ 00281 s->want_write = jqueue_size(s->wbufq); 00282 00283 /* make a copy for processing */ 00284 out = _sx_buffer_new(in->data, in->len, in->notify, in->notify_arg); 00285 00286 _sx_debug(ZONE, "encoding %d bytes for writing: %.*s", in->len, in->len, in->data); 00287 00288 /* run it by the plugins */ 00289 ret = _sx_chain_io_write(s, out); 00290 if(ret <= 0) { 00291 /* TODO/!!!: Are we leaking the 'out' buffer here? How about the 'in' buffer? */ 00292 if(ret == -1) { 00293 /* temporary failure, push it back on the queue */ 00294 jqueue_push(s->wbufq, in, (s->wbufq->front != NULL) ? s->wbufq->front->priority : 0); 00295 s->want_write = 1; 00296 } else if(ret == -2) { 00297 /* permanent failure, its all over */ 00298 /* !!! shut down */ 00299 s->want_read = s->want_write = 0; 00300 return -1; 00301 } 00302 00303 /* done */ 00304 return 0; 00305 } 00306 00307 _sx_buffer_free(in); 00308 00309 if (out->len == 0) 00310 /* if there's nothing to write, then we're done */ 00311 _sx_buffer_free(out); 00312 else 00313 s->wbufpending = out; 00314 00315 return 0; 00316 } 00317 00318 int sx_can_write(sx_t s) { 00319 sx_buf_t out; 00320 int ret, written; 00321 00322 assert((int) (s != NULL)); 00323 00324 /* do we care? */ 00325 if(!s->want_write && s->state < state_CLOSING) 00326 return 0; /* no more thanks */ 00327 00328 _sx_debug(ZONE, "%d ready for writing", s->tag); 00329 00330 ret = _sx_get_pending_write(s); 00331 if (ret < 0) { 00332 /* fatal error */ 00333 _sx_debug(ZONE, "fatal error after attempt to write on fd %d", s->tag); 00334 /* permanent error so inform the app it can kill us */ 00335 sx_kill(s); 00336 return 0; 00337 } 00338 00339 /* if there's nothing to write, then we're done */ 00340 if(s->wbufpending == NULL) { 00341 if(s->want_read) _sx_event(s, event_WANT_READ, NULL); 00342 return s->want_write; 00343 } 00344 00345 out = s->wbufpending; 00346 s->wbufpending = NULL; 00347 00348 /* get the callback to do the write */ 00349 _sx_debug(ZONE, "handing app %d bytes to write", out->len); 00350 written = _sx_event(s, event_WRITE, (void *) out); 00351 00352 if(written < 0) { 00353 /* bail if something went wrong */ 00354 _sx_buffer_free(out); 00355 s->want_read = 0; 00356 s->want_write = 0; 00357 return 0; 00358 } else if(written < out->len) { 00359 /* if not fully written, this buffer is still pending */ 00360 out->len -= written; 00361 out->data += written; 00362 s->wbufpending = out; 00363 s->want_write ++; 00364 } else { 00365 /* notify */ 00366 if(out->notify != NULL) 00367 (out->notify)(s, out->notify_arg); 00368 00369 /* done with this */ 00370 _sx_buffer_free(out); 00371 } 00372 00373 /* if we've written everything, and we're closed, then inform the app it can kill us */ 00374 if(s->want_write == 0 && s->state == state_CLOSING) { 00375 _sx_state(s, state_CLOSED); 00376 _sx_event(s, event_CLOSED, NULL); 00377 return 0; 00378 } 00379 00380 if(s->state == state_CLOSED) 00381 return 0; 00382 00383 if(s->want_read) _sx_event(s, event_WANT_READ, NULL); 00384 return s->want_write; 00385 } 00386 00388 int _sx_nad_write(sx_t s, nad_t nad, int elem) { 00389 char *out; 00390 int len; 00391 00392 /* silently drop it if we're closing or closed */ 00393 if(s->state >= state_CLOSING) { 00394 log_debug(ZONE, "stream closed, dropping outgoing packet"); 00395 nad_free(nad); 00396 return 1; 00397 } 00398 00399 /* run it through the plugins */ 00400 if(_sx_chain_nad_write(s, nad, elem) == 0) 00401 return 1; 00402 00403 /* serialise it */ 00404 nad_print(nad, elem, &out, &len); 00405 00406 _sx_debug(ZONE, "queueing for write: %.*s", len, out); 00407 00408 /* ready to go */ 00409 jqueue_push(s->wbufq, _sx_buffer_new(out, len, NULL, NULL), 0); 00410 00411 nad_free(nad); 00412 00413 /* things to write */ 00414 s->want_write = 1; 00415 00416 return 0; 00417 } 00418 00420 void sx_nad_write_elem(sx_t s, nad_t nad, int elem) { 00421 assert((int) (s != NULL)); 00422 assert((int) (nad != NULL)); 00423 00424 if(_sx_nad_write(s, nad, elem) == 1) 00425 return; 00426 00427 /* things to write */ 00428 s->want_write = 1; 00429 _sx_event(s, event_WANT_WRITE, NULL); 00430 00431 if(s->want_read) _sx_event(s, event_WANT_READ, NULL); 00432 } 00433 00435 int _sx_raw_write(sx_t s, char *buf, int len) { 00436 /* siltently drop it if we're closing or closed */ 00437 if(s->state >= state_CLOSING) { 00438 log_debug(ZONE, "stream closed, dropping outgoing raw data"); 00439 return 1; 00440 } 00441 00442 _sx_debug(ZONE, "queuing for write: %.*s", len, buf); 00443 00444 /* ready to go */ 00445 jqueue_push(s->wbufq, _sx_buffer_new(buf, len, NULL, NULL), 0); 00446 00447 /* things to write */ 00448 s->want_write = 1; 00449 00450 return 0; 00451 } 00452 00454 void sx_raw_write(sx_t s, char *buf, int len) { 00455 assert((int) (s != NULL)); 00456 assert((int) (buf != NULL)); 00457 assert(len); 00458 00459 if(_sx_raw_write(s, buf, len) == 1) 00460 return; 00461 00462 /* things to write */ 00463 s->want_write = 1; 00464 _sx_event(s, event_WANT_WRITE, NULL); 00465 00466 if(s->want_read) _sx_event(s, event_WANT_READ, NULL); 00467 } 00468 00470 void _sx_close(sx_t s) { 00471 /* close the stream if necessary */ 00472 if(s->state >= state_STREAM_SENT) { 00473 jqueue_push(s->wbufq, _sx_buffer_new("</stream:stream>", 16, NULL, NULL), 0); 00474 s->want_write = 1; 00475 } 00476 00477 _sx_state(s, state_CLOSING); 00478 } 00479 00480 void sx_close(sx_t s) { 00481 assert((int) (s != NULL)); 00482 00483 if(s->state >= state_CLOSING) 00484 return; 00485 00486 if(s->state >= state_STREAM_SENT && s->state < state_CLOSING) { 00487 _sx_close(s); 00488 _sx_event(s, event_WANT_WRITE, NULL); 00489 } else { 00490 _sx_state(s, state_CLOSED); 00491 _sx_event(s, event_CLOSED, NULL); 00492 } 00493 } 00494 00495 void sx_kill(sx_t s) { 00496 assert((int) (s != NULL)); 00497 00498 _sx_state(s, state_CLOSED); 00499 _sx_event(s, event_CLOSED, NULL); 00500 }