comparison src/protocols/yahoo/yahoo_packet.c @ 10392:a8f9e5ce4f92

[gaim-migrate @ 11620] a little bit of clean up and reorganization of the yahoo prpl. I moved the packet functions to their own file, renamed a couple of them, added a convience function and used it a lot. I plan on adding several more convience functions. committer: Tailor Script <tailor@pidgin.im>
author Tim Ringenbach <marv@pidgin.im>
date Thu, 16 Dec 2004 21:47:54 +0000
parents
children 45a0a07e8b25
comparison
equal deleted inserted replaced
10391:38256d3e8324 10392:a8f9e5ce4f92
1 /*
2 * gaim
3 *
4 * Gaim is the legal property of its developers, whose names are too numerous
5 * to list here. Please refer to the COPYRIGHT file distributed with this
6 * source distribution.
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 *
22 */
23
24 #include "internal.h"
25 #include "debug.h"
26
27 #include "yahoo.h"
28 #include "yahoo_packet.h"
29
30 struct yahoo_packet *yahoo_packet_new(enum yahoo_service service, enum yahoo_status status, int id)
31 {
32 struct yahoo_packet *pkt = g_new0(struct yahoo_packet, 1);
33
34 pkt->service = service;
35 pkt->status = status;
36 pkt->id = id;
37
38 return pkt;
39 }
40
41 void yahoo_packet_hash(struct yahoo_packet *pkt, int key, const char *value)
42 {
43 struct yahoo_pair *pair = g_new0(struct yahoo_pair, 1);
44 pair->key = key;
45 pair->value = g_strdup(value);
46 pkt->hash = g_slist_append(pkt->hash, pair);
47 }
48
49 int yahoo_packet_length(struct yahoo_packet *pkt)
50 {
51 GSList *l;
52
53 int len = 0;
54
55 l = pkt->hash;
56 while (l) {
57 struct yahoo_pair *pair = l->data;
58 int tmp = pair->key;
59 do {
60 tmp /= 10;
61 len++;
62 } while (tmp);
63 len += 2;
64 len += strlen(pair->value);
65 len += 2;
66 l = l->next;
67 }
68
69 return len;
70 }
71
72 void yahoo_packet_read(struct yahoo_packet *pkt, guchar *data, int len)
73 {
74 int pos = 0;
75
76 while (pos + 1 < len) {
77 char key[64], *value = NULL, *esc;
78 int accept;
79 int x;
80
81 struct yahoo_pair *pair = g_new0(struct yahoo_pair, 1);
82
83 /* this is weird, and in one of the chat packets, and causes us
84 * think all the values are keys and all the keys are values after
85 * this point if we don't handle it */
86 if (data[pos] == '\0') {
87 while (pos + 1 < len) {
88 if (data[pos] == 0xc0 && data[pos + 1] == 0x80)
89 break;
90 pos++;
91 }
92 pos += 2;
93 g_free(pair);
94 continue;
95 }
96
97 x = 0;
98 while (pos + 1 < len) {
99 if (data[pos] == 0xc0 && data[pos + 1] == 0x80)
100 break;
101 if (x >= sizeof(key)-1) {
102 x++;
103 pos++;
104 continue;
105 }
106 key[x++] = data[pos++];
107 }
108 if (x >= sizeof(key)-1) {
109 x = 0;
110 }
111 key[x] = 0;
112 pos += 2;
113 pair->key = strtol(key, NULL, 10);
114 accept = x; /* if x is 0 there was no key, so don't accept it */
115
116 if (len - pos + 1 <= 0) {
117 /* Truncated. Garbage or something. */
118 accept = 0;
119 }
120
121 if (accept) {
122 value = g_malloc(len - pos + 1);
123 x = 0;
124 while (pos + 1 < len) {
125 if (data[pos] == 0xc0 && data[pos + 1] == 0x80)
126 break;
127 value[x++] = data[pos++];
128 }
129 value[x] = 0;
130 pair->value = g_strdup(value);
131 g_free(value);
132 pkt->hash = g_slist_append(pkt->hash, pair);
133 esc = g_strescape(pair->value, NULL);
134 gaim_debug(GAIM_DEBUG_MISC, "yahoo",
135 "Key: %d \tValue: %s\n", pair->key, esc);
136 g_free(esc);
137 } else {
138 g_free(pair);
139 }
140 pos += 2;
141
142 /* Skip over garbage we've noticed in the mail notifications */
143 if (data[0] == '9' && data[pos] == 0x01)
144 pos++;
145 }
146 }
147
148 void yahoo_packet_write(struct yahoo_packet *pkt, guchar *data)
149 {
150 GSList *l = pkt->hash;
151 int pos = 0;
152
153 while (l) {
154 struct yahoo_pair *pair = l->data;
155 guchar buf[100];
156
157 g_snprintf(buf, sizeof(buf), "%d", pair->key);
158 strcpy(data + pos, buf);
159 pos += strlen(buf);
160 data[pos++] = 0xc0;
161 data[pos++] = 0x80;
162
163 strcpy(data + pos, pair->value);
164 pos += strlen(pair->value);
165 data[pos++] = 0xc0;
166 data[pos++] = 0x80;
167
168 l = l->next;
169 }
170 }
171
172 void yahoo_packet_dump(guchar *data, int len)
173 {
174 #ifdef YAHOO_DEBUG
175 int i;
176
177 gaim_debug(GAIM_DEBUG_MISC, "yahoo", "");
178
179 for (i = 0; i + 1 < len; i += 2) {
180 if ((i % 16 == 0) && i) {
181 gaim_debug(GAIM_DEBUG_MISC, NULL, "\n");
182 gaim_debug(GAIM_DEBUG_MISC, "yahoo", "");
183 }
184
185 gaim_debug(GAIM_DEBUG_MISC, NULL, "%02x%02x ", data[i], data[i + 1]);
186 }
187 if (i < len)
188 gaim_debug(GAIM_DEBUG_MISC, NULL, "%02x", data[i]);
189
190 gaim_debug(GAIM_DEBUG_MISC, NULL, "\n");
191 gaim_debug(GAIM_DEBUG_MISC, "yahoo", "");
192
193 for (i = 0; i < len; i++) {
194 if ((i % 16 == 0) && i) {
195 gaim_debug(GAIM_DEBUG_MISC, NULL, "\n");
196 gaim_debug(GAIM_DEBUG_MISC, "yahoo", "");
197 }
198
199 if (g_ascii_isprint(data[i]))
200 gaim_debug(GAIM_DEBUG_MISC, NULL, "%c ", data[i]);
201 else
202 gaim_debug(GAIM_DEBUG_MISC, NULL, ". ");
203 }
204
205 gaim_debug(GAIM_DEBUG_MISC, NULL, "\n");
206 #endif
207 }
208
209 int yahoo_packet_send(struct yahoo_packet *pkt, struct yahoo_data *yd)
210 {
211 int pktlen = yahoo_packet_length(pkt);
212 int len = YAHOO_PACKET_HDRLEN + pktlen;
213 int ret;
214
215 guchar *data;
216 int pos = 0;
217
218 if (yd->fd < 0)
219 return -1;
220
221 data = g_malloc0(len + 1);
222
223 memcpy(data + pos, "YMSG", 4); pos += 4;
224
225 if (yd->wm)
226 pos += yahoo_put16(data + pos, YAHOO_WEBMESSENGER_PROTO_VER);
227 else
228 pos += yahoo_put16(data + pos, YAHOO_PROTO_VER);
229
230 pos += yahoo_put16(data + pos, 0x0000);
231 pos += yahoo_put16(data + pos, pktlen);
232 pos += yahoo_put16(data + pos, pkt->service);
233 pos += yahoo_put32(data + pos, pkt->status);
234 pos += yahoo_put32(data + pos, pkt->id);
235
236 yahoo_packet_write(pkt, data + pos);
237
238 yahoo_packet_dump(data, len);
239 ret = write(yd->fd, data, len);
240 if (ret != len)
241 gaim_debug_warning("yahoo", "Only wrote %d of %d bytes!", ret, len);
242 g_free(data);
243
244 return ret;
245 }
246
247 int yahoo_packet_send_and_free(struct yahoo_packet *pkt, struct yahoo_data *yd)
248 {
249 int ret;
250
251 ret = yahoo_packet_send(pkt, yd);
252 yahoo_packet_free(pkt);
253 return ret;
254 }
255
256 int yahoo_packet_send_special(struct yahoo_packet *pkt, int fd, int pad)
257 {
258 int pktlen = yahoo_packet_length(pkt);
259 int len = YAHOO_PACKET_HDRLEN + pktlen;
260 int ret;
261
262 guchar *data;
263 int pos = 0;
264
265 if (fd < 0)
266 return -1;
267
268 data = g_malloc0(len + 1);
269
270 memcpy(data + pos, "YMSG", 4); pos += 4;
271
272 pos += yahoo_put16(data + pos, YAHOO_PROTO_VER);
273
274 pos += yahoo_put16(data + pos, 0x0000);
275 pos += yahoo_put16(data + pos, pktlen + pad);
276 pos += yahoo_put16(data + pos, pkt->service);
277 pos += yahoo_put32(data + pos, pkt->status);
278 pos += yahoo_put32(data + pos, pkt->id);
279
280 yahoo_packet_write(pkt, data + pos);
281
282 ret = write(fd, data, len);
283 g_free(data);
284
285 return ret;
286 }
287
288 void yahoo_packet_free(struct yahoo_packet *pkt)
289 {
290 while (pkt->hash) {
291 struct yahoo_pair *pair = pkt->hash->data;
292 g_free(pair->value);
293 g_free(pair);
294 pkt->hash = g_slist_remove(pkt->hash, pair);
295 }
296 g_free(pkt);
297 }