2
|
1 /*
|
|
2 * aim_chat.c
|
|
3 *
|
|
4 * Routines for the Chat service. Nothing works (yet).
|
|
5 *
|
|
6 */
|
|
7
|
237
|
8 #include <aim.h>
|
|
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 }
|