comparison libpurple/protocols/msnp9/cmdproc.c @ 21312:a07cfce78345

Add MSNP9 back as an alternative alongside the existing MSN prpl. Cowardly old fools like me who prefer the stability of our MSNP9 code over the features of MSNP14 can enable this using the --disable-msnp14 ./configure option. If we want to release from i.p.p and MSN stability is the only blocker, we can trivially flick the default to use MSNP9 in configure.ac
author Stu Tomlinson <stu@nosnilmot.com>
date Sun, 11 Nov 2007 12:57:52 +0000
parents
children ba47ec8a2477
comparison
equal deleted inserted replaced
21311:7d031cec5ba2 21312:a07cfce78345
1 /**
2 * @file cmdproc.c MSN command processor functions
3 *
4 * purple
5 *
6 * Purple is the legal property of its developers, whose names are too numerous
7 * to list here. Please refer to the COPYRIGHT file distributed with this
8 * source distribution.
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
23 */
24 #include "msn.h"
25 #include "cmdproc.h"
26
27 MsnCmdProc *
28 msn_cmdproc_new(MsnSession *session)
29 {
30 MsnCmdProc *cmdproc;
31
32 cmdproc = g_new0(MsnCmdProc, 1);
33
34 cmdproc->session = session;
35 cmdproc->txqueue = g_queue_new();
36 cmdproc->history = msn_history_new();
37
38 return cmdproc;
39 }
40
41 void
42 msn_cmdproc_destroy(MsnCmdProc *cmdproc)
43 {
44 MsnTransaction *trans;
45
46 while ((trans = g_queue_pop_head(cmdproc->txqueue)) != NULL)
47 msn_transaction_destroy(trans);
48
49 g_queue_free(cmdproc->txqueue);
50
51 msn_history_destroy(cmdproc->history);
52
53 if (cmdproc->last_cmd != NULL)
54 msn_command_destroy(cmdproc->last_cmd);
55
56 g_free(cmdproc);
57 }
58
59 void
60 msn_cmdproc_process_queue(MsnCmdProc *cmdproc)
61 {
62 MsnTransaction *trans;
63
64 while ((trans = g_queue_pop_head(cmdproc->txqueue)) != NULL)
65 msn_cmdproc_send_trans(cmdproc, trans);
66 }
67
68 void
69 msn_cmdproc_queue_trans(MsnCmdProc *cmdproc, MsnTransaction *trans)
70 {
71 g_return_if_fail(cmdproc != NULL);
72 g_return_if_fail(trans != NULL);
73
74 g_queue_push_tail(cmdproc->txqueue, trans);
75 }
76
77 static void
78 show_debug_cmd(MsnCmdProc *cmdproc, gboolean incoming, const char *command)
79 {
80 MsnServConn *servconn;
81 const char *names[] = { "NS", "SB" };
82 char *show;
83 char tmp;
84 size_t len;
85
86 servconn = cmdproc->servconn;
87 len = strlen(command);
88 show = g_strdup(command);
89
90 tmp = (incoming) ? 'S' : 'C';
91
92 if ((show[len - 1] == '\n') && (show[len - 2] == '\r'))
93 {
94 show[len - 2] = '\0';
95 }
96
97 purple_debug_misc("msn", "%c: %s %03d: %s\n", tmp,
98 names[servconn->type], servconn->num, show);
99
100 g_free(show);
101 }
102
103 void
104 msn_cmdproc_send_trans(MsnCmdProc *cmdproc, MsnTransaction *trans)
105 {
106 MsnServConn *servconn;
107 char *data;
108 size_t len;
109
110 g_return_if_fail(cmdproc != NULL);
111 g_return_if_fail(trans != NULL);
112
113 servconn = cmdproc->servconn;
114
115 if (!servconn->connected)
116 return;
117
118 msn_history_add(cmdproc->history, trans);
119
120 data = msn_transaction_to_string(trans);
121
122 len = strlen(data);
123
124 show_debug_cmd(cmdproc, FALSE, data);
125
126 if (trans->callbacks == NULL)
127 trans->callbacks = g_hash_table_lookup(cmdproc->cbs_table->cmds,
128 trans->command);
129
130 if (trans->payload != NULL)
131 {
132 data = g_realloc(data, len + trans->payload_len);
133 memcpy(data + len, trans->payload, trans->payload_len);
134 len += trans->payload_len;
135 }
136
137 msn_servconn_write(servconn, data, len);
138
139 g_free(data);
140 }
141
142 void
143 msn_cmdproc_send_quick(MsnCmdProc *cmdproc, const char *command,
144 const char *format, ...)
145 {
146 MsnServConn *servconn;
147 char *data;
148 char *params = NULL;
149 va_list arg;
150 size_t len;
151
152 g_return_if_fail(cmdproc != NULL);
153 g_return_if_fail(command != NULL);
154
155 servconn = cmdproc->servconn;
156
157 if (!servconn->connected)
158 return;
159
160 if (format != NULL)
161 {
162 va_start(arg, format);
163 params = g_strdup_vprintf(format, arg);
164 va_end(arg);
165 }
166
167 if (params != NULL)
168 data = g_strdup_printf("%s %s\r\n", command, params);
169 else
170 data = g_strdup_printf("%s\r\n", command);
171
172 g_free(params);
173
174 len = strlen(data);
175
176 show_debug_cmd(cmdproc, FALSE, data);
177
178 msn_servconn_write(servconn, data, len);
179
180 g_free(data);
181 }
182
183 void
184 msn_cmdproc_send(MsnCmdProc *cmdproc, const char *command,
185 const char *format, ...)
186 {
187 MsnTransaction *trans;
188 va_list arg;
189
190 g_return_if_fail(cmdproc != NULL);
191 g_return_if_fail(command != NULL);
192
193 if (!cmdproc->servconn->connected)
194 return;
195
196 trans = g_new0(MsnTransaction, 1);
197
198 trans->command = g_strdup(command);
199
200 if (format != NULL)
201 {
202 va_start(arg, format);
203 trans->params = g_strdup_vprintf(format, arg);
204 va_end(arg);
205 }
206
207 msn_cmdproc_send_trans(cmdproc, trans);
208 }
209
210 void
211 msn_cmdproc_process_payload(MsnCmdProc *cmdproc, char *payload,
212 int payload_len)
213 {
214 MsnCommand *last;
215
216 g_return_if_fail(cmdproc != NULL);
217
218 last = cmdproc->last_cmd;
219 last->payload = g_memdup(payload, payload_len);
220 last->payload_len = payload_len;
221
222 if (last->payload_cb != NULL)
223 last->payload_cb(cmdproc, last, payload, payload_len);
224 }
225
226 void
227 msn_cmdproc_process_msg(MsnCmdProc *cmdproc, MsnMessage *msg)
228 {
229 MsnMsgTypeCb cb;
230
231 if (msn_message_get_content_type(msg) == NULL)
232 {
233 purple_debug_misc("msn", "failed to find message content\n");
234 return;
235 }
236
237 cb = g_hash_table_lookup(cmdproc->cbs_table->msgs,
238 msn_message_get_content_type(msg));
239
240 if (cb == NULL)
241 {
242 purple_debug_warning("msn", "Unhandled content-type '%s'\n",
243 msn_message_get_content_type(msg));
244
245 return;
246 }
247
248 cb(cmdproc, msg);
249 }
250
251 void
252 msn_cmdproc_process_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
253 {
254 MsnTransCb cb = NULL;
255 MsnTransaction *trans = NULL;
256
257 if (cmd->trId)
258 trans = msn_history_find(cmdproc->history, cmd->trId);
259
260 if (trans != NULL)
261 if (trans->timer)
262 purple_timeout_remove(trans->timer);
263
264 if (g_ascii_isdigit(cmd->command[0]))
265 {
266 if (trans != NULL)
267 {
268 MsnErrorCb error_cb = NULL;
269 int error;
270
271 error = atoi(cmd->command);
272
273 if (trans->error_cb != NULL)
274 error_cb = trans->error_cb;
275
276 if (error_cb == NULL && cmdproc->cbs_table->errors != NULL)
277 error_cb = g_hash_table_lookup(cmdproc->cbs_table->errors, trans->command);
278
279 if (error_cb != NULL)
280 {
281 error_cb(cmdproc, trans, error);
282 }
283 else
284 {
285 #if 1
286 msn_error_handle(cmdproc->session, error);
287 #else
288 purple_debug_warning("msn", "Unhandled error '%s'\n",
289 cmd->command);
290 #endif
291 }
292
293 return;
294 }
295 }
296
297 if (cmdproc->cbs_table->async != NULL)
298 cb = g_hash_table_lookup(cmdproc->cbs_table->async, cmd->command);
299
300 if (cb == NULL && trans != NULL)
301 {
302 cmd->trans = trans;
303
304 if (trans->callbacks != NULL)
305 cb = g_hash_table_lookup(trans->callbacks, cmd->command);
306 }
307
308 if (cb == NULL && cmdproc->cbs_table->fallback != NULL)
309 cb = g_hash_table_lookup(cmdproc->cbs_table->fallback, cmd->command);
310
311 if (cb != NULL)
312 {
313 cb(cmdproc, cmd);
314 }
315 else
316 {
317 purple_debug_warning("msn", "Unhandled command '%s'\n",
318 cmd->command);
319 }
320
321 if (trans != NULL && trans->pendent_cmd != NULL)
322 msn_transaction_unqueue_cmd(trans, cmdproc);
323 }
324
325 void
326 msn_cmdproc_process_cmd_text(MsnCmdProc *cmdproc, const char *command)
327 {
328 show_debug_cmd(cmdproc, TRUE, command);
329
330 if (cmdproc->last_cmd != NULL)
331 msn_command_destroy(cmdproc->last_cmd);
332
333 cmdproc->last_cmd = msn_command_from_string(command);
334
335 msn_cmdproc_process_cmd(cmdproc, cmdproc->last_cmd);
336 }