1 /* mesode.h
2 ** strophe XMPP client library C API
3 **
4 ** Copyright (C) 2005-2009 Collecta, Inc.
5 **
6 **  This software is provided AS-IS with no warranty, either express or
7 **  implied.
8 **
9 **  This software is dual licensed under the MIT and GPLv3 licenses.
10 */
11 
12 /** @file
13  *  Strophe public C API definitions.
14  */
15 
16 #ifndef __LIBMESODE_MESODE_H__
17 #define __LIBMESODE_MESODE_H__
18 
19 #include <stddef.h>     /* size_t */
20 
21 #ifdef __cplusplus
22 extern "C" {
23 #endif
24 
25 /* namespace defines */
26 /** @def XMPP_NS_CLIENT
27  *  Namespace definition for 'jabber:client'.
28  */
29 #define XMPP_NS_CLIENT "jabber:client"
30 /** @def XMPP_NS_COMPONENT
31  *  Namespace definition for 'jabber:component:accept'.
32  */
33 #define XMPP_NS_COMPONENT "jabber:component:accept"
34 /** @def XMPP_NS_STREAMS
35  *  Namespace definition for 'http://etherx.jabber.org/streams'.
36  */
37 #define XMPP_NS_STREAMS "http://etherx.jabber.org/streams"
38 /** @def XMPP_NS_STREAMS_IETF
39  *  Namespace definition for 'urn:ietf:params:xml:ns:xmpp-streams'.
40  */
41 #define XMPP_NS_STREAMS_IETF "urn:ietf:params:xml:ns:xmpp-streams"
42 /** @def XMPP_NS_TLS
43  *  Namespace definition for 'url:ietf:params:xml:ns:xmpp-tls'.
44  */
45 #define XMPP_NS_TLS "urn:ietf:params:xml:ns:xmpp-tls"
46 /** @def XMPP_NS_SASL
47  *  Namespace definition for 'urn:ietf:params:xml:ns:xmpp-sasl'.
48  */
49 #define XMPP_NS_SASL "urn:ietf:params:xml:ns:xmpp-sasl"
50 /** @def XMPP_NS_BIND
51  *  Namespace definition for 'urn:ietf:params:xml:ns:xmpp-bind'.
52  */
53 #define XMPP_NS_BIND "urn:ietf:params:xml:ns:xmpp-bind"
54 /** @def XMPP_NS_SESSION
55  *  Namespace definition for 'urn:ietf:params:xml:ns:xmpp-session'.
56  */
57 #define XMPP_NS_SESSION "urn:ietf:params:xml:ns:xmpp-session"
58 /** @def XMPP_NS_AUTH
59  *  Namespace definition for 'jabber:iq:auth'.
60  */
61 #define XMPP_NS_AUTH "jabber:iq:auth"
62 /** @def XMPP_NS_DISCO_INFO
63  *  Namespace definition for 'http://jabber.org/protocol/disco#info'.
64  */
65 #define XMPP_NS_DISCO_INFO "http://jabber.org/protocol/disco#info"
66 /** @def XMPP_NS_DISCO_ITEMS
67  *  Namespace definition for 'http://jabber.org/protocol/disco#items'.
68  */
69 #define XMPP_NS_DISCO_ITEMS "http://jabber.org/protocol/disco#items"
70 /** @def XMPP_NS_ROSTER
71  *  Namespace definition for 'jabber:iq:roster'.
72  */
73 #define XMPP_NS_ROSTER "jabber:iq:roster"
74 
75 /* error defines */
76 /** @def XMPP_EOK
77  *  Success error code.
78  */
79 #define XMPP_EOK 0
80 /** @def XMPP_EMEM
81  *  Memory related failure error code.
82  *
83  *  This is returned on allocation errors and signals that the host may
84  *  be out of memory.
85  */
86 #define XMPP_EMEM -1
87 /** @def XMPP_EINVOP
88  *  Invalid operation error code.
89  *
90  *  This error code is returned when the operation was invalid and signals
91  *  that the Strophe API is being used incorrectly.
92  */
93 #define XMPP_EINVOP -2
94 /** @def XMPP_EINT
95  *  Internal failure error code.
96  */
97 #define XMPP_EINT -3
98 
99 /* initialization and shutdown */
100 void xmpp_initialize(void);
101 void xmpp_shutdown(void);
102 
103 /* version */
104 int xmpp_version_check(int major, int minor);
105 
106 /* run-time contexts */
107 
108 /* user-replaceable memory allocator */
109 typedef struct _xmpp_mem_t xmpp_mem_t;
110 
111 /* user-replaceable log object */
112 typedef struct _xmpp_log_t xmpp_log_t;
113 
114 /* opaque run time context containing the above hooks */
115 typedef struct _xmpp_ctx_t xmpp_ctx_t;
116 
117 typedef struct _tlscert_t xmpp_tlscert_t;
118 
119 xmpp_ctx_t *xmpp_ctx_new(const xmpp_mem_t * const mem,
120 			 const xmpp_log_t * const log);
121 void xmpp_ctx_free(xmpp_ctx_t * const ctx);
122 
123 /* free some blocks returned by other APIs, for example the
124    buffer you get from xmpp_stanza_to_text */
125 void xmpp_free(const xmpp_ctx_t * const ctx, void *p);
126 
127 struct _xmpp_mem_t {
128     void *(*alloc)(const size_t size, void * const userdata);
129     void (*free)(void *p, void * const userdata);
130     void *(*realloc)(void *p, const size_t size, void * const userdata);
131     void *userdata;
132 };
133 
134 typedef enum {
135     XMPP_LEVEL_DEBUG,
136     XMPP_LEVEL_INFO,
137     XMPP_LEVEL_WARN,
138     XMPP_LEVEL_ERROR
139 } xmpp_log_level_t;
140 
141 typedef enum {
142     XMPP_UNKNOWN,
143     XMPP_CLIENT,
144     XMPP_COMPONENT
145 } xmpp_conn_type_t;
146 
147 typedef void (*xmpp_log_handler)(void * const userdata,
148 				 const xmpp_log_level_t level,
149 				 const char * const area,
150 				 const char * const msg);
151 
152 struct _xmpp_log_t {
153     xmpp_log_handler handler;
154     void *userdata;
155 };
156 
157 /* return a default logger filtering at a given level */
158 xmpp_log_t *xmpp_get_default_logger(xmpp_log_level_t level);
159 
160 /* connection */
161 
162 /* opaque connection object */
163 typedef struct _xmpp_conn_t xmpp_conn_t;
164 typedef struct _xmpp_stanza_t xmpp_stanza_t;
165 
166 /* connection flags */
167 #define XMPP_CONN_FLAG_DISABLE_TLS   (1UL << 0)
168 #define XMPP_CONN_FLAG_MANDATORY_TLS (1UL << 1)
169 #define XMPP_CONN_FLAG_LEGACY_SSL    (1UL << 2)
170 /** @def XMPP_CONN_FLAG_TRUST_TLS
171  *  Trust server's certificate even if it is invalid.
172  */
173 #define XMPP_CONN_FLAG_TRUST_TLS     (1UL << 3)
174 /** @def XMPP_CONN_FLAG_LEGACY_AUTH
175  *  Enable legacy authentication support.
176  */
177 #define XMPP_CONN_FLAG_LEGACY_AUTH   (1UL << 4)
178 
179 /* connect callback */
180 typedef enum {
181     XMPP_CONN_CONNECT,
182     XMPP_CONN_RAW_CONNECT,
183     XMPP_CONN_DISCONNECT,
184     XMPP_CONN_FAIL
185 } xmpp_conn_event_t;
186 
187 typedef enum {
188     XMPP_SE_BAD_FORMAT,
189     XMPP_SE_BAD_NS_PREFIX,
190     XMPP_SE_CONFLICT,
191     XMPP_SE_CONN_TIMEOUT,
192     XMPP_SE_HOST_GONE,
193     XMPP_SE_HOST_UNKNOWN,
194     XMPP_SE_IMPROPER_ADDR,
195     XMPP_SE_INTERNAL_SERVER_ERROR,
196     XMPP_SE_INVALID_FROM,
197     XMPP_SE_INVALID_ID,
198     XMPP_SE_INVALID_NS,
199     XMPP_SE_INVALID_XML,
200     XMPP_SE_NOT_AUTHORIZED,
201     XMPP_SE_POLICY_VIOLATION,
202     XMPP_SE_REMOTE_CONN_FAILED,
203     XMPP_SE_RESOURCE_CONSTRAINT,
204     XMPP_SE_RESTRICTED_XML,
205     XMPP_SE_SEE_OTHER_HOST,
206     XMPP_SE_SYSTEM_SHUTDOWN,
207     XMPP_SE_UNDEFINED_CONDITION,
208     XMPP_SE_UNSUPPORTED_ENCODING,
209     XMPP_SE_UNSUPPORTED_STANZA_TYPE,
210     XMPP_SE_UNSUPPORTED_VERSION,
211     XMPP_SE_XML_NOT_WELL_FORMED
212 } xmpp_error_type_t;
213 
214 typedef struct {
215     xmpp_error_type_t type;
216     char *text;
217     xmpp_stanza_t *stanza;
218 } xmpp_stream_error_t;
219 
220 typedef void (*xmpp_conn_handler)(xmpp_conn_t * const conn,
221 				  const xmpp_conn_event_t event,
222 				  const int error,
223 				  xmpp_stream_error_t * const stream_error,
224 				  void * const userdata);
225 
226 typedef int (*xmpp_certfail_handler)(xmpp_tlscert_t *cert, const char * const errormsg);
227 void xmpp_send_error(xmpp_conn_t * const conn, xmpp_error_type_t const type, char * const text);
228 xmpp_conn_t *xmpp_conn_new(xmpp_ctx_t * const ctx);
229 xmpp_conn_t *xmpp_conn_clone(xmpp_conn_t * const conn);
230 int xmpp_conn_release(xmpp_conn_t * const conn);
231 
232 long xmpp_conn_get_flags(const xmpp_conn_t * const conn);
233 int xmpp_conn_set_flags(xmpp_conn_t * const conn, long flags);
234 const char *xmpp_conn_get_jid(const xmpp_conn_t * const conn);
235 const char *xmpp_conn_get_bound_jid(const xmpp_conn_t * const conn);
236 void xmpp_conn_set_jid(xmpp_conn_t * const conn, const char * const jid);
237 const char *xmpp_conn_get_pass(const xmpp_conn_t * const conn);
238 void xmpp_conn_set_pass(xmpp_conn_t * const conn, const char * const pass);
239 xmpp_ctx_t *xmpp_conn_get_context(xmpp_conn_t * const conn);
240 void xmpp_conn_disable_tls(xmpp_conn_t * const conn);
241 void xmpp_conn_tlscert_path(xmpp_conn_t * const conn, char *path);
242 int xmpp_conn_is_secured(xmpp_conn_t * const conn);
243 void xmpp_conn_set_keepalive(xmpp_conn_t * const conn, int timeout, int interval);
244 
245 xmpp_tlscert_t *xmpp_conn_tls_peer_cert(xmpp_conn_t * const conn);
246 int xmpp_conn_tlscert_version(xmpp_tlscert_t *cert);
247 char *xmpp_conn_tlscert_serialnumber(xmpp_tlscert_t *cert);
248 char *xmpp_conn_tlscert_subjectname(xmpp_tlscert_t *cert);
249 char *xmpp_conn_tlscert_issuername(xmpp_tlscert_t *cert);
250 char *xmpp_conn_tlscert_fingerprint(xmpp_tlscert_t *cert);
251 char *xmpp_conn_tlscert_notbefore(xmpp_tlscert_t *cert);
252 char *xmpp_conn_tlscert_notafter(xmpp_tlscert_t *cert);
253 char *xmpp_conn_tlscert_signature_algorithm(xmpp_tlscert_t *cert);
254 char *xmpp_conn_tlscert_key_algorithm(xmpp_tlscert_t *cert);
255 void xmpp_conn_free_tlscert(xmpp_ctx_t *ctx, xmpp_tlscert_t *cert);
256 
257 int xmpp_connect_client(xmpp_conn_t * const conn,
258 			  const char * const altdomain,
259 			  unsigned short altport,
260               xmpp_certfail_handler certfail_cb,
261 			  xmpp_conn_handler callback,
262 			  void * const userdata);
263 
264 int xmpp_connect_component(xmpp_conn_t * const conn, const char * const server,
265                            unsigned short port, xmpp_conn_handler callback,
266                            void * const userdata);
267 
268 int xmpp_connect_raw(xmpp_conn_t * const conn,
269                      const char * const altdomain,
270                      unsigned short altport,
271                      xmpp_certfail_handler certfail_cb,
272                      xmpp_conn_handler callback,
273                      void * const userdata);
274 int xmpp_conn_open_stream_default(xmpp_conn_t * const conn);
275 int xmpp_conn_open_stream(xmpp_conn_t * const conn, char **attributes,
276                           size_t attributes_len);
277 int xmpp_conn_tls_start(xmpp_conn_t * const conn);
278 
279 void xmpp_disconnect(xmpp_conn_t * const conn);
280 
281 void xmpp_send(xmpp_conn_t * const conn,
282 	       xmpp_stanza_t * const stanza);
283 
284 void xmpp_send_raw_string(xmpp_conn_t * const conn,
285 			  const char * const fmt, ...);
286 void xmpp_send_raw(xmpp_conn_t * const conn,
287 		   const char * const data, const size_t len);
288 
289 
290 /* handlers */
291 
292 /* if the handle returns false it is removed */
293 typedef int (*xmpp_timed_handler)(xmpp_conn_t * const conn,
294 				  void * const userdata);
295 
296 void xmpp_timed_handler_add(xmpp_conn_t * const conn,
297 			    xmpp_timed_handler handler,
298 			    const unsigned long period,
299 			    void * const userdata);
300 void xmpp_timed_handler_delete(xmpp_conn_t * const conn,
301 			       xmpp_timed_handler handler);
302 
303 
304 /* if the handler returns false it is removed */
305 typedef int (*xmpp_handler)(xmpp_conn_t * const conn,
306 			     xmpp_stanza_t * const stanza,
307 			     void * const userdata);
308 
309 void xmpp_handler_add(xmpp_conn_t * const conn,
310 		      xmpp_handler handler,
311 		      const char * const ns,
312 		      const char * const name,
313 		      const char * const type,
314 		      void * const userdata);
315 void xmpp_handler_delete(xmpp_conn_t * const conn,
316 			 xmpp_handler handler);
317 
318 void xmpp_id_handler_add(xmpp_conn_t * const conn,
319 			 xmpp_handler handler,
320 			 const char * const id,
321 			 void * const userdata);
322 void xmpp_id_handler_delete(xmpp_conn_t * const conn,
323 			    xmpp_handler handler,
324 			    const char * const id);
325 
326 /*
327 void xmpp_register_stanza_handler(conn, stanza, xmlns, type, handler)
328 */
329 
330 /* stanzas */
331 
332 /* allocate and initialize a blank stanza */
333 xmpp_stanza_t *xmpp_stanza_new(xmpp_ctx_t *ctx);
334 xmpp_stanza_t *xmpp_stanza_new_from_string(xmpp_ctx_t *ctx, const char *str);
335 
336 /* clone a stanza */
337 xmpp_stanza_t *xmpp_stanza_clone(xmpp_stanza_t * const stanza);
338 
339 /* copies a stanza and all children */
340 xmpp_stanza_t *xmpp_stanza_copy(const xmpp_stanza_t * const stanza);
341 
342 /* free a stanza object and it's contents */
343 int xmpp_stanza_release(xmpp_stanza_t * const stanza);
344 
345 int xmpp_stanza_is_text(xmpp_stanza_t * const stanza);
346 int xmpp_stanza_is_tag(xmpp_stanza_t * const stanza);
347 
348 /* marshall a stanza into text for transmission or display */
349 int xmpp_stanza_to_text(xmpp_stanza_t *stanza,
350 			char ** const buf, size_t * const buflen);
351 
352 xmpp_stanza_t *xmpp_stanza_get_children(xmpp_stanza_t * const stanza);
353 xmpp_stanza_t *xmpp_stanza_get_child_by_name(xmpp_stanza_t * const stanza,
354 					     const char * const name);
355 xmpp_stanza_t *xmpp_stanza_get_child_by_ns(xmpp_stanza_t * const stanza,
356 					   const char * const ns);
357 xmpp_stanza_t *xmpp_stanza_get_child_by_name_and_ns(xmpp_stanza_t * const stanza,
358                                                     const char * const name,
359                                                     const char * const ns);
360 xmpp_stanza_t *xmpp_stanza_get_next(xmpp_stanza_t * const stanza);
361 int xmpp_stanza_add_child(xmpp_stanza_t *stanza, xmpp_stanza_t *child);
362 
363 const char *xmpp_stanza_get_attribute(xmpp_stanza_t * const stanza,
364 				      const char * const name);
365 int xmpp_stanza_get_attribute_count(xmpp_stanza_t * const stanza);
366 int xmpp_stanza_get_attributes(xmpp_stanza_t * const stanza,
367 			       const char **attr, int attrlen);
368 /* concatenate all child text nodes.  this function
369  * returns a string that must be freed by the caller */
370 char *xmpp_stanza_get_text(xmpp_stanza_t * const stanza);
371 const char *xmpp_stanza_get_text_ptr(xmpp_stanza_t * const stanza);
372 const char *xmpp_stanza_get_name(xmpp_stanza_t * const stanza);
373 /* set_attribute adds/replaces attributes */
374 int xmpp_stanza_set_attribute(xmpp_stanza_t * const stanza,
375 			      const char * const key,
376 			      const char * const value);
377 int xmpp_stanza_set_name(xmpp_stanza_t *stanza,
378 			 const char * const name);
379 int xmpp_stanza_set_text(xmpp_stanza_t *stanza,
380 			 const char * const text);
381 int xmpp_stanza_set_text_with_size(xmpp_stanza_t *stanza,
382 				   const char * const text,
383 				   const size_t size);
384 int xmpp_stanza_del_attribute(xmpp_stanza_t * const stanza,
385                               const char * const name);
386 
387 /* common stanza helpers */
388 const char *xmpp_stanza_get_ns(xmpp_stanza_t * const stanza);
389 const char *xmpp_stanza_get_type(xmpp_stanza_t * const stanza);
390 const char *xmpp_stanza_get_id(xmpp_stanza_t * const stanza);
391 const char *xmpp_stanza_get_to(xmpp_stanza_t * const stanza);
392 const char *xmpp_stanza_get_from(xmpp_stanza_t * const stanza);
393 int xmpp_stanza_set_ns(xmpp_stanza_t * const stanza, const char * const ns);
394 int xmpp_stanza_set_id(xmpp_stanza_t * const stanza, const char * const id);
395 int xmpp_stanza_set_type(xmpp_stanza_t * const stanza, const char * const type);
396 int xmpp_stanza_set_to(xmpp_stanza_t * const stanza, const char * const to);
397 int xmpp_stanza_set_from(xmpp_stanza_t * const stanza, const char * const from);
398 
399 /* allocate and initialize a stanza in reply to another */
400 xmpp_stanza_t *xmpp_stanza_reply(xmpp_stanza_t * const stanza);
401 
402 /* stanza subclasses */
403 xmpp_stanza_t *xmpp_message_new(xmpp_ctx_t *ctx, const char * const type,
404                                 const char * const to, const char * const id);
405 char *xmpp_message_get_body(xmpp_stanza_t *msg);
406 int xmpp_message_set_body(xmpp_stanza_t *msg, const char * const text);
407 
408 xmpp_stanza_t *xmpp_iq_new(xmpp_ctx_t *ctx, const char * const type,
409                            const char * const id);
410 xmpp_stanza_t *xmpp_presence_new(xmpp_ctx_t *ctx);
411 xmpp_stanza_t *xmpp_error_new(xmpp_ctx_t *ctx, xmpp_error_type_t const type,
412                               const char * const text);
413 
414 /* jid */
415 
416 /* these return new strings that must be xmpp_free()'d */
417 char *xmpp_jid_new(xmpp_ctx_t *ctx, const char *node,
418                                     const char *domain,
419                                     const char *resource);
420 char *xmpp_jid_bare(xmpp_ctx_t *ctx, const char *jid);
421 char *xmpp_jid_node(xmpp_ctx_t *ctx, const char *jid);
422 char *xmpp_jid_domain(xmpp_ctx_t *ctx, const char *jid);
423 char *xmpp_jid_resource(xmpp_ctx_t *ctx, const char *jid);
424 
425 /* event loop */
426 
427 void xmpp_run_once(xmpp_ctx_t *ctx, const unsigned long  timeout);
428 void xmpp_run(xmpp_ctx_t *ctx);
429 void xmpp_stop(xmpp_ctx_t *ctx);
430 void xmpp_ctx_set_timeout(xmpp_ctx_t * const ctx, const unsigned long timeout);
431 
432 /* UUID */
433 
434 char *xmpp_uuid_gen(xmpp_ctx_t *ctx);
435 
436 /* SHA1 */
437 
438 /** @def XMPP_SHA1_DIGEST_SIZE
439  *  Size of the SHA1 message digest.
440  */
441 #define XMPP_SHA1_DIGEST_SIZE 20
442 
443 typedef struct _xmpp_sha1_t xmpp_sha1_t;
444 
445 char *xmpp_sha1(xmpp_ctx_t *ctx, const unsigned char *data, size_t len);
446 void xmpp_sha1_digest(const unsigned char *data, size_t len,
447                       unsigned char *digest);
448 
449 xmpp_sha1_t *xmpp_sha1_new(xmpp_ctx_t *ctx);
450 void xmpp_sha1_free(xmpp_sha1_t *sha1);
451 void xmpp_sha1_update(xmpp_sha1_t *sha1, const unsigned char *data, size_t len);
452 void xmpp_sha1_final(xmpp_sha1_t *sha1);
453 char *xmpp_sha1_to_string(xmpp_sha1_t *sha1, char *s, size_t slen);
454 char *xmpp_sha1_to_string_alloc(xmpp_sha1_t *sha1);
455 void xmpp_sha1_to_digest(xmpp_sha1_t *sha1, unsigned char *digest);
456 
457 /* Base64 */
458 
459 char *xmpp_base64_encode(xmpp_ctx_t *ctx, const unsigned char *data, size_t len);
460 char *xmpp_base64_decode_str(xmpp_ctx_t *ctx, const char *base64, size_t len);
461 void xmpp_base64_decode_bin(xmpp_ctx_t *ctx, const char *base64, size_t len,
462                             unsigned char **out, size_t *outlen);
463 
464 #ifdef __cplusplus
465 }
466 #endif
467 
468 #endif /* __LIBMESODE_MESODE_H__ */
469