1 /*
2 * jabberd - Jabber Open Source Server
3 * Copyright (c) 2002 Jeremie Miller, Thomas Muldowney,
4 * Ryan Eatmon, Robert Norris
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA02111-1307USA
19 */
20
21 #include "sx.h"
22
23 /** if you change these, reflect your changes in the defines in sx.h */
24 static const char *_stream_errors[] = {
25 "bad-format",
26 "bad-namespace-prefix",
27 "conflict",
28 "connection-timeout",
29 "host-gone",
30 "host-unknown",
31 "improper-addressing",
32 "internal-server-error",
33 "invalid-from",
34 "invalid-id",
35 "invalid-namespace",
36 "invalid-xml",
37 "not-authorized",
38 "policy-violation",
39 "remote-connection-failed",
40 "restricted-xml",
41 "resource-constraint",
42 "see-other-host",
43 "system-shutdown",
44 "undefined-condition",
45 "unsupported-encoding",
46 "unsupported-stanza-type",
47 "unsupported-version",
48 "xml-not-well-formed",
49 NULL
50 };
51
52 /** send an error */
_sx_error(sx_t s,int err,const char * text)53 void _sx_error(sx_t s, int err, const char *text) {
54 int len = 0;
55 sx_buf_t buf;
56
57 /* open stream if not already */
58 if(s->state < state_STREAM) {
59 if (s->flags & SX_WEBSOCKET_WRAPPER)
60 jqueue_push(s->wbufq, _sx_buffer_new("<open xmlns='" uri_XFRAMING "' version='1.0' />", sizeof(uri_XFRAMING) + 30, NULL, NULL), 0);
61 else
62 jqueue_push(s->wbufq, _sx_buffer_new("<stream:stream xmlns:stream='" uri_STREAMS "' version='1.0'>", sizeof(uri_STREAMS) + 44, NULL, NULL), 0);
63 }
64
65 /* build the error */
66 len = strlen(uri_STREAMS) + strlen(uri_STREAM_ERR) + strlen(_stream_errors[err]) + 58;
67 if(text != NULL) len += strlen(uri_STREAM_ERR) + strlen(text) + 22;
68
69 buf = _sx_buffer_new(NULL, len, NULL, NULL);
70
71 if(text == NULL)
72 len = sprintf(buf->data, "<stream:error xmlns:stream='" uri_STREAMS "'><%s xmlns='" uri_STREAM_ERR "'/></stream:error>", _stream_errors[err]);
73 else
74 len = sprintf(buf->data, "<stream:error xmlns:stream='" uri_STREAMS "'><%s xmlns='" uri_STREAM_ERR "'/><text xmlns='" uri_STREAM_ERR "'>%s</text></stream:error>", _stream_errors[err], text);
75
76 buf->len--;
77 assert(len == buf->len);
78
79 _sx_debug(ZONE, "prepared error: %.*s", buf->len, buf->data);
80 jqueue_push(s->wbufq, buf, 0);
81
82 /* close the stream if needed */
83 if(s->state < state_STREAM) {
84 if (s->flags & SX_WEBSOCKET_WRAPPER)
85 jqueue_push(s->wbufq, _sx_buffer_new("<close xmlns='" uri_XFRAMING "' />", sizeof(uri_XFRAMING) + 17, NULL, NULL), 0);
86 else
87 jqueue_push(s->wbufq, _sx_buffer_new("</stream:stream>", 16, NULL, NULL), 0);
88 }
89
90 /* stuff to write */
91 s->want_write = 1;
92 }
93
sx_error(sx_t s,int err,const char * text)94 void sx_error(sx_t s, int err, const char *text) {
95 assert(s != NULL);
96 assert(err >= 0 && err < stream_err_LAST);
97
98 _sx_error(s, err, text);
99
100 _sx_event(s, event_WANT_WRITE, NULL);
101 }
102
103 //** send an extended error with custom contents other than text */
104 // Ideally should be merged with sx_error. sx_error should permit additional content beneath the <stream:error> element, other than a <text> node.
_sx_error_extended(sx_t s,int err,const char * content)105 void _sx_error_extended(sx_t s, int err, const char *content) {
106 int len = 0;
107 sx_buf_t buf;
108
109 /* build the string */
110 if(s->state < state_STREAM) len = strlen(uri_STREAMS) + 61;
111 len += strlen(uri_STREAMS) + strlen(uri_STREAM_ERR) + strlen(_stream_errors[err]) + 58;
112 if(content != NULL) len += strlen(content) + strlen(_stream_errors[err]) + 2;
113
114 buf = _sx_buffer_new(NULL, len, NULL, NULL);
115 len = 0;
116
117 if(s->state < state_STREAM)
118 len = sprintf(buf->data, "<stream:stream xmlns:stream='" uri_STREAMS "' version='1.0'>");
119
120 if(content == NULL)
121 len += sprintf(&(buf->data[len]), "<stream:error xmlns:stream='" uri_STREAMS "'><%s xmlns='" uri_STREAM_ERR "'/></stream:error>", _stream_errors[err]);
122 else
123 len += sprintf(&(buf->data[len]), "<stream:error xmlns:stream='" uri_STREAMS "'><%s xmlns='" uri_STREAM_ERR "'>%s</%s></stream:error>", _stream_errors[err], content, _stream_errors[err]);
124
125 if(s->state < state_STREAM)
126 len += sprintf(&(buf->data[len]), "</stream:stream>");
127
128 buf->len--;
129 assert(len == buf->len);
130
131 _sx_debug(ZONE, "prepared error: %.*s", buf->len, buf->data);
132
133 /* go */
134 jqueue_push(s->wbufq, buf, 0);
135
136 /* stuff to write */
137 s->want_write = 1;
138 }
139
sx_error_extended(sx_t s,int err,const char * content)140 void sx_error_extended(sx_t s, int err, const char *content) {
141 assert(s != NULL);
142 assert(err >= 0 && err < stream_err_LAST);
143
144 _sx_error_extended(s, err, content);
145
146 _sx_event(s, event_WANT_WRITE, NULL);
147 }
148