jabberd2
2.2.16
|
00001 /* 00002 * jabberd - Jabber Open Source Server 00003 * Copyright (c) 2007 Tomasz Sterna 00004 * 00005 * This program is free software; you can redistribute it and/or modify 00006 * it under the terms of the GNU General Public License as published by 00007 * the Free Software Foundation; version 2 of the License 00008 * 00009 * This program is distributed in the hope that it will be useful, 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the 00012 * GNU General Public License for more details. 00013 * 00014 * You should have received a copy of the GNU General Public License 00015 * along with this program; if not, write to the Free Software 00016 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA02111-1307USA 00017 */ 00018 00019 /* 00020 * this sx plugin implements stanza acknowledgements 00021 * as described in XEP-0198: Stanza Acknowledgements 00022 */ 00023 00024 #include "sx.h" 00025 00026 #define STREAM_ACK_NS_DECL " xmlns:ack='" uri_ACK "'" 00027 00028 static void _sx_ack_header(sx_t s, sx_plugin_t p, sx_buf_t buf) { 00029 00030 log_debug(ZONE, "hacking ack namespace decl onto stream header"); 00031 00032 /* get enough space */ 00033 _sx_buffer_alloc_margin(buf, 0, strlen(STREAM_ACK_NS_DECL) + 2); 00034 00035 /* overwrite the trailing ">" with a decl followed by a new ">" */ 00036 memcpy(&buf->data[buf->len - 1], STREAM_ACK_NS_DECL ">", strlen(STREAM_ACK_NS_DECL)+1); 00037 buf->len += strlen(STREAM_ACK_NS_DECL); 00038 } 00039 00041 static void _sx_ack_features(sx_t s, sx_plugin_t p, nad_t nad) { 00042 /* offer feature only when authenticated and not enabled yet */ 00043 if(s->state == state_OPEN && s->plugin_data[p->index] == NULL) 00044 nad_append_elem(nad, -1, "ack:ack", 1); 00045 } 00046 00048 static int _sx_ack_process(sx_t s, sx_plugin_t p, nad_t nad) { 00049 int attr; 00050 00051 /* not interested if we're not a server */ 00052 if(s->type != type_SERVER) 00053 return 1; 00054 00055 /* only want ack packets */ 00056 if((NAD_ENS(nad, 0) < 0 || NAD_NURI_L(nad, NAD_ENS(nad, 0)) != strlen(uri_ACK) || strncmp(NAD_NURI(nad, NAD_ENS(nad, 0)), uri_ACK, strlen(uri_ACK)) != 0)) 00057 return 1; 00058 00059 /* pings */ 00060 if(NAD_ENAME_L(nad, 0) == 4 && strncmp(NAD_ENAME(nad, 0), "ping", 4) == 0) { 00061 jqueue_push(s->wbufq, _sx_buffer_new("<ack:pong/>", 11, NULL, NULL), 0); 00062 s->want_write = 1; 00063 00064 /* handled the packet */ 00065 nad_free(nad); 00066 return 0; 00067 } 00068 00069 /* enable only when authenticated */ 00070 if(s->state == state_OPEN && NAD_ENAME_L(nad, 0) == 6 && strncmp(NAD_ENAME(nad, 0), "enable", 6) == 0) { 00071 jqueue_push(s->wbufq, _sx_buffer_new("<ack:enabled/>", 14, NULL, NULL), 254); 00072 s->want_write = 1; 00073 00074 s->plugin_data[p->index] = (void *) 1; 00075 00076 /* handled the packet */ 00077 nad_free(nad); 00078 return 0; 00079 } 00080 00081 /* 'r' or 'a' when enabled */ 00082 if(s->plugin_data[p->index] != NULL && NAD_ENAME_L(nad, 0) == 1 && (strncmp(NAD_ENAME(nad, 0), "r", 1) == 0 || strncmp(NAD_ENAME(nad, 0), "a", 1) == 0) ) { 00083 attr = nad_find_attr(nad, 0, -1, "c", NULL); 00084 if(attr >= 0) { 00085 char *buf = (char *) malloc(sizeof(char) * (NAD_AVAL_L(nad, attr) + 13 + 1)); 00086 snprintf(buf, NAD_AVAL_L(nad, attr) + 13 + 1, "<ack:a b='%.*s'/>", NAD_AVAL_L(nad, attr), NAD_AVAL(nad, attr)); 00087 jqueue_push(s->wbufq, _sx_buffer_new(buf, NAD_AVAL_L(nad, attr) + 13, NULL, NULL), 255); 00088 free(buf); 00089 s->want_write = 1; 00090 } 00091 00092 /* handled the packet */ 00093 nad_free(nad); 00094 return 0; 00095 } 00096 00097 _sx_debug(ZONE, "unhandled ack namespace element '%.*s', dropping packet", NAD_ENAME_L(nad, 0), NAD_ENAME(nad, 0)); 00098 nad_free(nad); 00099 return 0; 00100 } 00101 00103 int sx_ack_init(sx_env_t env, sx_plugin_t p, va_list args) { 00104 log_debug(ZONE, "initialising stanza acknowledgements sx plugin"); 00105 00106 p->header = _sx_ack_header; 00107 p->features = _sx_ack_features; 00108 p->process = _sx_ack_process; 00109 00110 return 0; 00111 }