yong-stropheruby 0.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
+