comparison src/protocols/msn/servconn.c @ 5506:4f72b611f0ee

[gaim-migrate @ 5905] A few changes here. - Messages now have reference counting. - There's a message queue API in servconn. This was needed for times when we have a message but need further information from a command before processing it, like initial e-mail notifications. - As a result of the two above, we now have initial e-mail notifications again! committer: Tailor Script <tailor@pidgin.im>
author Christian Hammond <chipx86@chipx86.com>
date Sun, 25 May 2003 09:04:32 +0000
parents c6efac0e28ff
children 46d7ad0dfa26
comparison
equal deleted inserted replaced
5505:870207a49f2f 5506:4f72b611f0ee
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 */ 21 */
22 #include "msn.h" 22 #include "msn.h"
23 #include "servconn.h" 23 #include "servconn.h"
24 24
25 typedef struct
26 {
27 char *command;
28 MsnMessage *msg;
29
30 } MsnQueueEntry;
31
25 static gboolean 32 static gboolean
26 __process_single_line(MsnServConn *servconn, char *str) 33 __process_message(MsnServConn *servconn, MsnMessage *msg)
27 {
28 MsnServConnCommandCb cb;
29 gboolean result;
30 size_t param_count = 0;
31 char *command, *param_start;
32 char **params = NULL;
33
34 command = str;
35
36 /**
37 * See how many spaces we have in this.
38 */
39 param_start = strchr(command, ' ');
40
41 if (param_start != NULL) {
42 params = g_strsplit(param_start + 1, " ", 0);
43
44 for (param_count = 0; params[param_count] != NULL; param_count++)
45 ;
46
47 *param_start = '\0';
48 }
49
50 cb = g_hash_table_lookup(servconn->commands, command);
51
52 if (cb == NULL) {
53 cb = g_hash_table_lookup(servconn->commands, "_UNKNOWN_");
54
55 if (cb == NULL) {
56 gaim_debug(GAIM_DEBUG_WARNING, "msn",
57 "Unhandled command '%s'\n", str);
58
59 if (params != NULL)
60 g_strfreev(params);
61
62 return TRUE;
63 }
64 }
65
66 result = cb(servconn, command, (const char **)params, param_count);
67
68 if (params != NULL)
69 g_strfreev(params);
70
71 return result;
72 }
73
74 static gboolean
75 __process_multi_line(MsnServConn *servconn, char *buffer)
76 { 34 {
77 MsnServConnMsgCb cb; 35 MsnServConnMsgCb cb;
78 MsnMessage *msg;
79 char msg_str[MSN_BUF_LEN];
80
81 g_snprintf(msg_str, sizeof(msg_str),
82 "MSG %s %s %d\r\n%s",
83 servconn->msg_passport, servconn->msg_friendly,
84 servconn->msg_len, buffer);
85
86 msg = msn_message_new_from_str(servconn->session, msg_str);
87 36
88 cb = g_hash_table_lookup(servconn->msg_types, 37 cb = g_hash_table_lookup(servconn->msg_types,
89 msn_message_get_content_type(msg)); 38 msn_message_get_content_type(msg));
90 39
91 if (cb == NULL) { 40 if (cb == NULL) {
92 gaim_debug(GAIM_DEBUG_WARNING, "msn", 41 gaim_debug(GAIM_DEBUG_WARNING, "msn",
93 "Unhandled content-type '%s': %s\n", 42 "Unhandled content-type '%s': %s\n",
94 msn_message_get_content_type(msg), 43 msn_message_get_content_type(msg),
95 msn_message_get_body(msg)); 44 msn_message_get_body(msg));
96 45
97 msn_message_destroy(msg);
98
99 return FALSE; 46 return FALSE;
100 } 47 }
48
49 cb(servconn, msg);
50
51 return TRUE;
52 }
53
54 static gboolean
55 __process_single_line(MsnServConn *servconn, char *str)
56 {
57 MsnServConnCommandCb cb;
58 GSList *l, *l_next;
59 gboolean result;
60 size_t param_count = 0;
61 char *command, *param_start;
62 char **params = NULL;
63
64 command = str;
65
66 /**
67 * See how many spaces we have in this.
68 */
69 param_start = strchr(command, ' ');
70
71 if (param_start != NULL) {
72 params = g_strsplit(param_start + 1, " ", 0);
73
74 for (param_count = 0; params[param_count] != NULL; param_count++)
75 ;
76
77 *param_start = '\0';
78 }
79
80 cb = g_hash_table_lookup(servconn->commands, command);
81
82 if (cb == NULL) {
83 cb = g_hash_table_lookup(servconn->commands, "_UNKNOWN_");
84
85 if (cb == NULL) {
86 gaim_debug(GAIM_DEBUG_WARNING, "msn",
87 "Unhandled command '%s'\n", str);
88
89 if (params != NULL)
90 g_strfreev(params);
91
92 return TRUE;
93 }
94 }
95
96 result = cb(servconn, command, (const char **)params, param_count);
97
98 if (params != NULL)
99 g_strfreev(params);
100
101
102 /* Process all queued messages that are waiting on this command. */
103 for (l = servconn->msg_queue; l != NULL; l = l_next) {
104 MsnQueueEntry *entry = l->data;
105 MsnMessage *msg;
106
107 l_next = l->next;
108
109 if (entry->command == NULL ||
110 !g_ascii_strcasecmp(entry->command, command)) {
111
112 MsnUser *sender;
113
114 msg = entry->msg;
115
116 msn_message_ref(msg);
117
118 msn_servconn_unqueue_message(servconn, entry->msg);
119
120 sender = msn_message_get_sender(msg);
121
122 servconn->msg_passport = g_strdup(msn_user_get_passport(sender));
123 servconn->msg_friendly = g_strdup(msn_user_get_name(sender));
124
125 __process_message(servconn, msg);
126
127 g_free(servconn->msg_passport);
128 g_free(servconn->msg_friendly);
129
130 msn_message_destroy(msg);
131 }
132 }
133
134 return result;
135 }
136
137 static gboolean
138 __process_multi_line(MsnServConn *servconn, char *buffer)
139 {
140 MsnMessage *msg;
141 char msg_str[MSN_BUF_LEN];
142 gboolean result;
143
144 g_snprintf(msg_str, sizeof(msg_str),
145 "MSG %s %s %d\r\n%s",
146 servconn->msg_passport, servconn->msg_friendly,
147 servconn->msg_len, buffer);
101 148
102 gaim_debug(GAIM_DEBUG_MISC, "msn", 149 gaim_debug(GAIM_DEBUG_MISC, "msn",
103 "Message: {%s}\n", buffer); 150 "Message: {%s}\n", buffer);
104 151
105 cb(servconn, msg); 152 msg = msn_message_new_from_str(servconn->session, msg_str);
153
154 result = __process_message(servconn, msg);
106 155
107 msn_message_destroy(msg); 156 msn_message_destroy(msg);
108 157
109 return TRUE; 158 return result;
110 } 159 }
111 160
112 static void 161 static void
113 __connect_cb(gpointer data, gint source, GaimInputCondition cond) 162 __connect_cb(gpointer data, gint source, GaimInputCondition cond)
114 { 163 {
169 if (servconn->inpa) 218 if (servconn->inpa)
170 gaim_input_remove(servconn->inpa); 219 gaim_input_remove(servconn->inpa);
171 220
172 g_free(servconn->rxqueue); 221 g_free(servconn->rxqueue);
173 222
174 while (servconn->txqueue) { 223 while (servconn->txqueue != NULL) {
175 g_free(servconn->txqueue->data); 224 g_free(servconn->txqueue->data);
176 225
177 servconn->txqueue = g_slist_remove(servconn->txqueue, 226 servconn->txqueue = g_slist_remove(servconn->txqueue,
178 servconn->txqueue->data); 227 servconn->txqueue->data);
228 }
229
230 while (servconn->msg_queue != NULL) {
231 MsnQueueEntry *entry = servconn->msg_queue->data;
232
233 msn_servconn_unqueue_message(servconn, entry->msg);
179 } 234 }
180 235
181 servconn->connected = FALSE; 236 servconn->connected = FALSE;
182 } 237 }
183 238
271 else 326 else
272 g_snprintf(buf, sizeof(buf), "%s %u %s\r\n", 327 g_snprintf(buf, sizeof(buf), "%s %u %s\r\n",
273 command, servconn->session->trId++, params); 328 command, servconn->session->trId++, params);
274 329
275 return (msn_servconn_write(servconn, buf, strlen(buf)) > 0); 330 return (msn_servconn_write(servconn, buf, strlen(buf)) > 0);
331 }
332
333 void
334 msn_servconn_queue_message(MsnServConn *servconn, const char *command,
335 MsnMessage *msg)
336 {
337 MsnQueueEntry *entry;
338
339 g_return_if_fail(servconn != NULL);
340 g_return_if_fail(msg != NULL);
341
342 entry = g_new0(MsnQueueEntry, 1);
343 entry->msg = msg;
344 entry->command = (command == NULL ? NULL : g_strdup(command));
345
346 servconn->msg_queue = g_slist_append(servconn->msg_queue, entry);
347
348 msn_message_ref(msg);
349 }
350
351 void
352 msn_servconn_unqueue_message(MsnServConn *servconn, MsnMessage *msg)
353 {
354 MsnQueueEntry *entry = NULL;
355 GSList *l;
356
357 g_return_if_fail(servconn != NULL);
358 g_return_if_fail(msg != NULL);
359
360 for (l = servconn->msg_queue; l != NULL; l = l->next) {
361 entry = l->data;
362
363 if (entry->msg == msg)
364 break;
365
366 entry = NULL;
367 }
368
369 g_return_if_fail(entry != NULL);
370
371 msn_message_unref(msg);
372
373 servconn->msg_queue = g_slist_remove(servconn->msg_queue, entry);
374
375 if (entry->command != NULL)
376 g_free(entry->command);
377
378 g_free(entry);
276 } 379 }
277 380
278 void 381 void
279 msn_servconn_register_command(MsnServConn *servconn, const char *command, 382 msn_servconn_register_command(MsnServConn *servconn, const char *command,
280 MsnServConnCommandCb cb) 383 MsnServConnCommandCb cb)