stropheruby 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
data/ext/ctx.c ADDED
@@ -0,0 +1,416 @@
1
+ /* ctx.c
2
+ ** strophe XMPP client library -- run-time context implementation
3
+ **
4
+ ** Copyright (C) 2005-2008 OGG, LLC. All rights reserved.
5
+ **
6
+ ** This software is provided AS-IS with no warranty, either express
7
+ ** or implied.
8
+ **
9
+ ** This software is distributed under license and may not be copied,
10
+ ** modified or distributed except as expressly authorized under the
11
+ ** terms of the license contained in the file LICENSE.txt in this
12
+ ** distribution.
13
+ */
14
+
15
+ /** @file
16
+ * Runtime contexts, library initialization and shutdown, and versioning.
17
+ */
18
+
19
+ /** @defgroup Context Context objects
20
+ * These functions create and manipulate Strophe context objects.
21
+ *
22
+ * In order to support usage in a variety of environments, the
23
+ * Strophe library uses a runtime context object. This object
24
+ * contains the information on how to do memory allocation and
25
+ * logging. This allows the user to control how memory is allocated
26
+ * and what do to with log messages.
27
+ *
28
+ * These issues do not affect programs in the common case, but many
29
+ * environments require special treatment. Abstracting these into a runtime
30
+ * context object makes it easy to use Strophe on embedded platforms.
31
+ *
32
+ * Objects in Strophe are reference counted to ease memory management issues,
33
+ * but the context objects are not.
34
+ */
35
+
36
+ /** @defgroup Init Initialization, shutdown, and versioning
37
+ * These functions initialize and shutdown the library, and also allow
38
+ * for API version checking. Failure to properly call these functions may
39
+ * result in strange (and platform dependent) behavior.
40
+ *
41
+ * Specifically, the socket library on Win32 platforms must be initialized
42
+ * before use (although this is not the case on POSIX systems). The TLS
43
+ * subsystem must also seed the random number generator.
44
+ */
45
+
46
+ #include <stdlib.h>
47
+ #include <stdio.h>
48
+ #include <stdarg.h>
49
+ #include <string.h>
50
+
51
+ #include "strophe.h"
52
+ #include "common.h"
53
+ #include "util.h"
54
+
55
+ /** Initialize the Strophe library.
56
+ * This function initializes subcomponents of the Strophe library and must
57
+ * be called for Strophe to operate correctly.
58
+ *
59
+ * @ingroup Init
60
+ */
61
+ void xmpp_initialize(void)
62
+ {
63
+ sock_initialize();
64
+ tls_initialize();
65
+ }
66
+
67
+ /** Shutdown the Strophe library.
68
+ *
69
+ * @ingroup Init
70
+ */
71
+ void xmpp_shutdown(void)
72
+ {
73
+ tls_shutdown();
74
+ sock_shutdown();
75
+ }
76
+
77
+ /* version information */
78
+
79
+ #ifndef LIBXMPP_VERSION_MAJOR
80
+ /** @def LIBXMPP_VERSION_MAJOR
81
+ * The major version number of Strophe.
82
+ */
83
+ #define LIBXMPP_VERSION_MAJOR (0)
84
+ #endif
85
+ #ifndef LIBXMPP_VERSION_MINOR
86
+ /** @def LIBXMPP_VERSION_MINOR
87
+ * The minor version number of Strophe.
88
+ */
89
+ #define LIBXMPP_VERSION_MINOR (0)
90
+ #endif
91
+
92
+ /** Check that Strophe supports a specific API version.
93
+ *
94
+ * @param major the major version number
95
+ * @param minor the minor version number
96
+ *
97
+ * @return TRUE if the version is supported and FALSE if unsupported
98
+ *
99
+ * @ingroup Init
100
+ */
101
+ int xmpp_version_check(int major, int minor)
102
+ {
103
+ return (major == LIBXMPP_VERSION_MAJOR) &&
104
+ (minor >= LIBXMPP_VERSION_MINOR);
105
+ }
106
+
107
+ /* We define the global default allocator, logger, and context here. */
108
+
109
+ /* Wrap stdlib routines malloc, free, and realloc for default memory
110
+ * management.
111
+ */
112
+ static void *_malloc(const size_t size, void * const userdata)
113
+ {
114
+ return malloc(size);
115
+ }
116
+
117
+ static void _free(void *p, void * const userdata)
118
+ {
119
+ free(p);
120
+ }
121
+
122
+ static void *_realloc(void *p, const size_t size, void * const userdata)
123
+ {
124
+ return realloc(p, size);
125
+ }
126
+
127
+ /* default memory function map */
128
+ static xmpp_mem_t xmpp_default_mem = {
129
+ _malloc, /* use the thinly wrapped stdlib routines by default */
130
+ _free,
131
+ _realloc,
132
+ NULL
133
+ };
134
+
135
+ /* log levels and names */
136
+ static const char * const _xmpp_log_level_name[4] = {"DEBUG", "INFO", "WARN", "ERROR"};
137
+ static const xmpp_log_level_t _xmpp_default_logger_levels[] = {XMPP_LEVEL_DEBUG,
138
+ XMPP_LEVEL_INFO,
139
+ XMPP_LEVEL_WARN,
140
+ XMPP_LEVEL_ERROR};
141
+
142
+ /** Log a message.
143
+ * The default logger writes to stderr.
144
+ *
145
+ * @param userdata the opaque data used by the default logger. This contains
146
+ * the filter level in the default logger.
147
+ * @param level the level to log at
148
+ * @param area the area the log message is for
149
+ * @param msg the log message
150
+ */
151
+ void xmpp_default_logger(void * const userdata,
152
+ const xmpp_log_level_t level,
153
+ const char * const area,
154
+ const char * const msg)
155
+ {
156
+ xmpp_log_level_t filter_level = * (xmpp_log_level_t*)userdata;
157
+ if (level >= filter_level)
158
+ fprintf(stderr, "%s %s %s\n", area, _xmpp_log_level_name[level], msg);
159
+ }
160
+
161
+ static const xmpp_log_t _xmpp_default_loggers[] = {
162
+ {&xmpp_default_logger, (void*)&_xmpp_default_logger_levels[XMPP_LEVEL_DEBUG]},
163
+ {&xmpp_default_logger, (void*)&_xmpp_default_logger_levels[XMPP_LEVEL_INFO]},
164
+ {&xmpp_default_logger, (void*)&_xmpp_default_logger_levels[XMPP_LEVEL_WARN]},
165
+ {&xmpp_default_logger, (void*)&_xmpp_default_logger_levels[XMPP_LEVEL_ERROR]}
166
+ };
167
+
168
+ /** Get a default logger with filtering.
169
+ * The default logger provides a basic logging setup which writes log
170
+ * messages to stderr. Only messages where level is greater than or
171
+ * equal to the filter level will be logged.
172
+ *
173
+ * @param level the highest level the logger will log at
174
+ *
175
+ * @return the log structure for the given level
176
+ *
177
+ * @ingroup Context
178
+ */
179
+ xmpp_log_t *xmpp_get_default_logger(xmpp_log_level_t level)
180
+ {
181
+ /* clamp to the known range */
182
+ if (level > XMPP_LEVEL_ERROR) level = XMPP_LEVEL_ERROR;
183
+ if (level < XMPP_LEVEL_DEBUG) level = XMPP_LEVEL_DEBUG;
184
+
185
+ return (xmpp_log_t*)&_xmpp_default_loggers[level];
186
+ }
187
+
188
+ static xmpp_log_t xmpp_default_log = { NULL, NULL };
189
+
190
+ /* convenience functions for accessing the context */
191
+
192
+ /** Allocate memory in a Strophe context.
193
+ * All Strophe functions will use this to allocate memory.
194
+ *
195
+ * @param ctx a Strophe context object
196
+ * @param size the number of bytes to allocate
197
+ *
198
+ * @return a pointer to the allocated memory or NULL on an error
199
+ */
200
+ void *xmpp_alloc(const xmpp_ctx_t * const ctx, const size_t size)
201
+ {
202
+ return ctx->mem->alloc(size, ctx->mem->userdata);
203
+ }
204
+
205
+ /** Free memory in a Strophe context.
206
+ * All Strophe functions will use this to free allocated memory.
207
+ *
208
+ * @param ctx a Strophe context object
209
+ * @param p a pointer referencing memory to be freed
210
+ */
211
+ void xmpp_free(const xmpp_ctx_t * const ctx, void *p)
212
+ {
213
+ ctx->mem->free(p, ctx->mem->userdata);
214
+ }
215
+
216
+ /** Reallocate memory in a Strophe context.
217
+ * All Strophe functions will use this to reallocate memory.
218
+ *
219
+ * @param ctx a Strophe context object
220
+ * @param p a pointer to previously allocated memory
221
+ * @param size the new size in bytes to allocate
222
+ *
223
+ * @return a pointer to the reallocated memory or NULL on an error
224
+ */
225
+ void *xmpp_realloc(const xmpp_ctx_t * const ctx, void *p,
226
+ const size_t size)
227
+ {
228
+ return ctx->mem->realloc(p, size, ctx->mem->userdata);
229
+ }
230
+
231
+ /** Write a log message to the logger.
232
+ * Write a log message to the logger for the context for the specified
233
+ * level and area. This function takes a printf-style format string and a
234
+ * variable argument list (in va_list) format. This function is not meant
235
+ * to be called directly, but is used via xmpp_error, xmpp_warn, xmpp_info,
236
+ * and xmpp_debug.
237
+ *
238
+ * @param ctx a Strophe context object
239
+ * @param level the level at which to log
240
+ * @param area the area to log for
241
+ * @param fmt a printf-style format string for the message
242
+ * @param ap variable argument list supplied for the format string
243
+ */
244
+ void xmpp_log(const xmpp_ctx_t * const ctx,
245
+ const xmpp_log_level_t level,
246
+ const char * const area,
247
+ const char * const fmt,
248
+ va_list ap)
249
+ {
250
+ int oldret, ret;
251
+ char smbuf[4096] = {0};
252
+ char *buf;
253
+
254
+ buf = smbuf;
255
+ ret = xmpp_vsnprintf(buf, 4096 - 1, fmt, ap);
256
+ if (ret > 4096 - 1) {
257
+ buf = (char *)xmpp_alloc(ctx, ret + 1);
258
+ if (!buf) {
259
+ buf = NULL;
260
+ xmpp_error(ctx, "log", "Failed allocating memory for log message.");
261
+ return;
262
+ }
263
+ oldret = ret;
264
+ ret = xmpp_vsnprintf(buf, ret + 1, fmt, ap);
265
+ if (ret > oldret) {
266
+ xmpp_error(ctx, "log", "Unexpected error");
267
+ return;
268
+ }
269
+ }
270
+
271
+ if (ctx->log->handler)
272
+ ctx->log->handler(ctx->log->userdata, level, area, buf);
273
+ }
274
+
275
+ /** Write to the log at the ERROR level.
276
+ * This is a convenience function for writing to the log at the
277
+ * ERROR level. It takes a printf-style format string followed by a
278
+ * variable list of arguments for formatting.
279
+ *
280
+ * @param ctx a Strophe context object
281
+ * @param area the area to log for
282
+ * @param fmt a printf-style format string followed by a variable list of
283
+ * arguments to format
284
+ */
285
+ void xmpp_error(const xmpp_ctx_t * const ctx,
286
+ const char * const area,
287
+ const char * const fmt,
288
+ ...)
289
+ {
290
+ va_list ap;
291
+
292
+ va_start(ap, fmt);
293
+ xmpp_log(ctx, XMPP_LEVEL_ERROR, area, fmt, ap);
294
+ va_end(ap);
295
+ }
296
+
297
+ /** Write to the log at the WARN level.
298
+ * This is a convenience function for writing to the log at the WARN level.
299
+ * It takes a printf-style format string followed by a variable list of
300
+ * arguments for formatting.
301
+ *
302
+ * @param ctx a Strophe context object
303
+ * @param area the area to log for
304
+ * @param fmt a printf-style format string followed by a variable list of
305
+ * arguments to format
306
+ */
307
+ void xmpp_warn(const xmpp_ctx_t * const ctx,
308
+ const char * const area,
309
+ const char * const fmt,
310
+ ...)
311
+ {
312
+ va_list ap;
313
+
314
+ va_start(ap, fmt);
315
+ xmpp_log(ctx, XMPP_LEVEL_WARN, area, fmt, ap);
316
+ va_end(ap);
317
+ }
318
+
319
+ /** Write to the log at the INFO level.
320
+ * This is a convenience function for writing to the log at the INFO level.
321
+ * It takes a printf-style format string followed by a variable list of
322
+ * arguments for formatting.
323
+ *
324
+ * @param ctx a Strophe context object
325
+ * @param area the area to log for
326
+ * @param fmt a printf-style format string followed by a variable list of
327
+ * arguments to format
328
+ */
329
+ void xmpp_info(const xmpp_ctx_t * const ctx,
330
+ const char * const area,
331
+ const char * const fmt,
332
+ ...)
333
+ {
334
+ va_list ap;
335
+
336
+ va_start(ap, fmt);
337
+ xmpp_log(ctx, XMPP_LEVEL_INFO, area, fmt, ap);
338
+ va_end(ap);
339
+ }
340
+
341
+ /** Write to the log at the DEBUG level.
342
+ * This is a convenience function for writing to the log at the DEBUG level.
343
+ * It takes a printf-style format string followed by a variable list of
344
+ * arguments for formatting.
345
+ *
346
+ * @param ctx a Strophe context object
347
+ * @param area the area to log for
348
+ * @param fmt a printf-style format string followed by a variable list of
349
+ * arguments to format
350
+ */
351
+ void xmpp_debug(const xmpp_ctx_t * const ctx,
352
+ const char * const area,
353
+ const char * const fmt,
354
+ ...)
355
+ {
356
+ va_list ap;
357
+
358
+ va_start(ap, fmt);
359
+ xmpp_log(ctx, XMPP_LEVEL_DEBUG, area, fmt, ap);
360
+ va_end(ap);
361
+ }
362
+
363
+ /** Create and initialize a Strophe context object.
364
+ * If mem is NULL, a default allocation setup will be used which
365
+ * wraps malloc(), free(), and realloc() from the standard library.
366
+ * If log is NULL, a default logger will be used which does no
367
+ * logging. Basic filtered logging to stderr can be done with the
368
+ * xmpp_get_default_logger() convenience function.
369
+ *
370
+ * @param mem a pointer to an xmpp_mem_t structure or NULL
371
+ * @param log a pointer to an xmpp_log_t structure or NULL
372
+ *
373
+ * @return the allocated Strophe context object or NULL on an error
374
+ *
375
+ * @ingroup Context
376
+ */
377
+ xmpp_ctx_t *xmpp_ctx_new(const xmpp_mem_t * const mem,
378
+ const xmpp_log_t * const log)
379
+ {
380
+ xmpp_ctx_t *ctx = NULL;
381
+
382
+ if (mem == NULL)
383
+ ctx = xmpp_default_mem.alloc(sizeof(xmpp_ctx_t), NULL);
384
+ else
385
+ ctx = mem->alloc(sizeof(xmpp_ctx_t), mem->userdata);
386
+
387
+ if (ctx != NULL) {
388
+ if (mem != NULL)
389
+ ctx->mem = mem;
390
+ else
391
+ ctx->mem = &xmpp_default_mem;
392
+
393
+ if (log == NULL)
394
+ ctx->log = &xmpp_default_log;
395
+ else
396
+ ctx->log = log;
397
+
398
+ ctx->connlist = NULL;
399
+ ctx->loop_status = XMPP_LOOP_NOTSTARTED;
400
+ }
401
+
402
+ return ctx;
403
+ }
404
+
405
+ /** Free a Strophe context object that is no longer in use.
406
+ *
407
+ * @param ctx a Strophe context object
408
+ *
409
+ * @ingroup Context
410
+ */
411
+ void xmpp_ctx_free(xmpp_ctx_t * const ctx)
412
+ {
413
+ /* mem and log are owned by their suppliers */
414
+ xmpp_free(ctx, ctx); /* pull the hole in after us */
415
+ }
416
+