jabberd2  2.2.16
sx/sx.h
Go to the documentation of this file.
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 #ifndef INCL_SX_H
00022 #define INCL_SX_H
00023 
00024 #ifdef HAVE_CONFIG_H
00025 # include <config.h>
00026 #endif
00027 
00028 #include "ac-stdint.h"
00029 
00030 #include <expat.h>
00031 #include <util/util.h>
00032 
00033 /* jabberd2 Windows DLL */
00034 #ifndef JABBERD2_API
00035 # ifdef _WIN32
00036 #  ifdef JABBERD2_EXPORTS
00037 #   define JABBERD2_API  __declspec(dllexport)
00038 #  else /* JABBERD2_EXPORTS */
00039 #   define JABBERD2_API  __declspec(dllimport)
00040 #  endif /* JABBERD2_EXPORTS */
00041 # else /* _WIN32 */
00042 #  define JABBERD2_API extern
00043 # endif /* _WIN32 */
00044 #endif /* JABBERD2_API */
00045 
00046 #ifdef __cplusplus
00047 extern "C" {
00048 #endif
00049 
00050 /* forward declarations */
00051 typedef struct _sx_st           *sx_t;
00052 typedef struct _sx_env_st       *sx_env_t;
00053 typedef struct _sx_plugin_st    *sx_plugin_t;
00054 
00056 typedef enum {
00057     event_WANT_READ,        /* we want read actions */
00058     event_WANT_WRITE,       /* we want write actions */
00059     event_READ,             /* read some stuff for me */
00060     event_WRITE,            /* write this to the fd */
00061     event_STREAM,           /* stream is ready to go */
00062     event_OPEN,             /* normal operation */
00063     event_PACKET,           /* got a packet */
00064     event_CLOSED,           /* its over */
00065     event_ERROR             /* something's wrong */
00066 } sx_event_t;
00067 
00069 typedef enum {
00070     state_NONE,             /* pre-init */
00071     state_STREAM_RECEIVED,  /* stream start received (server) */
00072     state_STREAM_SENT,      /* stream start sent (client) */
00073     state_STREAM,           /* stream established */
00074     state_OPEN,             /* auth completed (normal stream operation) */
00075     state_CLOSING,          /* ready to close (send event_CLOSED to app) */
00076     state_CLOSED            /* closed (same as NONE, but can't be used any more) */
00077 } _sx_state_t;
00078 
00080 typedef enum {
00081     type_NONE,
00082     type_CLIENT,            /* we initiated the connection */
00083     type_SERVER             /* they initiated */
00084 } _sx_type_t;
00085 
00087 typedef int (*sx_callback_t)(sx_t s, sx_event_t e, void *data, void *arg);
00088 
00090 typedef int (*sx_plugin_init_t)(sx_env_t env, sx_plugin_t p, va_list args);
00091 
00092 /* errors */
00093 #define SX_SUCCESS          (0x00)
00094 #define SX_ERR_STREAM       (0x01)
00095 #define SX_ERR_AUTH         (0x02)
00096 #define SX_ERR_XML_PARSE    (0x03)
00097 
00099 typedef struct _sx_error_st {
00100     int                     code;
00101     char                    *generic;
00102     char                    *specific;
00103 } sx_error_t;
00104 
00106 #define _sx_gen_error(e,c,g,s)  do { e.code = c; e.generic = g; e.specific = s; } while(0);
00107 
00109 typedef void (*_sx_notify_t)(sx_t s, void *arg);
00110 
00112 typedef struct _sx_buf_st *sx_buf_t;
00113 struct _sx_buf_st {
00114     unsigned char           *data;     /* pointer to buffer's data */
00115     unsigned int            len;       /* length of buffer's data */
00116     unsigned char           *heap;     /* beginning of malloc() block containing data, if non-NULL */
00117 
00118     /* function to call when this buffer gets written */
00119     _sx_notify_t            notify;
00120     void                    *notify_arg;
00121 };
00122 
00123 /* stream errors */
00124 #define stream_err_BAD_FORMAT               (0)
00125 #define stream_err_BAD_NAMESPACE_PREFIX     (1)
00126 #define stream_err_CONFLICT                 (2)
00127 #define stream_err_CONNECTION_TIMEOUT       (3)
00128 #define stream_err_HOST_GONE                (4)
00129 #define stream_err_HOST_UNKNOWN             (5)
00130 #define stream_err_IMPROPER_ADDRESSING      (6)
00131 #define stream_err_INTERNAL_SERVER_ERROR    (7)
00132 #define stream_err_INVALID_FROM             (8)
00133 #define stream_err_INVALID_ID               (9)
00134 #define stream_err_INVALID_NAMESPACE        (10)
00135 #define stream_err_INVALID_XML              (11)
00136 #define stream_err_NOT_AUTHORIZED           (12)
00137 #define stream_err_POLICY_VIOLATION         (13)
00138 #define stream_err_REMOTE_CONNECTION_FAILED (14)
00139 #define stream_err_RESTRICTED_XML           (15)
00140 #define stream_err_RESOURCE_CONSTRAINT      (16)
00141 #define stream_err_SEE_OTHER_HOST           (17)
00142 #define stream_err_SYSTEM_SHUTDOWN          (18)
00143 #define stream_err_UNDEFINED_CONDITION      (19)
00144 #define stream_err_UNSUPPORTED_ENCODING     (20)
00145 #define stream_err_UNSUPPORTED_STANZA_TYPE  (21)
00146 #define stream_err_UNSUPPORTED_VERSION      (22)
00147 #define stream_err_XML_NOT_WELL_FORMED      (23)
00148 #define stream_err_LAST                     (24)
00149 
00150 /* exported functions */
00151 
00152 /* make/break */
00153 JABBERD2_API sx_t                        sx_new(sx_env_t env, int tag, sx_callback_t cb, void *arg);
00154 JABBERD2_API void                        sx_free(sx_t s);
00155 
00156 /* get things ready */
00157 JABBERD2_API void                        sx_client_init(sx_t s, unsigned int flags, char *ns, char *to, char *from, char *version);
00158 JABBERD2_API void                        sx_server_init(sx_t s, unsigned int flags);
00159 
00160 /* activity on socket, do stuff! (returns 1 if more read/write actions wanted, 0 otherwise) */
00161 JABBERD2_API int                         sx_can_read(sx_t s);
00162 JABBERD2_API int                         sx_can_write(sx_t s);
00163 
00165 JABBERD2_API void                        sx_nad_write_elem(sx_t s, nad_t nad, int elem);
00166 #define sx_nad_write(s,nad) sx_nad_write_elem(s, nad, 0)
00167 
00169 JABBERD2_API void                        sx_raw_write(sx_t s, char *buf, int len);
00170 
00172 JABBERD2_API void                        sx_auth(sx_t s, const char *auth_method, const char *auth_id);
00173 
00174 /* make/break an environment */
00175 JABBERD2_API sx_env_t                    sx_env_new(void);
00176 JABBERD2_API void                        sx_env_free(sx_env_t env);
00177 
00179 JABBERD2_API sx_plugin_t                 sx_env_plugin(sx_env_t env, sx_plugin_init_t init, ...);
00180 
00181 /* send errors and close stuff */
00182 JABBERD2_API void                        sx_error(sx_t s, int err, const char *text);
00183 JABBERD2_API void                        sx_error_extended(sx_t s, int err, const char *content);
00184 JABBERD2_API void                        sx_close(sx_t s);
00185 JABBERD2_API void                        sx_kill(sx_t s);
00186 
00187 
00188 /* internal functions */
00189 
00190 /* primary expat callbacks */
00191 JABBERD2_API void                        _sx_element_start(void *arg, const char *name, const char **atts);
00192 JABBERD2_API void                        _sx_element_end(void *arg, const char *name);
00193 JABBERD2_API void                        _sx_cdata(void *arg, const char *str, int len);
00194 JABBERD2_API void                        _sx_namespace_start(void *arg, const char *prefix, const char *uri);
00195 #ifdef HAVE_XML_STOPPARSER
00196 JABBERD2_API void                        _sx_entity_declaration(void *arg, const char *entityName,
00197                                                                 int is_parameter_entity, const char *value,
00198                                                                 int value_length, const char *base,
00199                                                                 const char *systemId, const char *publicId,
00200                                                                 const char *notationName);
00201 #endif
00202 
00204 JABBERD2_API void                        _sx_process_read(sx_t s, sx_buf_t buf);
00205 
00207 JABBERD2_API void                        _sx_nad_process(sx_t s, nad_t nad);
00208 
00209 /* chain management */
00210 JABBERD2_API void                        _sx_chain_io_plugin(sx_t s, sx_plugin_t p);
00211 JABBERD2_API void                        _sx_chain_nad_plugin(sx_t s, sx_plugin_t p);
00212 
00213 /* chain running */
00214 JABBERD2_API int                         _sx_chain_io_write(sx_t s, sx_buf_t buf);
00215 JABBERD2_API int                         _sx_chain_io_read(sx_t s, sx_buf_t buf);
00216 
00217 JABBERD2_API int                         _sx_chain_nad_write(sx_t s, nad_t nad, int elem);
00218 JABBERD2_API int                         _sx_chain_nad_read(sx_t s, nad_t nad);
00219 
00220 /* buffer utilities */
00221 JABBERD2_API sx_buf_t                     _sx_buffer_new(const char *data, int len, _sx_notify_t notify, void *notify_arg);
00222 JABBERD2_API void                        _sx_buffer_free(sx_buf_t buf);
00223 JABBERD2_API void                        _sx_buffer_clear(sx_buf_t buf);
00224 JABBERD2_API void                        _sx_buffer_alloc_margin(sx_buf_t buf, int before, int after);
00225 JABBERD2_API void                        _sx_buffer_set(sx_buf_t buf, char *newdata, int newlength, char *newheap);
00226 
00228 JABBERD2_API int                         _sx_nad_write(sx_t s, nad_t nad, int elem);
00229 
00231 JABBERD2_API void                        sx_raw_write(sx_t s, char *buf, int len);
00232 
00234 JABBERD2_API void                        _sx_reset(sx_t s);
00235 
00236 /* send errors and close stuff */
00237 JABBERD2_API void                        _sx_error(sx_t s, int err, const char *text);
00238 JABBERD2_API void                        _sx_error_extended(sx_t s, int err, const char *content);
00239 JABBERD2_API void                        _sx_close(sx_t s);
00240 
00242 typedef struct _sx_chain_st *_sx_chain_t;
00243 struct _sx_chain_st {
00244     sx_plugin_t              p;
00245 
00246     _sx_chain_t              wnext;          /* -> write */
00247     _sx_chain_t              rnext;          /* <- read */
00248 };
00249 
00251 struct _sx_st {
00252     /* environment */
00253     sx_env_t                 env;
00254 
00255     /* tag, for logging */
00256     int                      tag;
00257 
00258     /* IP address of the connection */
00259     /* pointing to sess.ip and owned by sess structure */
00260     char                    *ip;
00261 
00262     /* TCP port of the connection */
00263     /* pointing to sess.port and owned by sess structure */
00264     int                     port;
00265 
00266     /* callback */
00267     sx_callback_t            cb;
00268     void                    *cb_arg;
00269 
00270     /* type */
00271     _sx_type_t               type;
00272 
00273     /* flags */
00274     unsigned int             flags;
00275 
00276     /* application namespace */
00277     char                    *ns;
00278 
00279     /* requested stream properties */
00280     char                    *req_to;
00281     char                    *req_from;
00282     char                    *req_version;
00283 
00284     /* responded stream properties */
00285     char                    *res_to;
00286     char                    *res_from;
00287     char                    *res_version;
00288 
00289     /* stream id */
00290     char                    *id;
00291 
00292     /* io chain */
00293     _sx_chain_t              wio, rio;
00294 
00295     /* nad chain */
00296     _sx_chain_t              wnad, rnad;
00297 
00298     /* internal queues */
00299     jqueue_t                 wbufq;              /* buffers waiting to go to wio */
00300     sx_buf_t                 wbufpending;        /* buffer passed through wio but not written yet */
00301     jqueue_t                 rnadq;              /* completed nads waiting to go to rnad */
00302 
00303     /* do we want to read or write? */
00304     int                      want_read, want_write;
00305 
00306     /* bytes read from socket */
00307     int                      rbytes;
00308 
00309     /* read bytes maximum */
00310     int                      rbytesmax;
00311 
00312     /* current state */
00313     _sx_state_t              state;
00314 
00315     /* parser */
00316     XML_Parser               expat;
00317     int                      depth;
00318     int                      fail;
00319 
00320     /* nad currently being built */
00321     nad_t                    nad;
00322 
00323     /* plugin storage */
00324     void                   **plugin_data;
00325 
00326     /* type and id of auth */
00327     char                    *auth_method;
00328     char                    *auth_id;
00329 
00330     /* if true, then we were called from the callback */
00331     int                     reentry;
00332 
00333     /* this is true after a stream resets - applications should check this before doing per-stream init */
00334     int                     has_reset;
00335 
00336     /* security strength factor (in sasl parlance) - roughly equivalent to key strength */
00337     int                     ssf;
00338 
00339     /* is stream compressed */
00340     int                     compressed;
00341 };
00342 
00344 struct _sx_plugin_st {
00345     sx_env_t                env;
00346 
00347     int                     magic;              /* unique id so that plugins can find each other */
00348 
00349     int                     index;
00350 
00351     void                    *private;
00352 
00353     void                    (*new)(sx_t s, sx_plugin_t p);                          /* pre-run init */
00354     void                    (*free)(sx_t s, sx_plugin_t p);                         /* conn being freed */
00355 
00356     void                    (*client)(sx_t s, sx_plugin_t p);                       /* client init */
00357     void                    (*server)(sx_t s, sx_plugin_t p);                       /* server init */
00358 
00359     /* return -2 == failed (permanent), -1 == failed (temporary), 0 == handled, 1 == pass */
00360     int                     (*wio)(sx_t s, sx_plugin_t p, sx_buf_t buf);            /* before being written */
00361     int                     (*rio)(sx_t s, sx_plugin_t p, sx_buf_t buf);            /* after being read */
00362 
00363     /* return 0 == handled, 1 == pass */
00364     int                     (*wnad)(sx_t s, sx_plugin_t p, nad_t nad, int elem);    /* before being written */
00365     int                     (*rnad)(sx_t s, sx_plugin_t p, nad_t nad);              /* after being read */
00366 
00367     void                    (*header)(sx_t s, sx_plugin_t p, sx_buf_t buf);         /* before header req/res write */
00368     void                    (*stream)(sx_t s, sx_plugin_t p);                       /* after-stream init */
00369 
00370     void                    (*features)(sx_t s, sx_plugin_t p, nad_t nad);          /* offer features */
00371 
00372     /* return 0 == handled, 1 == pass */
00373     int                     (*process)(sx_t s, sx_plugin_t p, nad_t nad);           /* process completed nads */
00374 
00375     void                    (*unload)(sx_plugin_t p);                               /* plugin unloading */
00376 };
00377 
00379 struct _sx_env_st {
00380     sx_plugin_t             *plugins;
00381     int                     nplugins;
00382 };
00383 
00385 #define ZONE __FILE__,__LINE__
00386 
00388 JABBERD2_API void        __sx_debug(const char *file, int line, const char *msgfmt, ...);
00389 
00391 JABBERD2_API int         __sx_event(const char *file, int line, sx_t s, sx_event_t e, void *data);
00392 #define _sx_event(s,e,data) __sx_event(ZONE, s, e, data)
00393 
00394 #ifdef SX_DEBUG
00395 
00397 #define _sx_debug if(get_debug_flag()) __sx_debug
00398 
00400 #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)
00401 
00402 #else
00403 
00404 /* clean and efficient versions */
00405 #define _sx_debug if(0) __sx_debug
00406 #define _sx_state(s,st) s->state = st
00407 
00408 #endif
00409 
00410 #ifdef __cplusplus
00411 }
00412 #endif
00413 
00414 /* now include sx envplugins datatypes */
00415 #include "plugins.h"
00416 
00417 #endif