comparison src/protocols/oscar/chat.c @ 8225:9790cda80d52

[gaim-migrate @ 8948] Various bits o' chat code cleanup for oscar. Mostly I just wanted to re-use some code for incoming i18n chat messages. committer: Tailor Script <tailor@pidgin.im>
author Mark Doliner <mark@kingant.net>
date Wed, 11 Feb 2004 04:06:16 +0000
parents 862dc2839646
children 4f70e8b3e05e
comparison
equal deleted inserted replaced
8224:ad524b8c9c71 8225:9790cda80d52
83 conn->priv = (void *)ccp; 83 conn->priv = (void *)ccp;
84 84
85 return 0; 85 return 0;
86 } 86 }
87 87
88 static int aim_addtlvtochain_chatroom(aim_tlvlist_t **list, fu16_t type, fu16_t exchange, const char *roomname, fu16_t instance)
89 {
90 fu8_t *buf;
91 int buflen;
92 aim_bstream_t bs;
93
94 buflen = 2 + 1 + strlen(roomname) + 2;
95
96 if (!(buf = malloc(buflen)))
97 return 0;
98
99 aim_bstream_init(&bs, buf, buflen);
100
101 aimbs_put16(&bs, exchange);
102 aimbs_put8(&bs, strlen(roomname));
103 aimbs_putraw(&bs, roomname, strlen(roomname));
104 aimbs_put16(&bs, instance);
105
106 aim_tlvlist_add_raw(list, type, aim_bstream_curpos(&bs), buf);
107
108 free(buf);
109
110 return 0;
111 }
112
113 /*
114 * Join a room of name roomname. This is the first step to joining an
115 * already created room. It's basically a Service Request for
116 * family 0x000e, with a little added on to specify the exchange and room
117 * name.
118 */
119 faim_export int aim_chat_join(aim_session_t *sess, aim_conn_t *conn, fu16_t exchange, const char *roomname, fu16_t instance)
120 {
121 aim_frame_t *fr;
122 aim_snacid_t snacid;
123 aim_tlvlist_t *tl = NULL;
124 struct chatsnacinfo csi;
125
126 if (!sess || !conn || !roomname || !strlen(roomname))
127 return -EINVAL;
128
129 if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 512)))
130 return -ENOMEM;
131
132 memset(&csi, 0, sizeof(csi));
133 csi.exchange = exchange;
134 strncpy(csi.name, roomname, sizeof(csi.name));
135 csi.instance = instance;
136
137 snacid = aim_cachesnac(sess, 0x0001, 0x0004, 0x0000, &csi, sizeof(csi));
138 aim_putsnac(&fr->data, 0x0001, 0x0004, 0x0000, snacid);
139
140 /*
141 * Requesting service chat (0x000e)
142 */
143 aimbs_put16(&fr->data, 0x000e);
144
145 aim_addtlvtochain_chatroom(&tl, 0x0001, exchange, roomname, instance);
146 aim_tlvlist_write(&fr->data, &tl);
147 aim_tlvlist_free(&tl);
148
149 aim_tx_enqueue(sess, fr);
150
151 return 0;
152 }
153
154 faim_internal int aim_chat_readroominfo(aim_bstream_t *bs, struct aim_chat_roominfo *outinfo) 88 faim_internal int aim_chat_readroominfo(aim_bstream_t *bs, struct aim_chat_roominfo *outinfo)
155 { 89 {
156 int namelen; 90 int namelen;
157 91
158 if (!bs || !outinfo) 92 if (!bs || !outinfo)
172 106
173 if (!(conn = aim_chat_getconn(sess, name))) 107 if (!(conn = aim_chat_getconn(sess, name)))
174 return -ENOENT; 108 return -ENOENT;
175 109
176 aim_conn_close(conn); 110 aim_conn_close(conn);
177
178 return 0;
179 }
180
181 /*
182 * conn must be a BOS connection!
183 */
184 faim_export int aim_chat_invite(aim_session_t *sess, aim_conn_t *conn, const char *sn, const char *msg, fu16_t exchange, const char *roomname, fu16_t instance)
185 {
186 int i;
187 aim_frame_t *fr;
188 aim_msgcookie_t *cookie;
189 struct aim_invite_priv *priv;
190 fu8_t ckstr[8];
191 aim_snacid_t snacid;
192 aim_tlvlist_t *otl = NULL, *itl = NULL;
193 fu8_t *hdr;
194 int hdrlen;
195 aim_bstream_t hdrbs;
196
197 if (!sess || !conn || !sn || !msg || !roomname)
198 return -EINVAL;
199
200 if (conn->type != AIM_CONN_TYPE_BOS)
201 return -EINVAL;
202
203 if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 1152+strlen(sn)+strlen(roomname)+strlen(msg))))
204 return -ENOMEM;
205
206 snacid = aim_cachesnac(sess, 0x0004, 0x0006, 0x0000, sn, strlen(sn)+1);
207 aim_putsnac(&fr->data, 0x0004, 0x0006, 0x0000, snacid);
208
209 /*
210 * Cookie
211 */
212 for (i = 0; i < 8; i++)
213 ckstr[i] = (fu8_t)rand();
214
215 /* XXX should be uncached by an unwritten 'invite accept' handler */
216 if ((priv = malloc(sizeof(struct aim_invite_priv)))) {
217 priv->sn = strdup(sn);
218 priv->roomname = strdup(roomname);
219 priv->exchange = exchange;
220 priv->instance = instance;
221 }
222
223 if ((cookie = aim_mkcookie(ckstr, AIM_COOKIETYPE_INVITE, priv)))
224 aim_cachecookie(sess, cookie);
225 else
226 free(priv);
227
228 /* ICBM Header */
229 aimbs_putraw(&fr->data, ckstr, 8); /* Cookie */
230 aimbs_put16(&fr->data, 0x0002); /* Channel */
231 aimbs_put8(&fr->data, strlen(sn)); /* Screename length */
232 aimbs_putraw(&fr->data, sn, strlen(sn)); /* Screenname */
233
234 /*
235 * TLV t(0005)
236 *
237 * Everything else is inside this TLV.
238 *
239 * Sigh. AOL was rather inconsistent right here. So we have
240 * to play some minor tricks. Right inside the type 5 is some
241 * raw data, followed by a series of TLVs.
242 *
243 */
244 hdrlen = 2+8+16+6+4+4+strlen(msg)+4+2+1+strlen(roomname)+2;
245 hdr = malloc(hdrlen);
246 aim_bstream_init(&hdrbs, hdr, hdrlen);
247
248 aimbs_put16(&hdrbs, 0x0000); /* Unknown! */
249 aimbs_putraw(&hdrbs, ckstr, sizeof(ckstr)); /* I think... */
250 aim_putcap(&hdrbs, AIM_CAPS_CHAT);
251
252 aim_tlvlist_add_16(&itl, 0x000a, 0x0001);
253 aim_tlvlist_add_noval(&itl, 0x000f);
254 aim_tlvlist_add_raw(&itl, 0x000c, strlen(msg), msg);
255 aim_addtlvtochain_chatroom(&itl, 0x2711, exchange, roomname, instance);
256 aim_tlvlist_write(&hdrbs, &itl);
257
258 aim_tlvlist_add_raw(&otl, 0x0005, aim_bstream_curpos(&hdrbs), hdr);
259
260 aim_tlvlist_write(&fr->data, &otl);
261
262 free(hdr);
263 aim_tlvlist_free(&itl);
264 aim_tlvlist_free(&otl);
265
266 aim_tx_enqueue(sess, fr);
267 111
268 return 0; 112 return 0;
269 } 113 }
270 114
271 /* 115 /*
581 * message tlv 425 * message tlv
582 * message string 426 * message string
583 * possibly others 427 * possibly others
584 * 428 *
585 */ 429 */
586 static int incomingmsg(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs) 430 static int incomingim_ch3(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
587 { 431 {
432 int ret = 0, i;
433 aim_rxcallback_t userfunc;
588 aim_userinfo_t userinfo; 434 aim_userinfo_t userinfo;
589 aim_rxcallback_t userfunc; 435 fu8_t cookie[8];
590 int ret = 0;
591 fu8_t *cookie;
592 fu16_t channel; 436 fu16_t channel;
593 aim_tlvlist_t *otl; 437 aim_tlvlist_t *otl;
594 char *msg = NULL; 438 char *msg = NULL;
595 int len; 439 int len;
596 char *charset = NULL; 440 char *charset = NULL;
597 aim_msgcookie_t *ck; 441 aim_msgcookie_t *ck;
598 442
599 memset(&userinfo, 0, sizeof(aim_userinfo_t)); 443 memset(&userinfo, 0, sizeof(aim_userinfo_t));
600 444
601 /* 445 /*
602 * ICBM Cookie. Uncache it. 446 * Read ICBM Cookie.
603 */ 447 */
604 cookie = aimbs_getraw(bs, 8); 448 for (i = 0; i < 8; i++)
449 cookie[i] = aimbs_get8(bs);
605 450
606 if ((ck = aim_uncachecookie(sess, cookie, AIM_COOKIETYPE_CHAT))) { 451 if ((ck = aim_uncachecookie(sess, cookie, AIM_COOKIETYPE_CHAT))) {
607 free(ck->data); 452 free(ck->data);
608 free(ck); 453 free(ck);
609 } 454 }
610 455
611 /* 456 /*
612 * Channel ID 457 * Channel ID
613 * 458 *
614 * Channels 1 and 2 are implemented in the normal ICBM 459 * Channel 0x0003 is used for chat messages.
615 * parser.
616 *
617 * We only do channel 3 here.
618 * 460 *
619 */ 461 */
620 channel = aimbs_get16(bs); 462 channel = aimbs_get16(bs);
621 463
622 if (channel != 0x0003) { 464 if (channel != 0x0003) {
680 522
681 if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) 523 if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
682 ret = userfunc(sess, rx, &userinfo, len, msg, charset); 524 ret = userfunc(sess, rx, &userinfo, len, msg, charset);
683 525
684 aim_info_free(&userinfo); 526 aim_info_free(&userinfo);
685 free(cookie);
686 free(msg); 527 free(msg);
687 aim_tlvlist_free(&otl); 528 aim_tlvlist_free(&otl);
688 529
689 return ret; 530 return ret;
690 } 531 }
695 if (snac->subtype == 0x0002) 536 if (snac->subtype == 0x0002)
696 return infoupdate(sess, mod, rx, snac, bs); 537 return infoupdate(sess, mod, rx, snac, bs);
697 else if ((snac->subtype == 0x0003) || (snac->subtype == 0x0004)) 538 else if ((snac->subtype == 0x0003) || (snac->subtype == 0x0004))
698 return userlistchange(sess, mod, rx, snac, bs); 539 return userlistchange(sess, mod, rx, snac, bs);
699 else if (snac->subtype == 0x0006) 540 else if (snac->subtype == 0x0006)
700 return incomingmsg(sess, mod, rx, snac, bs); 541 return incomingim_ch3(sess, mod, rx, snac, bs);
701 542
702 return 0; 543 return 0;
703 } 544 }
704 545
705 faim_internal int chat_modfirst(aim_session_t *sess, aim_module_t *mod) 546 faim_internal int chat_modfirst(aim_session_t *sess, aim_module_t *mod)