Mercurial > pidgin
annotate libfaim/aim_chat.c @ 312:3069be4c291e
[gaim-migrate @ 322]
I don't know why I did this. I have homework due in 15 hours that I haven't
started yet, and it's in a language I don't know and it's a project I don't
understand. If my teacher knew about this, he would be pissed. He looks
pissed all the time, even when he's not. When he smiles he looks devilish.
Maybe I only think that because literally half the class flunked the midterm.
I am not joking about that. More people got F's than A, B, and C combined.
It's 2 am and the homework's due at 5 tomorrow so what do I do? Get chat to
work. Wow. That's going to look good on my resume. "Why did you flunk this
class?" "Because I was getting chat in Instant Messenger to work." Not that
that's not something to be proud of, but I wonder which is more important to
employers. The big battle, experience versus education. Just because you
got good grades in college doesn't mean you're smarter than someone who
flunked, it just means you put in the effort necessary to get a better grade
and the other person didn't. Maybe the person who flunked was working on
real honest-to-god actually *used* software, as opposed to some stupid tree
that only gets used for a fringe branch of computer science that doesn't
offer much more than a normal heap or binary search tree offers. Maybe the
person was out there reverse-engineering protocols and allowing cross-
platform communication to occur, creating interoperability and causing a
greater demand not only for the product, but for the platform it runs on!
Given the choices, who would you pick? Someone who was told how to code a
tree and managed to get it to work, or someone who increases your userbase
and marketability?
Enough of my rant for a while. I've had waaaaay too much sugar (gummy candy is
deadly).
committer: Tailor Script <tailor@pidgin.im>
author | Eric Warmenhoven <eric@warmenhoven.org> |
---|---|
date | Fri, 02 Jun 2000 09:11:48 +0000 |
parents | 0f14e6d8a51b |
children | 8cdc4ab449ec |
rev | line source |
---|---|
2 | 1 /* |
2 * aim_chat.c | |
3 * | |
4 * Routines for the Chat service. Nothing works (yet). | |
5 * | |
6 */ | |
7 | |
283
0f14e6d8a51b
[gaim-migrate @ 293]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
237
diff
changeset
|
8 #include <faim/aim.h> |
237 | 9 |
10 char *aim_chat_getname(struct aim_conn_t *conn) | |
11 { | |
12 if (!conn) | |
13 return NULL; | |
14 if (conn->type != AIM_CONN_TYPE_CHAT) | |
15 return NULL; | |
16 | |
17 return (char *)conn->priv; /* yuck ! */ | |
18 } | |
19 | |
20 struct aim_conn_t *aim_chat_getconn(struct aim_session_t *sess, char *name) | |
21 { | |
22 int i; | |
23 | |
24 for (i=0;i<AIM_CONN_MAX;i++) | |
25 { | |
26 if (sess->conns[i].type == AIM_CONN_TYPE_CHAT) | |
27 { | |
28 if (sess->conns[i].priv) | |
29 if (!strcmp((char *)sess->conns[i].priv, name)) | |
30 { | |
31 return &sess->conns[i]; | |
32 } | |
33 } | |
34 } | |
35 return NULL; | |
36 } | |
37 | |
38 int aim_chat_attachname(struct aim_conn_t *conn, char *roomname) | |
39 { | |
40 if (!conn || !roomname) | |
41 return -1; | |
42 | |
43 conn->priv = malloc(strlen(roomname)+1); | |
44 strcpy(conn->priv, roomname); | |
45 | |
46 return 0; | |
47 } | |
48 | |
49 u_long aim_chat_send_im(struct aim_session_t *sess, | |
50 struct aim_conn_t *conn, | |
51 char *msg) | |
52 { | |
53 | |
54 int curbyte,i; | |
55 struct command_tx_struct *newpacket; | |
56 | |
57 if (!sess || !conn || !msg) | |
58 return 0; | |
59 | |
60 if (!(newpacket = aim_tx_new(0x0002, conn, 1152))) | |
61 return -1; | |
62 | |
63 newpacket->lock = 1; /* lock struct */ | |
64 | |
65 curbyte = 0; | |
66 curbyte += aim_putsnac(newpacket->data+curbyte, | |
67 0x000e, 0x0005, 0x0000, sess->snac_nextid); | |
68 | |
69 /* | |
70 * Generate a random message cookie | |
71 */ | |
72 for (i=0;i<8;i++) | |
73 curbyte += aimutil_put8(newpacket->data+curbyte, (u_char) random()); | |
74 | |
75 /* | |
76 * metaTLV start. -- i assume this is a metaTLV. it could be the | |
77 * channel ID though. | |
78 */ | |
79 curbyte += aimutil_put16(newpacket->data+curbyte, 0x0003); | |
80 | |
81 /* | |
82 * Type 1: Unknown. Blank. | |
83 */ | |
84 curbyte += aimutil_put16(newpacket->data+curbyte, 0x0001); | |
85 curbyte += aimutil_put16(newpacket->data+curbyte, 0x0000); | |
86 | |
87 /* | |
88 * Type 6: Unknown. Blank. | |
89 */ | |
90 curbyte += aimutil_put16(newpacket->data+curbyte, 0x0006); | |
91 curbyte += aimutil_put16(newpacket->data+curbyte, 0x0000); | |
92 | |
93 /* | |
94 * Type 5: Message block. Contains more TLVs. | |
95 * | |
96 * This could include other information... We just | |
97 * put in a message TLV however. | |
98 * | |
99 */ | |
100 curbyte += aimutil_put16(newpacket->data+curbyte, 0x0005); | |
101 curbyte += aimutil_put16(newpacket->data+curbyte, strlen(msg)+4); | |
102 | |
103 /* | |
104 * SubTLV: Type 1: Message | |
105 */ | |
106 curbyte += aim_puttlv_str(newpacket->data+curbyte, 0x0001, strlen(msg), msg); | |
107 | |
108 newpacket->commandlen = curbyte; | |
109 | |
110 newpacket->lock = 0; | |
111 aim_tx_enqueue(sess, newpacket); | |
112 | |
113 return (sess->snac_nextid++); | |
114 } | |
2 | 115 |
116 /* | |
237 | 117 * Join a room of name roomname. This is the first |
118 * step to joining an already created room. It's | |
119 * basically a Service Request for family 0x000e, | |
120 * with a little added on to specify the exchange | |
121 * and room name. | |
2 | 122 * |
123 */ | |
237 | 124 u_long aim_chat_join(struct aim_session_t *sess, |
125 struct aim_conn_t *conn, | |
126 u_short exchange, | |
127 const char *roomname) | |
2 | 128 { |
237 | 129 struct command_tx_struct *newpacket; |
130 int i; | |
131 | |
132 if (!sess || !conn || !roomname) | |
133 return 0; | |
2 | 134 |
237 | 135 if (!(newpacket = aim_tx_new(0x0002, conn, 10+9+strlen(roomname)+2))) |
136 return -1; | |
2 | 137 |
237 | 138 newpacket->lock = 1; |
139 | |
140 i = aim_putsnac(newpacket->data, 0x0001, 0x0004, 0x0000, sess->snac_nextid); | |
2 | 141 |
237 | 142 i+= aimutil_put16(newpacket->data+i, 0x000e); |
2 | 143 |
237 | 144 /* |
145 * this is techinally a TLV, but we can't use normal functions | |
146 * because we need the extraneous nulls and other weird things. | |
147 */ | |
148 i+= aimutil_put16(newpacket->data+i, 0x0001); | |
149 i+= aimutil_put16(newpacket->data+i, 2+1+strlen(roomname)+2); | |
150 i+= aimutil_put16(newpacket->data+i, exchange); | |
151 i+= aimutil_put8(newpacket->data+i, strlen(roomname)); | |
152 memcpy(newpacket->data+i, roomname, strlen(roomname)); | |
153 i+= strlen(roomname); | |
154 //i+= aimutil_putstr(newpacket->data+i, roomname, strlen(roomname)); | |
155 i+= aimutil_put16(newpacket->data+i, 0x0000); | |
2 | 156 |
237 | 157 /* |
158 * Chat hack. | |
159 * | |
160 * XXX: A problem occurs here if we request a channel | |
161 * join but it fails....pendingjoin will be nonnull | |
162 * even though the channel is never going to get a | |
163 * redirect! | |
164 * | |
165 */ | |
166 sess->pendingjoin = (char *)malloc(strlen(roomname)+1); | |
167 strcpy(sess->pendingjoin, roomname); | |
2 | 168 |
237 | 169 newpacket->lock = 0; |
170 aim_tx_enqueue(sess, newpacket); | |
2 | 171 |
237 | 172 #if 0 |
2 | 173 { |
174 struct aim_snac_t snac; | |
175 | |
237 | 176 snac.id = sess->snac_nextid; |
2 | 177 snac.family = 0x0001; |
178 snac.type = 0x0004; | |
179 snac.flags = 0x0000; | |
180 | |
237 | 181 snac.data = malloc(strlen(roomname)+1); |
182 strcpy(snac.data, roomname); | |
2 | 183 |
237 | 184 aim_newsnac(sess, &snac); |
2 | 185 } |
186 | |
237 | 187 #endif |
188 return (sess->snac_nextid++); | |
189 } | |
190 | |
191 int aim_chat_readroominfo(u_char *buf, struct aim_chat_roominfo *outinfo) | |
192 { | |
193 int namelen = 0; | |
194 int i = 0; | |
195 | |
196 if (!buf || !outinfo) | |
197 return 0; | |
198 | |
199 outinfo->exchange = aimutil_get16(buf+i); | |
200 i += 2; | |
201 | |
202 namelen = aimutil_get8(buf+i); | |
203 i += 1; | |
204 | |
205 outinfo->name = (char *)malloc(namelen+1); | |
206 memcpy(outinfo->name, buf+i, namelen); | |
207 outinfo->name[namelen] = '\0'; | |
208 i += namelen; | |
209 | |
210 outinfo->instance = aimutil_get16(buf+i); | |
211 i += 2; | |
212 | |
213 return i; | |
214 }; | |
215 | |
216 | |
217 /* | |
218 * General room information. Lots of stuff. | |
219 * | |
220 * Values I know are in here but I havent attached | |
221 * them to any of the 'Unknown's: | |
222 * - Language (English) | |
223 * | |
224 */ | |
225 int aim_chat_parse_infoupdate(struct aim_session_t *sess, | |
226 struct command_rx_struct *command) | |
227 { | |
228 struct aim_userinfo_s *userinfo = NULL; | |
229 rxcallback_t userfunc=NULL; | |
230 int ret = 1, i = 0; | |
231 int usercount = 0; | |
232 u_char detaillevel = 0; | |
233 char *roomname = NULL; | |
234 struct aim_chat_roominfo roominfo; | |
235 u_short tlvcount = 0; | |
236 struct aim_tlvlist_t *tlvlist; | |
237 char *roomdesc = NULL; | |
238 | |
239 i = 10; | |
240 i += aim_chat_readroominfo(command->data+i, &roominfo); | |
241 | |
242 detaillevel = aimutil_get8(command->data+i); | |
243 i++; | |
244 | |
245 tlvcount = aimutil_get16(command->data+i); | |
246 i += 2; | |
247 | |
248 /* | |
249 * Everything else are TLVs. | |
250 */ | |
251 tlvlist = aim_readtlvchain(command->data+i, command->commandlen-i); | |
252 | |
253 /* | |
254 * TLV type 0x006a is the room name in Human Readable Form. | |
255 */ | |
256 if (aim_gettlv(tlvlist, 0x006a, 1)) | |
257 roomname = aim_gettlv_str(tlvlist, 0x006a, 1); | |
258 | |
259 /* | |
260 * Type 0x006f: Number of occupants. | |
261 */ | |
262 if (aim_gettlv(tlvlist, 0x006f, 1)) | |
263 { | |
264 struct aim_tlv_t *tmptlv; | |
265 tmptlv = aim_gettlv(tlvlist, 0x006f, 1); | |
266 | |
267 usercount = aimutil_get16(tmptlv->value); | |
268 } | |
269 | |
270 /* | |
271 * Type 0x0073: Occupant list. | |
272 */ | |
273 if (aim_gettlv(tlvlist, 0x0073, 1)) | |
274 { | |
275 int curoccupant = 0; | |
276 struct aim_tlv_t *tmptlv; | |
277 | |
278 tmptlv = aim_gettlv(tlvlist, 0x0073, 1); | |
279 | |
280 /* Allocate enough userinfo structs for all occupants */ | |
281 userinfo = calloc(usercount, sizeof(struct aim_userinfo_s)); | |
282 | |
283 i = 0; | |
284 while (curoccupant < usercount) | |
285 i += aim_extractuserinfo(tmptlv->value+i, &userinfo[curoccupant++]); | |
286 } | |
287 | |
288 /* | |
289 * Type 0x00c9: Unknown. | |
290 */ | |
291 if (aim_gettlv(tlvlist, 0x00c9, 1)) | |
292 ; | |
293 | |
294 /* | |
295 * Type 0x00ca: Creation date | |
296 */ | |
297 if (aim_gettlv(tlvlist, 0x00ca, 1)) | |
298 ; | |
299 | |
300 /* | |
301 * Type 0x00d1: Maximum Message Length | |
302 */ | |
303 if (aim_gettlv(tlvlist, 0x00d1, 1)) | |
304 ; | |
305 | |
306 /* | |
307 * Type 0x00d2: Unknown. | |
308 */ | |
309 if (aim_gettlv(tlvlist, 0x00d2, 1)) | |
310 ; | |
311 | |
312 /* | |
313 * Type 0x00d3: Room Description | |
314 */ | |
315 if (aim_gettlv(tlvlist, 0x00d3, 1)) | |
316 roomdesc = aim_gettlv_str(tlvlist, 0x00d3, 1); | |
317 | |
318 /* | |
319 * Type 0x00d5: Unknown. | |
320 */ | |
321 if (aim_gettlv(tlvlist, 0x00d5, 1)) | |
322 ; | |
323 | |
324 | |
325 userfunc = aim_callhandler(command->conn, AIM_CB_FAM_CHT, AIM_CB_CHT_ROOMINFOUPDATE); | |
326 if (userfunc) | |
327 { | |
328 ret = userfunc(sess, | |
329 command, | |
330 &roominfo, | |
331 roomname, | |
332 usercount, | |
333 userinfo, | |
334 roomdesc); | |
335 } | |
336 free(roominfo.name); | |
337 free(userinfo); | |
338 free(roomname); | |
339 free(roomdesc); | |
340 aim_freetlvchain(&tlvlist); | |
341 | |
342 return ret; | |
2 | 343 } |
237 | 344 |
345 int aim_chat_parse_joined(struct aim_session_t *sess, | |
346 struct command_rx_struct *command) | |
347 { | |
348 struct aim_userinfo_s *userinfo = NULL; | |
349 rxcallback_t userfunc=NULL; | |
350 int i = 10, curcount = 0, ret = 1; | |
351 | |
352 while (i < command->commandlen) | |
353 { | |
354 curcount++; | |
355 userinfo = realloc(userinfo, curcount * sizeof(struct aim_userinfo_s)); | |
356 i += aim_extractuserinfo(command->data+i, &userinfo[curcount-1]); | |
357 } | |
358 | |
359 userfunc = aim_callhandler(command->conn, AIM_CB_FAM_CHT, AIM_CB_CHT_USERJOIN); | |
360 if (userfunc) | |
361 { | |
362 ret = userfunc(sess, | |
363 command, | |
364 curcount, | |
365 userinfo); | |
366 } | |
367 | |
368 free(userinfo); | |
369 | |
370 return ret; | |
371 } | |
372 | |
373 int aim_chat_parse_leave(struct aim_session_t *sess, | |
374 struct command_rx_struct *command) | |
375 { | |
376 | |
377 struct aim_userinfo_s *userinfo = NULL; | |
378 rxcallback_t userfunc=NULL; | |
379 int i = 10, curcount = 0, ret = 1; | |
380 | |
381 while (i < command->commandlen) | |
382 { | |
383 curcount++; | |
384 userinfo = realloc(userinfo, curcount * sizeof(struct aim_userinfo_s)); | |
385 i += aim_extractuserinfo(command->data+i, &userinfo[curcount-1]); | |
386 } | |
387 | |
388 userfunc = aim_callhandler(command->conn, AIM_CB_FAM_CHT, AIM_CB_CHT_USERLEAVE); | |
389 if (userfunc) | |
390 { | |
391 ret = userfunc(sess, | |
392 command, | |
393 curcount, | |
394 userinfo); | |
395 } | |
396 | |
397 free(userinfo); | |
398 | |
399 return ret; | |
400 } | |
401 | |
402 /* | |
403 * We could probably include this in the normal ICBM parsing | |
404 * code as channel 0x0003, however, since only the start | |
405 * would be the same, we might as well do it here. | |
406 */ | |
407 int aim_chat_parse_incoming(struct aim_session_t *sess, | |
408 struct command_rx_struct *command) | |
409 { | |
410 struct aim_userinfo_s userinfo; | |
411 rxcallback_t userfunc=NULL; | |
412 int ret = 1, i = 0, z = 0; | |
413 u_char cookie[8]; | |
414 int channel; | |
415 struct aim_tlvlist_t *outerlist; | |
416 char *msg = NULL; | |
417 | |
418 memset(&userinfo, 0x00, sizeof(struct aim_userinfo_s)); | |
419 | |
420 i = 10; /* skip snac */ | |
421 | |
422 /* | |
423 * ICBM Cookie. Ignore it. | |
424 */ | |
425 for (z=0; z<8; z++,i++) | |
426 cookie[z] = command->data[i]; | |
427 | |
428 /* | |
429 * Channel ID | |
430 * | |
431 * Channels 1 and 2 are implemented in the normal ICBM | |
432 * parser. | |
433 * | |
434 * We only do channel 3 here. | |
435 * | |
436 */ | |
437 channel = aimutil_get16(command->data+i); | |
438 i += 2; | |
439 | |
440 if (channel != 0x0003) | |
441 { | |
442 printf("faim: chat_incoming: unknown channel! (0x%04x)\n", channel); | |
443 return 1; | |
444 } | |
445 | |
446 /* | |
447 * Start parsing TLVs right away. | |
448 */ | |
449 outerlist = aim_readtlvchain(command->data+i, command->commandlen-i); | |
450 | |
451 /* | |
452 * Type 0x0003: Source User Information | |
453 */ | |
454 if (aim_gettlv(outerlist, 0x0003, 1)) | |
455 { | |
456 struct aim_tlv_t *userinfotlv; | |
457 | |
458 userinfotlv = aim_gettlv(outerlist, 0x0003, 1); | |
459 aim_extractuserinfo(userinfotlv->value, &userinfo); | |
460 } | |
461 | |
462 /* | |
463 * Type 0x0001: Unknown. | |
464 */ | |
465 if (aim_gettlv(outerlist, 0x0001, 1)) | |
466 ; | |
467 | |
468 /* | |
469 * Type 0x0005: Message Block. Conains more TLVs. | |
470 */ | |
471 if (aim_gettlv(outerlist, 0x0005, 1)) | |
472 { | |
473 struct aim_tlvlist_t *innerlist; | |
474 struct aim_tlv_t *msgblock; | |
475 | |
476 msgblock = aim_gettlv(outerlist, 0x0005, 1); | |
477 innerlist = aim_readtlvchain(msgblock->value, msgblock->length); | |
478 | |
479 /* | |
480 * Type 0x0001: Message. | |
481 */ | |
482 if (aim_gettlv(innerlist, 0x0001, 1)) | |
483 msg = aim_gettlv_str(innerlist, 0x0001, 1); | |
484 | |
485 aim_freetlvchain(&innerlist); | |
486 } | |
487 | |
488 userfunc = aim_callhandler(command->conn, AIM_CB_FAM_CHT, AIM_CB_CHT_INCOMINGMSG); | |
489 if (userfunc) | |
490 { | |
491 ret = userfunc(sess, | |
492 command, | |
493 &userinfo, | |
494 msg); | |
495 } | |
496 free(msg); | |
497 aim_freetlvchain(&outerlist); | |
498 | |
499 return ret; | |
500 } | |
501 | |
502 u_long aim_chat_clientready(struct aim_session_t *sess, | |
503 struct aim_conn_t *conn) | |
504 { | |
505 struct command_tx_struct *newpacket; | |
506 int i; | |
507 | |
508 if (!(newpacket = aim_tx_new(0x0002, conn, 0x20))) | |
509 return -1; | |
510 | |
511 newpacket->lock = 1; | |
512 | |
513 i = aim_putsnac(newpacket->data, 0x0001, 0x0002, 0x0000, sess->snac_nextid); | |
514 | |
515 i+= aimutil_put16(newpacket->data+i, 0x000e); | |
516 i+= aimutil_put16(newpacket->data+i, 0x0001); | |
517 | |
518 i+= aimutil_put16(newpacket->data+i, 0x0004); | |
519 i+= aimutil_put16(newpacket->data+i, 0x0001); | |
520 | |
521 i+= aimutil_put16(newpacket->data+i, 0x0001); | |
522 i+= aimutil_put16(newpacket->data+i, 0x0003); | |
523 | |
524 i+= aimutil_put16(newpacket->data+i, 0x0004); | |
525 i+= aimutil_put16(newpacket->data+i, 0x0686); | |
526 | |
527 newpacket->lock = 0; | |
528 aim_tx_enqueue(sess, newpacket); | |
529 | |
530 return (sess->snac_nextid++); | |
531 } | |
532 | |
533 int aim_chat_leaveroom(struct aim_session_t *sess, char *name) | |
534 { | |
535 int i; | |
536 | |
537 for (i=0;i<AIM_CONN_MAX;i++) | |
538 { | |
539 if (sess->conns[i].type == AIM_CONN_TYPE_CHAT) | |
540 { | |
541 if (sess->conns[i].priv) | |
542 if (!strcmp((char *)sess->conns[i].priv, name)) | |
543 { | |
544 aim_conn_close(&sess->conns[i]); | |
545 return 0; | |
546 } | |
547 } | |
548 } | |
549 return -1; | |
550 } | |
551 | |
552 /* | |
553 * conn must be a BOS connection! | |
554 */ | |
555 u_long aim_chat_invite(struct aim_session_t *sess, | |
556 struct aim_conn_t *conn, | |
557 char *sn, | |
558 char *msg, | |
559 u_short exchange, | |
560 char *roomname, | |
561 u_short instance) | |
562 { | |
563 struct command_tx_struct *newpacket; | |
564 int i,curbyte=0; | |
565 | |
566 if (!sess || !conn || !sn || !msg || !roomname) | |
567 return 0; | |
568 | |
569 if (!(newpacket = aim_tx_new(0x0002, conn, 1152+strlen(sn)+strlen(roomname)+strlen(msg)))) | |
570 return -1; | |
571 | |
572 newpacket->lock = 1; | |
573 | |
574 curbyte = aim_putsnac(newpacket->data, 0x0004, 0x0006, 0x0000, sess->snac_nextid); | |
575 | |
576 /* | |
577 * Cookie | |
578 */ | |
579 for (i=0;i<8;i++) | |
580 curbyte += aimutil_put8(newpacket->data+curbyte, (u_char)rand()); | |
581 | |
582 /* | |
583 * Channel (2) | |
584 */ | |
585 curbyte += aimutil_put16(newpacket->data+curbyte, 0x0002); | |
586 | |
587 /* | |
588 * Dest sn | |
589 */ | |
590 curbyte += aimutil_put8(newpacket->data+curbyte, strlen(sn)); | |
591 curbyte += aimutil_putstr(newpacket->data+curbyte, sn, strlen(sn)); | |
592 | |
593 /* | |
594 * TLV t(0005) | |
595 */ | |
596 curbyte += aimutil_put16(newpacket->data+curbyte, 0x0005); | |
597 curbyte += aimutil_put16(newpacket->data+curbyte, 0x28+strlen(msg)+0x04+0x03+strlen(roomname)+0x02); | |
598 | |
599 /* | |
600 * Unknown info | |
601 */ | |
602 curbyte += aimutil_put16(newpacket->data+curbyte, 0x0000); | |
603 curbyte += aimutil_put16(newpacket->data+curbyte, 0x3131); | |
604 curbyte += aimutil_put16(newpacket->data+curbyte, 0x3538); | |
605 curbyte += aimutil_put16(newpacket->data+curbyte, 0x3446); | |
606 curbyte += aimutil_put16(newpacket->data+curbyte, 0x4100); | |
607 curbyte += aimutil_put16(newpacket->data+curbyte, 0x748f); | |
608 curbyte += aimutil_put16(newpacket->data+curbyte, 0x2420); | |
609 curbyte += aimutil_put16(newpacket->data+curbyte, 0x6287); | |
610 curbyte += aimutil_put16(newpacket->data+curbyte, 0x11d1); | |
611 curbyte += aimutil_put16(newpacket->data+curbyte, 0x8222); | |
612 curbyte += aimutil_put16(newpacket->data+curbyte, 0x4445); | |
613 curbyte += aimutil_put16(newpacket->data+curbyte, 0x5354); | |
614 curbyte += aimutil_put16(newpacket->data+curbyte, 0x0000); | |
615 | |
616 /* | |
617 * TLV t(000a) -- Unknown | |
618 */ | |
619 curbyte += aimutil_put16(newpacket->data+curbyte, 0x000a); | |
620 curbyte += aimutil_put16(newpacket->data+curbyte, 0x0002); | |
621 curbyte += aimutil_put16(newpacket->data+curbyte, 0x0001); | |
622 | |
623 /* | |
624 * TLV t(000f) -- Unknown | |
625 */ | |
626 curbyte += aimutil_put16(newpacket->data+curbyte, 0x000f); | |
627 curbyte += aimutil_put16(newpacket->data+curbyte, 0x0000); | |
628 | |
629 /* | |
630 * TLV t(000c) -- Invitation message | |
631 */ | |
632 curbyte += aim_puttlv_str(newpacket->data+curbyte, 0x000c, strlen(msg), msg); | |
633 | |
634 /* | |
635 * TLV t(2711) -- Container for room information | |
636 */ | |
637 curbyte += aimutil_put16(newpacket->data+curbyte, 0x2711); | |
638 curbyte += aimutil_put16(newpacket->data+curbyte, 3+strlen(roomname)+2); | |
639 curbyte += aimutil_put16(newpacket->data+curbyte, exchange); | |
640 curbyte += aimutil_put8(newpacket->data+curbyte, strlen(roomname)); | |
641 curbyte += aimutil_putstr(newpacket->data+curbyte, roomname, strlen(roomname)); | |
642 curbyte += aimutil_put16(newpacket->data+curbyte, instance); | |
643 | |
644 newpacket->commandlen = curbyte; | |
645 newpacket->lock = 0; | |
646 aim_tx_enqueue(sess, newpacket); | |
647 | |
648 return (sess->snac_nextid++); | |
649 } |