1 /* 2 * jabberd - Jabber Open Source Server 3 * Copyright (c) 2002 Jeremie Miller, Thomas Muldowney, 4 * Ryan Eatmon, Robert Norris 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; either version 2 of the License, or 9 * (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program; if not, write to the Free Software 18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA02111-1307USA 19 */ 20 21 #ifndef INCL_SX_H 22 #define INCL_SX_H 23 24 #ifdef HAVE_CONFIG_H 25 # include <config.h> 26 #endif 27 28 #include "ac-stdint.h" 29 30 #include <expat.h> 31 #include <util/util.h> 32 33 /* jabberd2 Windows DLL */ 34 #ifndef JABBERD2_API 35 # ifdef _WIN32 36 # ifdef JABBERD2_EXPORTS 37 # define JABBERD2_API __declspec(dllexport) 38 # else /* JABBERD2_EXPORTS */ 39 # define JABBERD2_API __declspec(dllimport) 40 # endif /* JABBERD2_EXPORTS */ 41 # else /* _WIN32 */ 42 # define JABBERD2_API extern 43 # endif /* _WIN32 */ 44 #endif /* JABBERD2_API */ 45 46 #ifdef __cplusplus 47 extern "C" { 48 #endif 49 50 /* forward declarations */ 51 typedef struct _sx_st *sx_t; 52 typedef struct _sx_env_st *sx_env_t; 53 typedef struct _sx_plugin_st *sx_plugin_t; 54 55 /** things that can happen */ 56 typedef enum { 57 event_WANT_READ, /* we want read actions */ 58 event_WANT_WRITE, /* we want write actions */ 59 event_READ, /* read some stuff for me */ 60 event_WRITE, /* write this to the fd */ 61 event_STREAM, /* stream is ready to go */ 62 event_OPEN, /* normal operation */ 63 event_PACKET, /* got a packet */ 64 event_CLOSED, /* its over */ 65 event_ERROR /* something's wrong */ 66 } sx_event_t; 67 68 /** connection states */ 69 typedef enum { 70 state_NONE, /* pre-init */ 71 state_STREAM_RECEIVED, /* stream start received (server) */ 72 state_STREAM_SENT, /* stream start sent (client) */ 73 state_STREAM, /* stream established */ 74 state_OPEN, /* auth completed (normal stream operation) */ 75 state_CLOSING, /* ready to close (send event_CLOSED to app) */ 76 state_CLOSED /* closed (same as NONE, but can't be used any more) */ 77 } _sx_state_t; 78 79 /** connection types */ 80 typedef enum { 81 type_NONE, 82 type_CLIENT, /* we initiated the connection */ 83 type_SERVER /* they initiated */ 84 } _sx_type_t; 85 86 /** event callback */ 87 typedef int (*sx_callback_t)(sx_t s, sx_event_t e, void *data, void *arg); 88 89 /** plugin init */ 90 typedef int (*sx_plugin_init_t)(sx_env_t env, sx_plugin_t p, va_list args); 91 92 /* errors */ 93 #define SX_SUCCESS (0x00) 94 #define SX_ERR_STREAM (0x01) 95 #define SX_ERR_AUTH (0x02) 96 #define SX_ERR_XML_PARSE (0x03) 97 98 /** error info for event_ERROR */ 99 typedef struct _sx_error_st { 100 int code; 101 const char *generic; 102 const char *specific; 103 } sx_error_t; 104 105 /** helper macro to populate this struct */ 106 #define _sx_gen_error(e,c,g,s) do { e.code = c; e.generic = g; e.specific = s; } while(0); 107 108 /** prototype for the write notify function */ 109 typedef void (*_sx_notify_t)(sx_t s, void *arg); 110 111 /** utility: buffer */ 112 typedef struct _sx_buf_st *sx_buf_t; 113 struct _sx_buf_st { 114 char *data; /* pointer to buffer's data */ 115 unsigned int len; /* length of buffer's data */ 116 char *heap; /* beginning of malloc() block containing data, if non-NULL */ 117 118 /* function to call when this buffer gets written */ 119 _sx_notify_t notify; 120 void *notify_arg; 121 }; 122 123 /* stream errors */ 124 #define stream_err_BAD_FORMAT (0) 125 #define stream_err_BAD_NAMESPACE_PREFIX (1) 126 #define stream_err_CONFLICT (2) 127 #define stream_err_CONNECTION_TIMEOUT (3) 128 #define stream_err_HOST_GONE (4) 129 #define stream_err_HOST_UNKNOWN (5) 130 #define stream_err_IMPROPER_ADDRESSING (6) 131 #define stream_err_INTERNAL_SERVER_ERROR (7) 132 #define stream_err_INVALID_FROM (8) 133 #define stream_err_INVALID_ID (9) 134 #define stream_err_INVALID_NAMESPACE (10) 135 #define stream_err_INVALID_XML (11) 136 #define stream_err_NOT_AUTHORIZED (12) 137 #define stream_err_POLICY_VIOLATION (13) 138 #define stream_err_REMOTE_CONNECTION_FAILED (14) 139 #define stream_err_RESTRICTED_XML (15) 140 #define stream_err_RESOURCE_CONSTRAINT (16) 141 #define stream_err_SEE_OTHER_HOST (17) 142 #define stream_err_SYSTEM_SHUTDOWN (18) 143 #define stream_err_UNDEFINED_CONDITION (19) 144 #define stream_err_UNSUPPORTED_ENCODING (20) 145 #define stream_err_UNSUPPORTED_STANZA_TYPE (21) 146 #define stream_err_UNSUPPORTED_VERSION (22) 147 #define stream_err_XML_NOT_WELL_FORMED (23) 148 #define stream_err_LAST (24) 149 /** if you change these, reflect your changes in the table in error.c */ 150 151 /* exported functions */ 152 153 /* make/break */ 154 JABBERD2_API sx_t sx_new(sx_env_t env, int tag, sx_callback_t cb, void *arg); 155 JABBERD2_API void sx_free(sx_t s); 156 157 /* get things ready */ 158 JABBERD2_API void sx_client_init(sx_t s, unsigned int flags, const char *ns, const char *to, const char *from, const char *version); 159 JABBERD2_API void sx_server_init(sx_t s, unsigned int flags); 160 161 /* activity on socket, do stuff! (returns 1 if more read/write actions wanted, 0 otherwise) */ 162 JABBERD2_API int sx_can_read(sx_t s); 163 JABBERD2_API int sx_can_write(sx_t s); 164 165 /** sending a nad */ 166 JABBERD2_API void sx_nad_write_elem(sx_t s, nad_t nad, int elem); 167 #define sx_nad_write(s,nad) sx_nad_write_elem(s, nad, 0) 168 169 /** sending raw data */ 170 JABBERD2_API void sx_raw_write(sx_t s, const char *buf, int len); 171 172 /** authenticate the stream and move to the auth'd state */ 173 JABBERD2_API void sx_auth(sx_t s, const char *auth_method, const char *auth_id); 174 175 /* make/break an environment */ 176 JABBERD2_API sx_env_t sx_env_new(void); 177 JABBERD2_API void sx_env_free(sx_env_t env); 178 179 /** load a plugin into the environment */ 180 JABBERD2_API sx_plugin_t sx_env_plugin(sx_env_t env, sx_plugin_init_t init, ...); 181 182 /* send errors and close stuff */ 183 JABBERD2_API void sx_error(sx_t s, int err, const char *text); 184 JABBERD2_API void sx_error_extended(sx_t s, int err, const char *content); 185 JABBERD2_API void sx_close(sx_t s); 186 JABBERD2_API void sx_kill(sx_t s); 187 188 189 /* helper functions */ 190 JABBERD2_API char* _sx_flags(sx_t s); 191 192 /* primary expat callbacks */ 193 JABBERD2_API void _sx_element_start(void *arg, const char *name, const char **atts); 194 JABBERD2_API void _sx_element_end(void *arg, const char *name); 195 JABBERD2_API void _sx_cdata(void *arg, const char *str, int len); 196 JABBERD2_API void _sx_namespace_start(void *arg, const char *prefix, const char *uri); 197 #ifdef HAVE_XML_STOPPARSER 198 JABBERD2_API void _sx_entity_declaration(void *arg, const char *entityName, 199 int is_parameter_entity, const char *value, 200 int value_length, const char *base, 201 const char *systemId, const char *publicId, 202 const char *notationName); 203 #endif 204 205 /** processor for incoming wire data */ 206 JABBERD2_API void _sx_process_read(sx_t s, sx_buf_t buf); 207 208 /** main nad processor */ 209 JABBERD2_API void _sx_nad_process(sx_t s, nad_t nad); 210 211 /* chain management */ 212 JABBERD2_API void _sx_chain_io_plugin(sx_t s, sx_plugin_t p); 213 JABBERD2_API void _sx_chain_nad_plugin(sx_t s, sx_plugin_t p); 214 215 /* chain running */ 216 JABBERD2_API int _sx_chain_io_write(sx_t s, sx_buf_t buf); 217 JABBERD2_API int _sx_chain_io_read(sx_t s, sx_buf_t buf); 218 219 JABBERD2_API int _sx_chain_nad_write(sx_t s, nad_t nad, int elem); 220 JABBERD2_API int _sx_chain_nad_read(sx_t s, nad_t nad); 221 222 /* buffer utilities */ 223 JABBERD2_API sx_buf_t _sx_buffer_new(const char *data, int len, _sx_notify_t notify, void *notify_arg); 224 JABBERD2_API void _sx_buffer_free(sx_buf_t buf); 225 JABBERD2_API void _sx_buffer_clear(sx_buf_t buf); 226 JABBERD2_API void _sx_buffer_alloc_margin(sx_buf_t buf, int before, int after); 227 JABBERD2_API void _sx_buffer_set(sx_buf_t buf, char *newdata, int newlength, char *newheap); 228 229 /** sending a nad (internal) */ 230 JABBERD2_API int _sx_nad_write(sx_t s, nad_t nad, int elem); 231 232 /** sending raw data (internal) */ 233 JABBERD2_API void sx_raw_write(sx_t s, const char *buf, int len); 234 235 /** reset stream state without informing the app */ 236 JABBERD2_API void _sx_reset(sx_t s); 237 238 /* send errors and close stuff */ 239 JABBERD2_API void _sx_error(sx_t s, int err, const char *text); 240 JABBERD2_API void _sx_error_extended(sx_t s, int err, const char *content); 241 JABBERD2_API void _sx_close(sx_t s); 242 243 /** read/write plugin chain */ 244 typedef struct _sx_chain_st *_sx_chain_t; 245 struct _sx_chain_st { 246 sx_plugin_t p; 247 248 _sx_chain_t wnext; /* -> write */ 249 _sx_chain_t rnext; /* <- read */ 250 }; 251 252 /** holds the state for a single stream */ 253 struct _sx_st { 254 /* environment */ 255 sx_env_t env; 256 257 /* tag, for logging */ 258 int tag; 259 260 /* IP address of the connection */ 261 /* pointing to sess.ip and owned by sess structure */ 262 const char *ip; 263 264 /* TCP port of the connection */ 265 /* pointing to sess.port and owned by sess structure */ 266 int port; 267 268 /* callback */ 269 sx_callback_t cb; 270 void *cb_arg; 271 272 /* type */ 273 _sx_type_t type; 274 275 /* flags */ 276 unsigned int flags; 277 278 /* application namespace */ 279 const char *ns; 280 281 /* requested stream properties */ 282 const char *req_to; 283 const char *req_from; 284 const char *req_version; 285 286 /* responded stream properties */ 287 const char *res_to; 288 const char *res_from; 289 const char *res_version; 290 291 /* stream id */ 292 const char *id; 293 294 /* io chain */ 295 _sx_chain_t wio, rio; 296 297 /* nad chain */ 298 _sx_chain_t wnad, rnad; 299 300 /* internal queues */ 301 jqueue_t wbufq; /* buffers waiting to go to wio */ 302 sx_buf_t wbufpending; /* buffer passed through wio but not written yet */ 303 jqueue_t rnadq; /* completed nads waiting to go to rnad */ 304 305 /* do we want to read or write? */ 306 int want_read, want_write; 307 308 /* bytes read from socket */ 309 int rbytes; 310 /* bytes parsed by parser */ 311 int pbytes; 312 /* total bytes processed */ 313 int tbytes; 314 315 /* read bytes maximum */ 316 int rbytesmax; 317 318 /* current state */ 319 _sx_state_t state; 320 321 /* parser */ 322 XML_Parser expat; 323 int depth; 324 int fail; 325 326 /* nad currently being built */ 327 nad_t nad; 328 329 /* plugin storage */ 330 void **plugin_data; 331 332 /* type and id of auth */ 333 const char *auth_method; 334 const char *auth_id; 335 336 /* if true, then we were called from the callback */ 337 int reentry; 338 339 /* this is true after a stream resets - applications should check this before doing per-stream init */ 340 int has_reset; 341 342 /* security strength factor (in sasl parlance) - roughly equivalent to key strength */ 343 int ssf; 344 }; 345 346 /** a plugin */ 347 struct _sx_plugin_st { 348 sx_env_t env; 349 350 int magic; /* unique id so that plugins can find each other */ 351 352 int index; 353 354 void *private; 355 356 void (*new)(sx_t s, sx_plugin_t p); /* pre-run init */ 357 void (*free)(sx_t s, sx_plugin_t p); /* conn being freed */ 358 359 void (*client)(sx_t s, sx_plugin_t p); /* client init */ 360 void (*server)(sx_t s, sx_plugin_t p); /* server init */ 361 362 /* return -2 == failed (permanent), -1 == failed (temporary), 0 == handled, 1 == pass */ 363 int (*wio)(sx_t s, sx_plugin_t p, sx_buf_t buf); /* before being written */ 364 int (*rio)(sx_t s, sx_plugin_t p, sx_buf_t buf); /* after being read */ 365 366 /* return 0 == handled, 1 == pass */ 367 int (*wnad)(sx_t s, sx_plugin_t p, nad_t nad, int elem); /* before being written */ 368 int (*rnad)(sx_t s, sx_plugin_t p, nad_t nad); /* after being read */ 369 370 void (*header)(sx_t s, sx_plugin_t p, sx_buf_t buf); /* before header req/res write */ 371 void (*stream)(sx_t s, sx_plugin_t p); /* after-stream init */ 372 373 void (*features)(sx_t s, sx_plugin_t p, nad_t nad); /* offer features */ 374 375 /* return 0 == handled, 1 == pass */ 376 int (*process)(sx_t s, sx_plugin_t p, nad_t nad); /* process completed nads */ 377 378 void (*unload)(sx_plugin_t p); /* plugin unloading */ 379 }; 380 381 /** an environment */ 382 struct _sx_env_st { 383 sx_plugin_t *plugins; 384 int nplugins; 385 }; 386 387 /** debugging macros */ 388 #define ZONE __FILE__,__LINE__ 389 390 /** helper functions for macros when we're debugging */ 391 JABBERD2_API void __sx_debug(const char *file, int line, const char *msgfmt, ...); 392 393 /** helper and internal macro for firing the callback */ 394 JABBERD2_API int __sx_event(const char *file, int line, sx_t s, sx_event_t e, void *data); 395 #define _sx_event(s,e,data) __sx_event(ZONE, s, e, data) 396 397 #ifdef SX_DEBUG 398 399 /** print debug output */ 400 #define _sx_debug if(get_debug_flag()) __sx_debug 401 402 /** state changes with output */ 403 #define _sx_state(s,st) do { _sx_debug(ZONE, "%d state change from %d to %d", s->tag, s->state, st); s->state = st; } while(0) 404 405 #else 406 407 /* clean and efficient versions */ 408 #define _sx_debug if(0) __sx_debug 409 #define _sx_state(s,st) s->state = st 410 411 #endif 412 413 #ifdef __cplusplus 414 } 415 #endif 416 417 /* now include sx envplugins datatypes */ 418 #include "plugins.h" 419 420 #endif 421