Mercurial > pidgin
comparison src/protocols/oscar/ft.c @ 2246:933346315b9b
[gaim-migrate @ 2256]
heh.
committer: Tailor Script <tailor@pidgin.im>
author | Eric Warmenhoven <eric@warmenhoven.org> |
---|---|
date | Sun, 09 Sep 2001 10:07:14 +0000 |
parents | 424a40f12a6c |
children | f721ae9582d5 |
comparison
equal
deleted
inserted
replaced
2245:31157c54fe6e | 2246:933346315b9b |
---|---|
19 | 19 |
20 /* TODO: | 20 /* TODO: |
21 o look for memory leaks.. there's going to be shitloads, i'm sure. | 21 o look for memory leaks.. there's going to be shitloads, i'm sure. |
22 */ | 22 */ |
23 | 23 |
24 struct aim_directim_intdata { | |
25 fu8_t cookie[8]; | |
26 char sn[MAXSNLEN+1]; | |
27 char ip[22]; | |
28 }; | |
29 | |
30 static int listenestablish(fu16_t portnum); | |
24 static struct aim_fileheader_t *aim_oft_getfh(unsigned char *hdr); | 31 static struct aim_fileheader_t *aim_oft_getfh(unsigned char *hdr); |
25 | 32 |
26 /** | 33 /** |
27 * aim_handlerendconnect - call this to accept OFT connections and set up the requisite structures | 34 * aim_handlerendconnect - call this to accept OFT connections and set up the required structures |
28 * @sess: the session | 35 * @sess: the session |
29 * @cur: the conn the incoming connection is on | 36 * @cur: the conn the incoming connection is on |
30 * | 37 * |
31 * call this when you get an outstanding read on a conn with subtype | 38 * call this when you get an outstanding read on a conn with subtype |
32 * AIM_CONN_SUBTYPE_RENDEZVOUS_OUT, it will clone the current | 39 * AIM_CONN_SUBTYPE_RENDEZVOUS_OUT, it will clone the current |
33 * &aim_conn_t and tweak things as appropriate. the new conn and the | 40 * &aim_conn_t and tweak things as appropriate. the new conn and the |
34 * listener conn are both returned to the client in the | 41 * listener conn are both returned to the client in the |
35 * %AIM_CB_FAM_OFT, %AIM_CB_OFT_<CLASS>INITIATE callback. | 42 * %AIM_CB_FAM_OFT, %AIM_CB_OFT_<CLASS>INITIATE callback. |
36 */ | 43 */ |
37 faim_export int aim_handlerendconnect(struct aim_session_t *sess, struct aim_conn_t *cur) | 44 faim_export int aim_handlerendconnect(aim_session_t *sess, aim_conn_t *cur) |
38 { | 45 { |
39 int acceptfd = 0; | 46 int acceptfd = 0; |
40 aim_rxcallback_t userfunc; | 47 struct sockaddr cliaddr; |
41 struct sockaddr cliaddr; | 48 int clilen = sizeof(cliaddr); |
42 int clilen = sizeof(cliaddr); | 49 int ret = 0; |
43 int ret = 0; | 50 aim_conn_t *newconn; |
44 struct aim_conn_t *newconn; | 51 |
45 | 52 if ((acceptfd = accept(cur->fd, &cliaddr, &clilen)) == -1) |
46 if ( (acceptfd = accept(cur->fd, &cliaddr, &clilen)) == -1) | 53 return 0; /* not an error */ |
47 return -1; | 54 |
48 if (cliaddr.sa_family != AF_INET) { /* just in case IPv6 really is happening */ | 55 if (cliaddr.sa_family != AF_INET) { /* just in case IPv6 really is happening */ |
49 close(acceptfd); | 56 close(acceptfd); |
50 aim_conn_close(cur); | 57 aim_conn_close(cur); |
51 return -1; | 58 return -1; |
52 } | 59 } |
53 | 60 |
54 /* safe? maybe cur->priv should be NULLed after this. --mid */ | 61 if (!(newconn = aim_cloneconn(sess, cur))) { |
55 | 62 close(acceptfd); |
56 /* That would be bad. very bad. we want cur->priv->sn to make it up | 63 aim_conn_close(cur); |
57 to the client-level for conn management and such. even though | 64 return -1; |
58 that is abusing the interface --jbm */ | 65 } |
59 | 66 |
60 if (!(newconn = aim_cloneconn(sess, cur))) { | 67 newconn->type = AIM_CONN_TYPE_RENDEZVOUS; |
61 close(acceptfd); | 68 newconn->fd = acceptfd; |
62 aim_conn_close(cur); | 69 |
63 return -1; | 70 if (newconn->subtype == AIM_CONN_SUBTYPE_OFT_DIRECTIM) { |
64 } | 71 struct aim_directim_intdata *priv; |
65 | 72 aim_rxcallback_t userfunc; |
66 newconn->type = AIM_CONN_TYPE_RENDEZVOUS; | 73 |
67 newconn->fd = acceptfd; | 74 priv = (struct aim_directim_intdata *)(newconn->internal = cur->internal); |
68 | 75 cur->internal = NULL; |
69 switch(newconn->subtype) { | 76 |
70 case AIM_CONN_SUBTYPE_OFT_DIRECTIM: { | 77 snprintf(priv->ip, sizeof(priv->ip), "%s:%u", |
71 struct aim_directim_priv *priv; | 78 inet_ntoa(((struct sockaddr_in *)&cliaddr)->sin_addr), |
72 | 79 ntohs(((struct sockaddr_in *)&cliaddr)->sin_port)); |
73 priv = cur->priv; | 80 |
74 | 81 if ((userfunc = aim_callhandler(sess, newconn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIMINITIATE))) |
75 newconn->priv = cur->priv; | 82 ret = userfunc(sess, NULL, newconn, cur); |
76 | 83 |
77 cur->priv = NULL; | 84 } else if (newconn->subtype == AIM_CONN_SUBTYPE_OFT_GETFILE) { |
78 | 85 #if 0 |
79 snprintf(priv->ip, sizeof(priv->ip), "%s:%u", | 86 struct aim_filetransfer_priv *priv; |
80 inet_ntoa(((struct sockaddr_in *)&cliaddr)->sin_addr), | 87 aim_rxcallback_t userfunc; |
81 ntohs(((struct sockaddr_in *)&cliaddr)->sin_port)); | 88 |
82 | 89 |
83 if ( (userfunc = aim_callhandler(sess, newconn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIMINITIATE))) | 90 newconn->priv = cur->priv; |
84 ret = userfunc(sess, NULL, newconn, cur); | 91 cur->priv = NULL; |
85 | 92 priv = (struct aim_filetransfer_priv *)newconn->priv; |
86 break; | 93 |
87 } | 94 snprintf(priv->ip, sizeof(priv->ip), "%s:%u", inet_ntoa(((struct sockaddr_in *)&cliaddr)->sin_addr), ntohs(((struct sockaddr_in *)&cliaddr)->sin_port)); |
88 case AIM_CONN_SUBTYPE_OFT_GETFILE: { | 95 |
89 struct aim_filetransfer_priv *priv; | 96 if ((userfunc = aim_callhandler(sess, newconn, AIM_CB_FAM_OFT, AIM_CB_OFT_GETFILEINITIATE))) |
90 | 97 ret = userfunc(sess, NULL, newconn, cur); |
91 | 98 #endif |
92 newconn->priv = cur->priv; | 99 } else { |
93 cur->priv = NULL; | 100 faimdprintf(sess, 1,"Got a Connection on a listener that's not Rendezvous(??!) Closing conn.\n"); |
94 priv = (struct aim_filetransfer_priv *)newconn->priv; | 101 aim_conn_close(newconn); |
95 | 102 ret = -1; |
96 snprintf(priv->ip, sizeof(priv->ip), "%s:%u", inet_ntoa(((struct sockaddr_in *)&cliaddr)->sin_addr), ntohs(((struct sockaddr_in *)&cliaddr)->sin_port)); | 103 } |
97 | 104 |
98 if ( (userfunc = aim_callhandler(sess, newconn, AIM_CB_FAM_OFT, AIM_CB_OFT_GETFILEINITIATE))) | 105 return ret; |
99 ret = userfunc(sess, NULL, newconn, cur); | 106 } |
100 | 107 |
101 break; | |
102 } | |
103 default: { | |
104 faimdprintf(sess, 1,"Got a Connection on a listener that's not Rendezvous(??!) Closing conn.\n"); | |
105 aim_conn_close(newconn); | |
106 break; | |
107 } | |
108 } | |
109 | |
110 return ret; | |
111 } | |
112 | |
113 /** | 108 /** |
114 * aim_send_im_direct - send IM client-to-client over established connection | 109 * aim_send_im_direct - send IM client-to-client over established connection |
115 * @sess: session to conn | 110 * @sess: session to conn |
116 * @conn: directim connection | 111 * @conn: directim connection |
117 * @msg: null-terminated string to send; if this is NULL, it will send a "typing" notice. | 112 * @msg: null-terminated string to send; if this is NULL, it will send a "typing" notice. |
118 * | 113 * |
119 * Call this just like you would aim_send_im, to send a directim. You | 114 * Call this just like you would aim_send_im, to send a directim. You |
120 * _must_ have previously established the directim connection. | 115 * _must_ have previously established the directim connection. |
121 */ | 116 */ |
122 faim_export int aim_send_im_direct(struct aim_session_t *sess, struct aim_conn_t *conn, char *msg) | 117 faim_export int aim_send_im_direct(aim_session_t *sess, aim_conn_t *conn, const char *msg) |
123 { | 118 { |
124 struct command_tx_struct *newpacket; | 119 struct aim_directim_intdata *intdata = (struct aim_directim_intdata *)conn->internal; |
125 struct aim_directim_priv *priv = NULL; | 120 aim_frame_t *fr; |
126 int i; | 121 aim_bstream_t hdrbs; /* XXX this should be within aim_frame_t */ |
127 | 122 |
128 if (!sess || !conn || (conn->type != AIM_CONN_TYPE_RENDEZVOUS) || !conn->priv) { | 123 if (!sess || !conn || (conn->type != AIM_CONN_TYPE_RENDEZVOUS)) |
129 faimdprintf(sess, 2,"faim: directim: invalid arguments\n"); | 124 return -EINVAL; |
130 return -1; | 125 |
131 } | 126 if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_OFT, 0x01, strlen(msg)))) |
132 | 127 return -ENOMEM; |
133 priv = (struct aim_directim_priv *)conn->priv; | 128 |
134 | 129 memcpy(fr->hdr.oft.magic, "ODC2", 4); |
135 if (!(newpacket = aim_tx_new(sess, conn, AIM_FRAMETYPE_OFT, 0x0001, strlen(msg)))) { | 130 |
136 faimdprintf(sess, 2,"faim: directim: tx_new failed\n"); | 131 fr->hdr.oft.hdr2len = 0x44; |
137 return -1; | 132 |
138 } | 133 if (!(fr->hdr.oft.hdr2 = calloc(1, fr->hdr.oft.hdr2len))) { |
139 | 134 aim_frame_destroy(fr); |
140 newpacket->lock = 1; | 135 return -ENOMEM; |
141 | 136 } |
142 /* if msg is non-null, we'resending an IM, else a "typing" notice */ | 137 |
143 if (msg) { | 138 aim_bstream_init(&hdrbs, fr->hdr.oft.hdr2, fr->hdr.oft.hdr2len); |
144 if (strlen(msg) >= MAXMSGLEN) | 139 |
145 return -1; | 140 aimbs_put16(&hdrbs, 0x0006); |
146 newpacket->hdr.oft.hdr2len = 0x54; | 141 aimbs_put16(&hdrbs, 0x0000); |
147 if (!(newpacket->hdr.oft.hdr2 = calloc(1,newpacket->hdr.oft.hdr2len))) { | 142 aimbs_putraw(&hdrbs, intdata->cookie, 8); |
148 newpacket->lock = 0; | 143 aimbs_put16(&hdrbs, 0x0000); |
149 aim_tx_destroy(newpacket); | 144 aimbs_put16(&hdrbs, 0x0000); |
150 return -1; | 145 aimbs_put16(&hdrbs, 0x0000); |
151 } | 146 aimbs_put16(&hdrbs, 0x0000); |
152 } else { | 147 aimbs_put32(&hdrbs, strlen(msg)); |
153 newpacket->hdr.oft.hdr2len = 0x44; | 148 aimbs_put16(&hdrbs, 0x0000); |
154 if (!(newpacket->hdr.oft.hdr2 = calloc(1,newpacket->hdr.oft.hdr2len))) { | 149 aimbs_put16(&hdrbs, 0x0000); |
155 newpacket->lock = 0; | 150 aimbs_put16(&hdrbs, 0x0000); |
156 aim_tx_destroy(newpacket); | 151 |
157 return -1; | 152 /* flags -- 0x000e for "typing", 0x0000 for message */ |
158 } | 153 aimbs_put16(&hdrbs, msg ? 0x0000 : 0x000e); |
159 } | 154 |
160 | 155 aimbs_put16(&hdrbs, 0x0000); |
161 memcpy(newpacket->hdr.oft.magic, "ODC2", 4); | 156 aimbs_put16(&hdrbs, 0x0000); |
162 newpacket->data = NULL; | 157 aimbs_putraw(&hdrbs, sess->sn, strlen(sess->sn)); |
163 | 158 |
164 i = 0; | 159 aim_bstream_setpos(&hdrbs, 52); /* bleeehh */ |
165 i += aimutil_put16(newpacket->hdr.oft.hdr2+i, 0x0006); | 160 |
166 i += aimutil_put16(newpacket->hdr.oft.hdr2+i, 0x0000); | 161 aimbs_put8(&hdrbs, 0x00); |
167 i += aimutil_putstr(newpacket->hdr.oft.hdr2+i, (char *)priv->cookie, 8); | 162 aimbs_put16(&hdrbs, 0x0000); |
168 i += aimutil_put16(newpacket->hdr.oft.hdr2+i, 0x0000); | 163 aimbs_put16(&hdrbs, 0x0000); |
169 i += aimutil_put16(newpacket->hdr.oft.hdr2+i, 0x0000); | 164 aimbs_put16(&hdrbs, 0x0000); |
170 i += aimutil_put16(newpacket->hdr.oft.hdr2+i, 0x0000); | 165 aimbs_put16(&hdrbs, 0x0000); |
171 i += aimutil_put16(newpacket->hdr.oft.hdr2+i, 0x0000); | 166 aimbs_put16(&hdrbs, 0x0000); |
172 i += aimutil_put32(newpacket->hdr.oft.hdr2+i, strlen(msg)); | 167 aimbs_put16(&hdrbs, 0x0000); |
173 i += aimutil_put16(newpacket->hdr.oft.hdr2+i, 0x0000); | 168 aimbs_put16(&hdrbs, 0x0000); |
174 i += aimutil_put16(newpacket->hdr.oft.hdr2+i, 0x0000); | 169 |
175 i += aimutil_put16(newpacket->hdr.oft.hdr2+i, 0x0000); | 170 /* end of hdr2 */ |
176 | 171 |
177 /* flags -- 0x000e for "typing", 0x0000 for message */ | 172 if (msg) { |
178 if (msg) | 173 #if 0 /* XXX this is how you send buddy icon info... */ |
179 i += aimutil_put16(newpacket->hdr.oft.hdr2+i, 0x0000); | 174 i += aimutil_put16(newpacket->hdr.oft.hdr2+i, 0x0008); |
180 else | 175 i += aimutil_put16(newpacket->hdr.oft.hdr2+i, 0x000c); |
181 i += aimutil_put16(newpacket->hdr.oft.hdr2+i, 0x000e); | 176 i += aimutil_put16(newpacket->hdr.oft.hdr2+i, 0x0000); |
182 | 177 i += aimutil_put16(newpacket->hdr.oft.hdr2+i, 0x1466); |
183 i += aimutil_put16(newpacket->hdr.oft.hdr2+i, 0x0000); | 178 i += aimutil_put16(newpacket->hdr.oft.hdr2+i, 0x0001); |
184 i += aimutil_put16(newpacket->hdr.oft.hdr2+i, 0x0000); | 179 i += aimutil_put16(newpacket->hdr.oft.hdr2+i, 0x2e0f); |
185 i += aimutil_putstr(newpacket->hdr.oft.hdr2+i, sess->sn, strlen(sess->sn)); | 180 i += aimutil_put16(newpacket->hdr.oft.hdr2+i, 0x393e); |
186 i = 52; | 181 i += aimutil_put16(newpacket->hdr.oft.hdr2+i, 0xcac8); |
187 | 182 #endif |
188 i += aimutil_put8(newpacket->hdr.oft.hdr2+i, 0x00); | 183 aimbs_putraw(&fr->data, msg, strlen(msg)); |
189 i += aimutil_put16(newpacket->hdr.oft.hdr2+i, 0x0000); | 184 } |
190 i += aimutil_put16(newpacket->hdr.oft.hdr2+i, 0x0000); | 185 |
191 i += aimutil_put16(newpacket->hdr.oft.hdr2+i, 0x0000); | 186 aim_tx_enqueue(sess, fr); |
192 i += aimutil_put16(newpacket->hdr.oft.hdr2+i, 0x0000); | 187 |
193 i += aimutil_put16(newpacket->hdr.oft.hdr2+i, 0x0000); | 188 return 0; |
194 i += aimutil_put16(newpacket->hdr.oft.hdr2+i, 0x0000); | |
195 i += aimutil_put16(newpacket->hdr.oft.hdr2+i, 0x0000); | |
196 | |
197 /* end of hdr2 */ | |
198 | |
199 if (msg) { | |
200 /* values grabbed from a dump */ | |
201 i += aimutil_put16(newpacket->hdr.oft.hdr2+i, 0x0008); | |
202 i += aimutil_put16(newpacket->hdr.oft.hdr2+i, 0x000c); | |
203 i += aimutil_put16(newpacket->hdr.oft.hdr2+i, 0x0000); | |
204 i += aimutil_put16(newpacket->hdr.oft.hdr2+i, 0x1466); | |
205 i += aimutil_put16(newpacket->hdr.oft.hdr2+i, 0x0001); | |
206 i += aimutil_put16(newpacket->hdr.oft.hdr2+i, 0x2e0f); | |
207 i += aimutil_put16(newpacket->hdr.oft.hdr2+i, 0x393e); | |
208 i += aimutil_put16(newpacket->hdr.oft.hdr2+i, 0xcac8); | |
209 if(!(newpacket->data = strdup(msg))) | |
210 return -1; | |
211 } | |
212 newpacket->lock = 0; | |
213 aim_tx_enqueue(sess, newpacket); | |
214 return 0; | |
215 } | 189 } |
216 | 190 |
217 /* XXX: give the client author the responsibility of setting up a | 191 /* XXX: give the client author the responsibility of setting up a |
218 * listener, then we no longer have a libfaim problem with broken | 192 * listener, then we no longer have a libfaim problem with broken |
219 * solaris *innocent smile* -jbm */ | 193 * solaris *innocent smile* -jbm */ |
194 | |
195 static int getlocalip(fu8_t *ip) | |
196 { | |
197 struct hostent *hptr; | |
198 char localhost[129]; | |
199 | |
200 /* XXX if available, use getaddrinfo() */ | |
201 /* XXX allow client to specify which IP to use for multihomed boxes */ | |
202 | |
203 if (gethostname(localhost, 128) < 0) | |
204 return -1; | |
205 | |
206 if (!(hptr = gethostbyname(localhost))) | |
207 return -1; | |
208 | |
209 memcpy(ip, hptr->h_addr_list[0], 4); | |
210 | |
211 return 0; | |
212 } | |
213 | |
214 /* XXX this should probably go in im.c */ | |
215 static int aim_request_directim(aim_session_t *sess, aim_conn_t *conn, const char *destsn, fu8_t *ip, fu16_t port, fu8_t *ckret) | |
216 { | |
217 fu8_t ck[8]; | |
218 aim_frame_t *fr; | |
219 aim_snacid_t snacid; | |
220 aim_tlvlist_t *tl = NULL, *itl = NULL; | |
221 int hdrlen, i; | |
222 fu8_t *hdr; | |
223 aim_bstream_t hdrbs; | |
224 | |
225 if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 256+strlen(destsn)))) | |
226 return -ENOMEM; | |
227 | |
228 snacid = aim_cachesnac(sess, 0x0004, 0x0006, 0x0000, NULL, 0); | |
229 aim_putsnac(&fr->data, 0x0004, 0x0006, 0x0000, snacid); | |
230 | |
231 /* | |
232 * Generate a random message cookie | |
233 * | |
234 * This cookie needs to be alphanumeric and NULL-terminated to be | |
235 * TOC-compatible. | |
236 * | |
237 * XXX have I mentioned these should be generated in msgcookie.c? | |
238 * | |
239 */ | |
240 for (i = 0; i < 7; i++) | |
241 ck[i] = 0x30 + ((fu8_t) rand() % 10); | |
242 ck[7] = '\0'; | |
243 | |
244 if (ckret) | |
245 memcpy(ckret, ck, 8); | |
246 | |
247 /* Cookie */ | |
248 aimbs_putraw(&fr->data, ck, 8); | |
249 | |
250 /* Channel */ | |
251 aimbs_put16(&fr->data, 0x0002); | |
252 | |
253 /* Destination SN */ | |
254 aimbs_put8(&fr->data, strlen(destsn)); | |
255 aimbs_putraw(&fr->data, destsn, strlen(destsn)); | |
256 | |
257 aim_addtlvtochain_noval(&tl, 0x0003); | |
258 | |
259 hdrlen = 2+8+16+6+8+6+4; | |
260 hdr = malloc(hdrlen); | |
261 aim_bstream_init(&hdrbs, hdr, hdrlen); | |
262 | |
263 aimbs_put16(&hdrbs, 0x0000); | |
264 aimbs_putraw(&hdrbs, ck, 8); | |
265 aim_putcap(&hdrbs, AIM_CAPS_IMIMAGE); | |
266 | |
267 aim_addtlvtochain16(&itl, 0x000a, 0x0001); | |
268 aim_addtlvtochain_raw(&itl, 0x0003, 4, ip); | |
269 aim_addtlvtochain16(&itl, 0x0005, port); | |
270 aim_addtlvtochain_noval(&itl, 0x000f); | |
271 | |
272 aim_writetlvchain(&hdrbs, &itl); | |
273 | |
274 aim_addtlvtochain_raw(&tl, 0x0005, aim_bstream_curpos(&hdrbs), hdr); | |
275 | |
276 aim_writetlvchain(&fr->data, &tl); | |
277 | |
278 free(hdr); | |
279 aim_freetlvchain(&itl); | |
280 aim_freetlvchain(&tl); | |
281 | |
282 aim_tx_enqueue(sess, fr); | |
283 | |
284 return 0; | |
285 } | |
220 | 286 |
221 /** | 287 /** |
222 * aim_directim_intitiate - For those times when we want to open up the directim channel ourselves. | 288 * aim_directim_intitiate - For those times when we want to open up the directim channel ourselves. |
223 * @sess: your session, | 289 * @sess: your session, |
224 * @conn: the BOS conn, | 290 * @conn: the BOS conn, |
225 * @priv: a dummy priv value (we'll let it get filled in later) (if you pass a %NULL, we alloc one) | 291 * @priv: a dummy priv value (we'll let it get filled in later) (if you pass a %NULL, we alloc one) |
226 * @destsn: the SN to connect to. | 292 * @destsn: the SN to connect to. |
227 * | 293 * |
228 */ | 294 */ |
229 faim_export struct aim_conn_t *aim_directim_initiate(struct aim_session_t *sess, | 295 faim_export aim_conn_t *aim_directim_initiate(aim_session_t *sess, aim_conn_t *conn, const char *destsn) |
230 struct aim_conn_t *conn, | |
231 struct aim_directim_priv *priv, | |
232 char *destsn) | |
233 { | 296 { |
234 | 297 aim_conn_t *newconn; |
235 struct command_tx_struct *newpacket; | 298 aim_msgcookie_t *cookie; |
236 struct aim_conn_t *newconn; | 299 struct aim_directim_intdata *priv; |
237 struct aim_msgcookie_t *cookie; | 300 int listenfd; |
238 int curbyte, i, listenfd; | 301 fu16_t port = 4443; |
239 short port = 4443; | 302 fu8_t localip[4]; |
240 struct hostent *hptr; | 303 fu8_t ck[8]; |
241 char localhost[129]; | 304 |
242 unsigned char cap[16]; | 305 if (getlocalip(localip) == -1) |
243 char d[4]; /* IPv6 is a bit bigger... */ | 306 return NULL; |
244 | 307 |
245 /* XXX: TLVlist-ize this */ | 308 if ((listenfd = listenestablish(port)) == -1) |
246 | 309 return NULL; |
247 /* Open our socket */ | 310 |
248 | 311 aim_request_directim(sess, conn, destsn, localip, port, ck); |
249 if ( (listenfd = aim_listenestablish(port)) == -1) | 312 |
250 return NULL; | 313 cookie = (aim_msgcookie_t *)calloc(1, sizeof(aim_msgcookie_t)); |
251 | 314 memcpy(cookie->cookie, ck, 8); |
252 /* get our local IP */ | 315 cookie->type = AIM_COOKIETYPE_OFTIM; |
253 /* XXX if available, use getaddrinfo() */ | 316 |
254 /* XXX allow client to specify which IP to use for multihomed boxes */ | 317 priv = (struct aim_directim_intdata *)calloc(1, sizeof(struct aim_directim_intdata)); |
255 if (gethostname(localhost, 128) < 0) | 318 |
256 return NULL; | 319 memcpy(priv->cookie, ck, 8); |
257 if ( (hptr = gethostbyname(localhost)) == NULL) | 320 strncpy(priv->sn, destsn, sizeof(priv->sn)); |
258 return NULL; | 321 cookie->data = priv; |
259 memcpy(&d, hptr->h_addr_list[0], 4); | 322 aim_cachecookie(sess, cookie); |
260 | 323 |
261 aim_putcap(cap, 16, AIM_CAPS_IMIMAGE); | 324 /* XXX switch to aim_cloneconn()? */ |
262 | 325 if (!(newconn = aim_newconn(sess, AIM_CONN_TYPE_RENDEZVOUS_OUT, NULL))) { |
263 /* create the OSCAR packet */ | 326 close(listenfd); |
264 | 327 return NULL; |
265 if (!(newpacket = aim_tx_new(sess, conn, AIM_FRAMETYPE_OSCAR, 0x0002, 10+8+2+1+strlen(destsn)+4+4+0x32))) | 328 } |
266 return NULL; | 329 |
267 newpacket->lock = 1; | 330 /* this one is for the conn */ |
268 | 331 priv = (struct aim_directim_intdata *)calloc(1, sizeof(struct aim_directim_intdata)); |
269 curbyte = 0; | 332 |
270 curbyte += aim_putsnac(newpacket->data+curbyte, 0x0004, 0x0006, 0x0000, sess->snac_nextid); | 333 memcpy(priv->cookie, ck, 8); |
271 | 334 strncpy(priv->sn, destsn, sizeof(priv->sn)); |
272 /* Generate a random message cookie */ | 335 |
273 /* This cookie needs to be alphanumeric and NULL-terminated to be TOC-compatible. */ | 336 newconn->fd = listenfd; |
274 for (i=0; i<7; i++) | 337 newconn->subtype = AIM_CONN_SUBTYPE_OFT_DIRECTIM; |
275 curbyte += aimutil_put8(newpacket->data+curbyte, 0x30 + ((u_char) rand() % 20)); | 338 newconn->internal = priv; |
276 | 339 newconn->lastactivity = time(NULL); |
277 curbyte += aimutil_put8(newpacket->data+curbyte, 0x00); | 340 |
278 | 341 faimdprintf(sess, 2,"faim: listening (fd = %d, unconnected)\n", newconn->fd); |
279 /* grab all the data for cookie caching */ | 342 |
280 cookie = (struct aim_msgcookie_t *)calloc(1, sizeof(struct aim_msgcookie_t)); | 343 return newconn; |
281 memcpy(cookie->cookie, newpacket->data+curbyte-8, 8); | |
282 cookie->type = AIM_COOKIETYPE_OFTIM; | |
283 priv = cookie->data; | |
284 | |
285 if (!priv) | |
286 priv = (struct aim_directim_priv *)calloc(1, sizeof(struct aim_directim_priv)); | |
287 | |
288 memcpy(priv->cookie, cookie, 8); | |
289 memcpy(priv->sn, destsn, sizeof(priv->sn)); | |
290 cookie->data = priv; | |
291 aim_cachecookie(sess, cookie); | |
292 | |
293 /* Channel ID */ | |
294 curbyte += aimutil_put16(newpacket->data+curbyte,0x0002); | |
295 | |
296 /* Destination SN (prepended with byte length)*/ | |
297 curbyte += aimutil_put8(newpacket->data+curbyte,strlen(destsn)); | |
298 curbyte += aimutil_putstr(newpacket->data+curbyte, destsn, strlen(destsn)); | |
299 curbyte += aimutil_put16(newpacket->data+curbyte, 0x0003); | |
300 curbyte += aimutil_put16(newpacket->data+curbyte, 0x0000); | |
301 | |
302 /* enTLV start */ | |
303 curbyte += aimutil_put16(newpacket->data+curbyte, 0x0005); | |
304 curbyte += aimutil_put16(newpacket->data+curbyte, 0x0032); | |
305 | |
306 /* Flag data / ICBM Parameters */ | |
307 curbyte += aimutil_put8(newpacket->data+curbyte, 0x00); | |
308 curbyte += aimutil_put8(newpacket->data+curbyte, 0x00); | |
309 | |
310 /* Cookie */ | |
311 curbyte += aimutil_putstr(newpacket->data+curbyte, (char *)cookie, 8); | |
312 | |
313 /*Capability String */ | |
314 curbyte += aimutil_putstr(newpacket->data+curbyte, (char *)cap, 0x10); | |
315 | |
316 /* 000a/0002 : 0001 */ | |
317 curbyte += aimutil_put16(newpacket->data+curbyte, 0x000a); | |
318 curbyte += aimutil_put16(newpacket->data+curbyte, 0x0002); | |
319 curbyte += aimutil_put16(newpacket->data+curbyte, 0x0001); | |
320 | |
321 /* 0003/0004: IP address */ | |
322 curbyte += aimutil_put16(newpacket->data+curbyte, 0x0003); | |
323 curbyte += aimutil_put16(newpacket->data+curbyte, 0x0004); | |
324 for(i = 0;i < 4; i++) | |
325 curbyte += aimutil_put8(newpacket->data+curbyte, d[i]); | |
326 | |
327 /* 0005/0002: Port */ | |
328 curbyte += aimutil_put16(newpacket->data+curbyte, 0x0005); | |
329 curbyte += aimutil_put16(newpacket->data+curbyte, 0x0002); | |
330 curbyte += aimutil_put16(newpacket->data+curbyte, port); | |
331 | |
332 /* 000f/0000: ?? */ | |
333 curbyte += aimutil_put16(newpacket->data+curbyte, 0x000f); | |
334 curbyte += aimutil_put16(newpacket->data+curbyte, 0x0000); | |
335 newpacket->commandlen = curbyte; | |
336 newpacket->lock = 0; | |
337 aim_tx_enqueue(sess, newpacket); | |
338 | |
339 | |
340 /* XXX switch to aim_cloneconn()? */ | |
341 if (!(newconn = aim_newconn(sess, AIM_CONN_TYPE_RENDEZVOUS_OUT, NULL))) | |
342 return NULL; | |
343 | |
344 newconn->fd = listenfd; | |
345 newconn->subtype = AIM_CONN_SUBTYPE_OFT_DIRECTIM; | |
346 newconn->priv = priv; | |
347 newconn->lastactivity = time(NULL); | |
348 | |
349 faimdprintf(sess, 2,"faim: listening (fd = %d, unconnected)\n", newconn->fd); | |
350 | |
351 return newconn; | |
352 } | 344 } |
353 | 345 |
346 #if 0 | |
354 /** | 347 /** |
355 * unsigned int aim_oft_listener_clean - close up old listeners | 348 * unsigned int aim_oft_listener_clean - close up old listeners |
356 * @sess: session to clean up in | 349 * @sess: session to clean up in |
357 * @age: maximum age in seconds | 350 * @age: maximum age in seconds |
358 * | 351 * |
379 faim_mutex_unlock(&cur->active); | 372 faim_mutex_unlock(&cur->active); |
380 } | 373 } |
381 faim_mutex_unlock(&sess->connlistlock); | 374 faim_mutex_unlock(&sess->connlistlock); |
382 return hit; | 375 return hit; |
383 } | 376 } |
377 #endif | |
378 | |
379 faim_export const char *aim_directim_getsn(aim_conn_t *conn) | |
380 { | |
381 struct aim_directim_intdata *intdata; | |
382 | |
383 if (!conn) | |
384 return NULL; | |
385 | |
386 if ((conn->type != AIM_CONN_TYPE_RENDEZVOUS) || | |
387 (conn->subtype != AIM_CONN_SUBTYPE_OFT_DIRECTIM)) | |
388 return NULL; | |
389 | |
390 if (!conn->internal) | |
391 return NULL; | |
392 | |
393 intdata = (struct aim_directim_intdata *)conn->internal; | |
394 | |
395 return intdata->sn; | |
396 } | |
384 | 397 |
385 /** | 398 /** |
386 * aim_directim_connect - connect to buddy for directim | 399 * aim_directim_connect - connect to buddy for directim |
387 * @sess: the session to append the conn to, | 400 * @sess: the session to append the conn to, |
388 * @conn: the BOS connection, | 401 * @sn: the SN we're connecting to |
389 * @priv: the filled-in priv data structure for the connection | 402 * @addr: address to connect to |
390 * | 403 * |
391 * returns conn if connected, %NULL on error | 404 * This is a wrapper for aim_newconn. |
405 * | |
406 * If addr is NULL, the socket is not created, but the connection is | |
407 * allocated and setup to connect. | |
408 * | |
392 */ | 409 */ |
393 faim_export struct aim_conn_t *aim_directim_connect(struct aim_session_t *sess, struct aim_conn_t *conn, struct aim_directim_priv *priv) | 410 faim_export aim_conn_t *aim_directim_connect(aim_session_t *sess, const char *sn, const char *addr, const fu8_t *cookie) |
394 { | 411 { |
395 struct aim_conn_t *newconn = NULL; | 412 aim_conn_t *newconn; |
396 | 413 struct aim_directim_intdata *intdata; |
397 if (!sess || !conn || !priv) | 414 |
398 return NULL; | 415 if (!sess || !sn) |
399 | 416 return NULL; |
400 /* XXX verify that non-blocking connects actually work */ | 417 |
401 newconn = aim_newconn(sess, AIM_CONN_TYPE_RENDEZVOUS, priv->ip); | 418 if (!(intdata = malloc(sizeof(struct aim_directim_intdata)))) |
402 if (!newconn || (newconn->fd == -1)) { | 419 return NULL; |
403 faimdprintf(sess, 2, "could not connect to %s\n", priv->ip); | 420 memset(intdata, 0, sizeof(struct aim_directim_intdata)); |
404 perror("aim_newconn"); | 421 |
405 return newconn; | 422 memcpy(intdata->cookie, cookie, 8); |
406 } | 423 strncpy(intdata->sn, sn, sizeof(intdata->sn)); |
407 | 424 if (addr) |
408 newconn->subtype = AIM_CONN_SUBTYPE_OFT_DIRECTIM; | 425 strncpy(intdata->ip, addr, sizeof(intdata->ip)); |
409 newconn->priv = priv; | 426 |
410 faimdprintf(sess, 2, "faim: connected to peer (fd = %d)\n", newconn->fd); | 427 /* XXX verify that non-blocking connects actually work */ |
411 | 428 if (!(newconn = aim_newconn(sess, AIM_CONN_TYPE_RENDEZVOUS, addr))) { |
412 return newconn; | 429 free(intdata); |
430 return NULL; | |
431 } | |
432 | |
433 if (!newconn) { | |
434 free(intdata); | |
435 return newconn; | |
436 } | |
437 | |
438 newconn->subtype = AIM_CONN_SUBTYPE_OFT_DIRECTIM; | |
439 newconn->internal = intdata; | |
440 | |
441 return newconn; | |
413 } | 442 } |
414 | 443 |
415 /** | 444 /** |
416 * aim_directim_getconn - find a directim conn for buddy name | 445 * aim_directim_getconn - find a directim conn for buddy name |
417 * @sess: your session, | 446 * @sess: your session, |
418 * @name: the name to get, | 447 * @name: the name to get, |
419 * | 448 * |
420 * returns conn for directim with name, %NULL if none found. | 449 * returns conn for directim with name, %NULL if none found. |
421 * | 450 * |
422 */ | 451 */ |
423 faim_export struct aim_conn_t *aim_directim_getconn(struct aim_session_t *sess, const char *name) | 452 faim_export aim_conn_t *aim_directim_getconn(aim_session_t *sess, const char *name) |
424 { | 453 { |
425 struct aim_conn_t *cur; | 454 aim_conn_t *cur; |
426 struct aim_directim_priv *priv; | 455 |
427 | 456 if (!sess || !name || !strlen(name)) |
428 if (!sess || !name) | 457 return NULL; |
429 return NULL; | 458 |
430 | 459 for (cur = sess->connlist; cur; cur = cur->next) { |
431 faim_mutex_lock(&sess->connlistlock); | 460 struct aim_directim_intdata *intdata; |
432 | 461 |
433 for (cur = sess->connlist; cur; cur = cur->next) { | 462 if ((cur->type != AIM_CONN_TYPE_RENDEZVOUS) || (cur->subtype != AIM_CONN_SUBTYPE_OFT_DIRECTIM)) |
434 if (cur->type != AIM_CONN_TYPE_RENDEZVOUS || cur->subtype != AIM_CONN_SUBTYPE_OFT_DIRECTIM) | 463 continue; |
435 continue; | 464 |
436 priv = cur->priv; | 465 intdata = cur->internal; |
437 if (aim_sncmp(priv->sn, name) == 0) | 466 |
438 break; | 467 if (aim_sncmp(intdata->sn, name) == 0) |
439 } faim_mutex_unlock(&sess->connlistlock); | 468 break; |
440 return cur; | 469 } |
470 | |
471 return cur; | |
441 } | 472 } |
442 | 473 |
443 /** | 474 /** |
444 * aim_accepttransfer - accept a file transfer request | 475 * aim_accepttransfer - accept a file transfer request |
445 * @sess: the session, | 476 * @sess: the session, |
452 * @listingsize: length of the listing file(buffer) | 483 * @listingsize: length of the listing file(buffer) |
453 * @listingchecksum: checksum of the listing | 484 * @listingchecksum: checksum of the listing |
454 * @rendid: capability type (%AIM_CAPS_GETFILE or %AIM_CAPS_SENDFILE) | 485 * @rendid: capability type (%AIM_CAPS_GETFILE or %AIM_CAPS_SENDFILE) |
455 * | 486 * |
456 * Returns new connection or %NULL on error. | 487 * Returns new connection or %NULL on error. |
488 * | |
489 * XXX this should take a struct. | |
457 */ | 490 */ |
458 faim_export struct aim_conn_t *aim_accepttransfer(struct aim_session_t *sess, | 491 faim_export aim_conn_t *aim_accepttransfer(aim_session_t *sess, |
459 struct aim_conn_t *conn, | 492 aim_conn_t *conn, |
460 char *sn, char *cookie, | 493 const char *sn, const fu8_t *cookie, |
461 char *ip, | 494 const fu8_t *ip, |
462 unsigned short listingfiles, | 495 fu16_t listingfiles, |
463 unsigned short listingtotsize, | 496 fu16_t listingtotsize, |
464 unsigned short listingsize, | 497 fu16_t listingsize, |
465 unsigned int listingchecksum, | 498 fu32_t listingchecksum, |
466 unsigned short rendid) | 499 fu16_t rendid) |
467 { | 500 { |
501 return NULL; | |
502 #if 0 | |
468 struct command_tx_struct *newpacket, *newoft; | 503 struct command_tx_struct *newpacket, *newoft; |
469 struct aim_conn_t *newconn; | 504 struct aim_conn_t *newconn; |
470 struct aim_fileheader_t *fh; | 505 struct aim_fileheader_t *fh; |
471 struct aim_filetransfer_priv *priv; | 506 struct aim_filetransfer_priv *priv; |
472 struct aim_msgcookie_t *cachedcook; | 507 struct aim_msgcookie_t *cachedcook; |
545 memset(fh->name, 0, sizeof(fh->name)); | 580 memset(fh->name, 0, sizeof(fh->name)); |
546 memcpy(fh->name, "listing.txt", sizeof(fh->name)); | 581 memcpy(fh->name, "listing.txt", sizeof(fh->name)); |
547 | 582 |
548 if (!(newoft->hdr.oft.hdr2 = (char *)calloc(1,newoft->hdr.oft.hdr2len))) { | 583 if (!(newoft->hdr.oft.hdr2 = (char *)calloc(1,newoft->hdr.oft.hdr2len))) { |
549 newoft->lock = 0; | 584 newoft->lock = 0; |
550 aim_tx_destroy(newoft); | 585 aim_frame_destroy(newoft); |
551 /* XXX: conn leak */ | 586 /* XXX: conn leak */ |
552 perror("calloc (1)"); | 587 perror("calloc (1)"); |
553 return NULL; | 588 return NULL; |
554 } | 589 } |
555 | 590 |
607 curbyte += aim_putcap(newpacket->data+curbyte, 0x10, rendid); | 642 curbyte += aim_putcap(newpacket->data+curbyte, 0x10, rendid); |
608 newpacket->lock = 0; | 643 newpacket->lock = 0; |
609 aim_tx_enqueue(sess, newpacket); | 644 aim_tx_enqueue(sess, newpacket); |
610 | 645 |
611 return newconn; | 646 return newconn; |
647 #endif | |
612 } | 648 } |
613 | 649 |
614 /** | 650 /** |
615 * aim_getlisting(FILE *file) -- get an aim_fileheader_t for a given FILE* | 651 * aim_getlisting(FILE *file) -- get an aim_fileheader_t for a given FILE* |
616 * @file is an opened listing file | 652 * @file is an opened listing file |
619 * | 655 * |
620 * Currently omits checksum. we'll fix this when AOL breaks us, i | 656 * Currently omits checksum. we'll fix this when AOL breaks us, i |
621 * guess. | 657 * guess. |
622 * | 658 * |
623 */ | 659 */ |
624 | 660 faim_export struct aim_fileheader_t *aim_getlisting(aim_session_t *sess, FILE *file) |
625 faim_export struct aim_fileheader_t *aim_getlisting(struct aim_session_t *sess, FILE *file) | 661 { |
626 { | 662 return NULL; |
663 #if 0 | |
627 struct aim_fileheader_t *fh; | 664 struct aim_fileheader_t *fh; |
628 u_long totsize = 0, size = 0, checksum = 0xffff0000; | 665 u_long totsize = 0, size = 0, checksum = 0xffff0000; |
629 short totfiles = 0; | 666 short totfiles = 0; |
630 char *linebuf, sizebuf[9]; | 667 char *linebuf, sizebuf[9]; |
631 | 668 |
725 memcpy(fh->name, "listing.txt", sizeof(fh->name)); | 762 memcpy(fh->name, "listing.txt", sizeof(fh->name)); |
726 memset(fh->name+strlen(fh->name), 0, 64-strlen(fh->name)); | 763 memset(fh->name+strlen(fh->name), 0, 64-strlen(fh->name)); |
727 | 764 |
728 faimdprintf(sess, 2, "faim: OFT: listing fh name %s / %s\n", fh->name, (fh->name+(strlen(fh->name)))); | 765 faimdprintf(sess, 2, "faim: OFT: listing fh name %s / %s\n", fh->name, (fh->name+(strlen(fh->name)))); |
729 return fh; | 766 return fh; |
767 #endif | |
730 } | 768 } |
731 | 769 |
732 /** | 770 /** |
733 * aim_listenestablish - create a listening socket on a port. | 771 * aim_listenestablish - create a listening socket on a port. |
734 * @portnum: the port number to bind to. | 772 * @portnum: the port number to bind to. |
735 * | 773 * |
736 * you need to call accept() when it's connected. returns your fd | 774 * you need to call accept() when it's connected. returns your fd |
737 * | 775 * |
738 */ | 776 */ |
739 faim_export int aim_listenestablish(u_short portnum) | 777 static int listenestablish(fu16_t portnum) |
740 { | 778 { |
741 #if defined(__linux__) | 779 #if defined(__linux__) |
742 /* XXX what other OS's support getaddrinfo? */ | 780 /* XXX what other OS's support getaddrinfo? */ |
743 int listenfd; | 781 int listenfd; |
744 const int on = 1; | 782 const int on = 1; |
745 struct addrinfo hints, *res, *ressave; | 783 struct addrinfo hints, *res, *ressave; |
746 char serv[5]; | 784 char serv[5]; |
747 | 785 |
748 snprintf(serv, sizeof(serv), "%d", portnum); | 786 snprintf(serv, sizeof(serv), "%d", portnum); |
749 memset(&hints, 0, sizeof(struct addrinfo)); | 787 memset(&hints, 0, sizeof(struct addrinfo)); |
750 hints.ai_flags = AI_PASSIVE; | 788 hints.ai_flags = AI_PASSIVE; |
751 hints.ai_family = AF_UNSPEC; | 789 hints.ai_family = AF_UNSPEC; |
752 hints.ai_socktype = SOCK_STREAM; | 790 hints.ai_socktype = SOCK_STREAM; |
753 if (getaddrinfo(NULL /*any IP*/, serv, &hints, &res) != 0) { | 791 if (getaddrinfo(NULL /*any IP*/, serv, &hints, &res) != 0) { |
754 perror("getaddrinfo"); | 792 perror("getaddrinfo"); |
755 return -1; | 793 return -1; |
756 } | 794 } |
757 ressave = res; | 795 ressave = res; |
758 do { | 796 do { |
759 listenfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol); | 797 listenfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol); |
760 if (listenfd < 0) | 798 if (listenfd < 0) |
761 continue; | 799 continue; |
762 setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); | 800 setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); |
763 if (bind(listenfd, res->ai_addr, res->ai_addrlen) == 0) | 801 if (bind(listenfd, res->ai_addr, res->ai_addrlen) == 0) |
764 break; | 802 break; |
765 /* success */ | 803 /* success */ |
766 close(listenfd); | 804 close(listenfd); |
767 } while ( (res = res->ai_next) ); | 805 } while ( (res = res->ai_next) ); |
768 | 806 |
769 if (!res) | 807 if (!res) |
770 return -1; | 808 return -1; |
771 | 809 |
772 if (listen(listenfd, 1024)!=0) { | 810 if (listen(listenfd, 1024)!=0) { |
773 perror("listen"); | 811 perror("listen"); |
774 return -1; | 812 return -1; |
775 } | 813 } |
776 | 814 |
777 freeaddrinfo(ressave); | 815 freeaddrinfo(ressave); |
778 return listenfd; | 816 return listenfd; |
779 #else | 817 #else |
780 int listenfd; | 818 int listenfd; |
781 const int on = 1; | 819 const int on = 1; |
782 struct sockaddr_in sockin; | 820 struct sockaddr_in sockin; |
783 | 821 |
784 if ((listenfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { | 822 if ((listenfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { |
785 perror("socket(listenfd)"); | 823 perror("socket(listenfd)"); |
786 return -1; | 824 return -1; |
787 } | 825 } |
788 | 826 |
789 if (setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on) != 0)) { | 827 if (setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on) != 0)) { |
790 perror("setsockopt(listenfd)"); | 828 perror("setsockopt(listenfd)"); |
791 close(listenfd); | 829 close(listenfd); |
792 return -1; | 830 return -1; |
793 } | 831 } |
794 | 832 |
795 memset(&sockin, 0, sizeof(struct sockaddr_in)); | 833 memset(&sockin, 0, sizeof(struct sockaddr_in)); |
796 sockin.sin_family = AF_INET; | 834 sockin.sin_family = AF_INET; |
797 sockin.sin_port = htons(portnum); | 835 sockin.sin_port = htons(portnum); |
798 | 836 |
799 if (bind(listenfd, (struct sockaddr *)&sockin, sizeof(struct sockaddr_in)) != 0) { | 837 if (bind(listenfd, (struct sockaddr *)&sockin, sizeof(struct sockaddr_in)) != 0) { |
800 perror("bind(listenfd)"); | 838 perror("bind(listenfd)"); |
801 close(listenfd); | 839 close(listenfd); |
802 return -1; | 840 return -1; |
803 } | 841 } |
804 if (listen(listenfd, 4) != 0) { | 842 if (listen(listenfd, 4) != 0) { |
805 perror("listen(listenfd)"); | 843 perror("listen(listenfd)"); |
806 close(listenfd); | 844 close(listenfd); |
807 return -1; | 845 return -1; |
808 } | 846 } |
809 return listenfd; | 847 return listenfd; |
810 #endif | 848 #endif |
811 } | 849 } |
850 | |
851 static int getcommand_getfile(aim_session_t *sess, aim_conn_t *conn) | |
852 { | |
853 #if 0 | |
854 struct aim_filetransfer_priv *ft; | |
855 aim_rxcallback_t userfunc; | |
856 | |
857 ft = conn->priv; | |
858 if (ft->state == 2) { | |
859 /* waiting on listing data */ | |
860 int ret = 0; | |
861 char *listing; | |
862 struct command_tx_struct *newoft; | |
863 | |
864 if (!(listing = malloc(ft->fh.size))) | |
865 return -1; | |
866 | |
867 ft->state = 0; | |
868 if (aim_recv(conn->fd, listing, ft->fh.size) != ft->fh.size) | |
869 faimdprintf(sess, 2, "OFT get: file %s was short. (0x%lx)\n", ft->fh.name, ft->fh.size); | |
870 | |
871 if (!(newoft = aim_tx_new(sess, conn, AIM_FRAMETYPE_OFT, 0x120b, 0))) { | |
872 faimdprintf(sess, 2, "faim: aim_get_command_rendezvous: getfile listing: tx_new OFT failed\n"); | |
873 faim_mutex_unlock(&conn->active); | |
874 free(listing); | |
875 aim_conn_close(conn); | |
876 return -1; | |
877 } | |
878 | |
879 memcpy(newoft->hdr.oft.magic, "OFT2", 4); | |
880 newoft->hdr.oft.hdr2len = 0x100 - 8; | |
881 | |
882 /* Protocol BS - set nrecvd to size of listing, recvcsum to listing checksum, flags to 0 */ | |
883 | |
884 ft->fh.nrecvd = ft->fh.size; | |
885 ft->fh.recvcsum = ft->fh.checksum; | |
886 ft->fh.flags = 0; | |
887 | |
888 if (!(newoft->hdr.oft.hdr2 = (char *)calloc(1,newoft->hdr.oft.hdr2len))) { | |
889 aim_frame_destroy(newoft); | |
890 free(listing); | |
891 return -1; | |
892 } | |
893 | |
894 if (!(aim_oft_buildheader((unsigned char *)newoft->hdr.oft.hdr2, &(ft->fh)))) | |
895 faimdprintf(sess, 2, "eek! bh fail listing\n"); | |
896 | |
897 /* send the 120b */ | |
898 aim_tx_enqueue(sess, newoft); | |
899 if ( (userfunc = aim_callhandler(sess, conn, AIM_CB_FAM_OFT, AIM_CB_OFT_GETFILELISTING)) ) | |
900 ret = userfunc(sess, NULL, conn, ft, listing); | |
901 | |
902 free(listing); | |
903 return ret; | |
904 } | |
905 | |
906 if (ft->state == 3) { | |
907 /* waiting on file data */ | |
908 if ( (userfunc = aim_callhandler(sess, conn, AIM_CB_FAM_OFT, AIM_CB_OFT_GETFILERECEIVE)) ) | |
909 return userfunc(sess, NULL, conn, ft); | |
910 return 0; | |
911 } | |
912 | |
913 if (ft->state == 4) { | |
914 if( (userfunc = aim_callhandler(sess, conn, AIM_CB_FAM_OFT, AIM_CB_OFT_GETFILESTATE4)) ) | |
915 return userfunc(sess, NULL, conn); | |
916 aim_conn_close(conn); | |
917 return 0; | |
918 } | |
919 | |
920 return 0; | |
921 #else | |
922 return -1; | |
923 #endif | |
924 } | |
925 | |
926 static void connclose_sendfile(aim_session_t *sess, aim_conn_t *conn) | |
927 { | |
928 aim_msgcookie_t *cook; | |
929 struct aim_filetransfer_priv *priv = (struct aim_filetransfer_priv *)conn->priv; | |
930 | |
931 cook = aim_uncachecookie(sess, priv->cookie, AIM_COOKIETYPE_OFTSEND); | |
932 aim_cookie_free(sess, cook); | |
933 | |
934 return; | |
935 } | |
936 | |
937 static void connkill_sendfile(aim_session_t *sess, aim_conn_t *conn) | |
938 { | |
939 | |
940 free(conn->internal); | |
941 | |
942 return; | |
943 } | |
944 | |
945 static void connclose_getfile(aim_session_t *sess, aim_conn_t *conn) | |
946 { | |
947 aim_msgcookie_t *cook; | |
948 struct aim_filetransfer_priv *priv = (struct aim_filetransfer_priv *)conn->priv; | |
949 | |
950 cook = aim_uncachecookie(sess, priv->cookie, AIM_COOKIETYPE_OFTGET); | |
951 aim_cookie_free(sess, cook); | |
952 | |
953 return; | |
954 } | |
955 | |
956 static void connkill_getfile(aim_session_t *sess, aim_conn_t *conn) | |
957 { | |
958 | |
959 free(conn->internal); | |
960 | |
961 return; | |
962 } | |
963 | |
964 static void connclose_directim(aim_session_t *sess, aim_conn_t *conn) | |
965 { | |
966 struct aim_directim_intdata *intdata = (struct aim_directim_intdata *)conn->internal; | |
967 aim_msgcookie_t *cook; | |
968 | |
969 cook = aim_uncachecookie(sess, intdata->cookie, AIM_COOKIETYPE_OFTIM); | |
970 aim_cookie_free(sess, cook); | |
971 | |
972 return; | |
973 } | |
974 | |
975 static void connkill_directim(aim_session_t *sess, aim_conn_t *conn) | |
976 { | |
977 | |
978 free(conn->internal); | |
979 | |
980 return; | |
981 } | |
982 | |
983 faim_internal void aim_conn_close_rend(aim_session_t *sess, aim_conn_t *conn) | |
984 { | |
985 | |
986 if (conn->type != AIM_CONN_TYPE_RENDEZVOUS) | |
987 return; | |
988 | |
989 if (conn->subtype == AIM_CONN_SUBTYPE_OFT_SENDFILE) | |
990 connclose_sendfile(sess, conn); | |
991 else if (conn->subtype == AIM_CONN_SUBTYPE_OFT_GETFILE) | |
992 connclose_getfile(sess, conn); | |
993 else if (conn->subtype == AIM_CONN_SUBTYPE_OFT_DIRECTIM) | |
994 connclose_directim(sess, conn); | |
995 | |
996 return; | |
997 } | |
998 | |
999 faim_internal void aim_conn_kill_rend(aim_session_t *sess, aim_conn_t *conn) | |
1000 { | |
1001 | |
1002 if (conn->type != AIM_CONN_TYPE_RENDEZVOUS) | |
1003 return; | |
1004 | |
1005 if (conn->subtype == AIM_CONN_SUBTYPE_OFT_SENDFILE) | |
1006 connkill_sendfile(sess, conn); | |
1007 else if (conn->subtype == AIM_CONN_SUBTYPE_OFT_GETFILE) | |
1008 connkill_getfile(sess, conn); | |
1009 else if (conn->subtype == AIM_CONN_SUBTYPE_OFT_DIRECTIM) | |
1010 connkill_directim(sess, conn); | |
1011 | |
1012 return; | |
1013 } | |
1014 | |
1015 static int handlehdr_directim(aim_session_t *sess, aim_conn_t *conn, fu8_t *hdr) | |
1016 { | |
1017 aim_frame_t fr; | |
1018 aim_rxcallback_t userfunc; | |
1019 fu32_t payloadlength; | |
1020 fu16_t flags; | |
1021 char *snptr = NULL; | |
1022 | |
1023 fr.conn = conn; | |
1024 | |
1025 payloadlength = aimutil_get32(hdr+22); | |
1026 flags = aimutil_get16(hdr+32); | |
1027 snptr = (char *)hdr+38; | |
1028 | |
1029 faimdprintf(sess, 2, "faim: OFT frame: handlehdr_directim: %04x / %04x / %s\n", payloadlength, flags, snptr); | |
1030 | |
1031 if (flags == 0x000e) { | |
1032 int ret = 0; | |
1033 | |
1034 if ((userfunc = aim_callhandler(sess, conn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIMTYPING))) | |
1035 ret = userfunc(sess, &fr, snptr); | |
1036 | |
1037 return ret; | |
1038 | |
1039 } else if ((flags == 0x0000) && payloadlength) { | |
1040 char *msg; | |
1041 int ret = 0; | |
1042 | |
1043 if (!(msg = calloc(1, payloadlength+1))) | |
1044 return -1; | |
1045 | |
1046 if (aim_recv(conn->fd, msg, payloadlength) < payloadlength) { | |
1047 free(msg); | |
1048 return -1; | |
1049 } | |
1050 | |
1051 msg[payloadlength] = '\0'; | |
1052 | |
1053 if ( (userfunc = aim_callhandler(sess, conn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIMINCOMING)) ) | |
1054 ret = userfunc(sess, &fr, snptr, msg); | |
1055 | |
1056 free(msg); | |
1057 | |
1058 return ret; | |
1059 } | |
1060 | |
1061 return 0; | |
1062 } | |
1063 | |
1064 static int handlehdr_getfile_listing(aim_session_t *sess, aim_conn_t *conn, fu8_t *hdr) | |
1065 { | |
1066 #if 0 | |
1067 struct aim_filetransfer_priv *ft; | |
1068 struct aim_fileheader_t *fh; | |
1069 struct aim_msgcookie_t *cook; | |
1070 struct command_tx_struct *newoft; | |
1071 aim_rxcallback_t userfunc; | |
1072 | |
1073 faimdprintf(sess, 2,"faim: rend: fileget 0x1108\n"); | |
1074 fh = aim_oft_getfh(hdr); | |
1075 | |
1076 faim_mutex_unlock(&conn->active); | |
1077 | |
1078 if (!(cook = aim_checkcookie(sess, fh->bcookie, AIM_COOKIETYPE_OFTGET))) { | |
1079 free(fh); | |
1080 return -1; | |
1081 } | |
1082 | |
1083 ft = cook->data; | |
1084 | |
1085 /* we're waaaaiiiting.. for listing.txt */ | |
1086 ft->state = 2; | |
1087 | |
1088 memcpy(&(ft->fh), fh, sizeof(struct aim_fileheader_t)); | |
1089 free(fh); | |
1090 | |
1091 if(aim_cachecookie(sess, cook) == -1) { | |
1092 faimdprintf(sess, 1, "error caching cookie\n"); | |
1093 return -1; | |
1094 } | |
1095 | |
1096 if (!(newoft = aim_tx_new(sess, conn, AIM_FRAMETYPE_OFT, 0x1209, 0))) { | |
1097 aim_conn_close(conn); | |
1098 return -1; | |
1099 } | |
1100 | |
1101 memcpy(newoft->hdr.oft.magic, "OFT2", 4); | |
1102 newoft->hdr.oft.hdr2len = 0x100 - 8; | |
1103 | |
1104 if (!(newoft->hdr.oft.hdr2 = (char *)calloc(1,newoft->hdr.oft.hdr2len))) { | |
1105 newoft->lock = 0; | |
1106 aim_frame_destroy(newoft); | |
1107 return -1; | |
1108 } | |
1109 | |
1110 if (!(aim_oft_buildheader((unsigned char *)newoft->hdr.oft.hdr2, &(ft->fh)))) { | |
1111 newoft->lock = 0; | |
1112 aim_frame_destroy(newoft); | |
1113 return -1; | |
1114 } | |
1115 | |
1116 newoft->lock = 0; | |
1117 aim_tx_enqueue(sess, newoft); | |
1118 #endif | |
1119 return -1; | |
1120 } | |
1121 | |
1122 static int handlehdr_getfile_listing2(aim_session_t *sess, aim_conn_t *conn, fu8_t *hdr) | |
1123 { | |
1124 #if 0 | |
1125 struct aim_filetransfer_priv *ft; | |
1126 struct aim_fileheader_t *fh; | |
1127 struct aim_msgcookie_t *cook; | |
1128 int ret = 0; | |
1129 aim_rxcallback_t userfunc; | |
1130 | |
1131 fh = aim_oft_getfh(hdr); | |
1132 | |
1133 if (!(cook = aim_checkcookie(sess, fh->bcookie, AIM_COOKIETYPE_OFTGET))) | |
1134 faimdprintf(sess, 2, "shit, no cookie in 0x1209. (%i/%s)going to crash..\n", AIM_COOKIETYPE_OFTGET, fh->bcookie); | |
1135 | |
1136 ft = cook->data; | |
1137 | |
1138 if (ft->fh.size != fh->size) | |
1139 faimdprintf(sess, 2, "hrm. ft->fh.size (%ld) != fh->size (%ld). um. using ft->fh.size\n", ft->fh.size, fh->size); | |
1140 | |
1141 if ( (userfunc = aim_callhandler(sess, conn, AIM_CB_FAM_OFT, AIM_CB_OFT_GETFILELISTINGREQ))) | |
1142 ret = userfunc(sess, NULL, conn, fh); | |
1143 | |
1144 faimdprintf(sess, 2, "faim: get_command_rendezvous: hit end of 1209\n"); | |
1145 | |
1146 free(fh); | |
1147 | |
1148 return ret; | |
1149 #else | |
1150 return -1; | |
1151 #endif | |
1152 } | |
1153 | |
1154 static int handlehdr_getfile_listing3(aim_session_t *sess, aim_conn_t *conn, fu8_t *hdr) | |
1155 { | |
1156 #if 0 | |
1157 struct aim_filetransfer_priv *ft; | |
1158 struct aim_msgcookie_t *cook; | |
1159 struct aim_fileheader_t *fh; | |
1160 aim_rxcallback_t userfunc; | |
1161 | |
1162 fh = aim_oft_getfh(hdr); | |
1163 | |
1164 if (!(cook = aim_checkcookie(sess, fh->bcookie, AIM_COOKIETYPE_OFTGET))) { | |
1165 free(fh); | |
1166 return -1; | |
1167 } | |
1168 | |
1169 free(fh); | |
1170 | |
1171 ft = cook->data; | |
1172 | |
1173 if (aim_cachecookie(sess, cook) == -1) | |
1174 return -1; | |
1175 | |
1176 if ((userfunc = aim_callhandler(sess, conn, AIM_CB_FAM_OFT, AIM_CB_OFT_GETFILELISTINGRXCONFIRM))) | |
1177 return userfunc(sess, NULL, conn); | |
1178 #endif | |
1179 return -1; | |
1180 } | |
1181 | |
1182 static int handlehdr_getfile_request(aim_session_t *sess, aim_conn_t *conn, fu8_t *hdr) | |
1183 { | |
1184 #if 0 | |
1185 struct aim_filetransfer_priv *ft; | |
1186 struct aim_msgcookie_t *cook; | |
1187 struct aim_fileheader_t *fh; | |
1188 struct command_tx_struct *newoft; | |
1189 int i = 0; | |
1190 aim_rxcallback_t userfunc; | |
1191 | |
1192 fh = aim_oft_getfh(hdr); | |
1193 | |
1194 if (!(cook = aim_checkcookie(sess, fh->bcookie, AIM_COOKIETYPE_OFTGET))) { | |
1195 free(fh); | |
1196 return -1; | |
1197 } | |
1198 | |
1199 ft = cook->data; | |
1200 memcpy(&(ft->fh), fh, sizeof(struct aim_fileheader_t)); | |
1201 free(fh); | |
1202 | |
1203 aim_cachecookie(sess, cook); | |
1204 | |
1205 faimdprintf(sess, 2, "faim: fileget: %s seems to want %s\n", ft->sn, ft->fh.name); | |
1206 | |
1207 if ( (userfunc = aim_callhandler(sess, conn, AIM_CB_FAM_OFT, AIM_CB_OFT_GETFILEFILEREQ)) ) | |
1208 i = userfunc(sess, NULL, conn, &(ft->fh), cook->cookie); | |
1209 | |
1210 if (i < 0) | |
1211 return i; | |
1212 | |
1213 if (!(newoft = aim_tx_new(sess, conn, AIM_FRAMETYPE_OFT, 0x0101, 0))) { | |
1214 faimdprintf(sess, 2, "faim: send_final_transfer: tx_new OFT failed\n"); | |
1215 return -1; | |
1216 } | |
1217 | |
1218 newoft->lock = 1; | |
1219 memcpy(newoft->hdr.oft.magic, "OFT2", 4); | |
1220 newoft->hdr.oft.hdr2len = 0x100 - 8; | |
1221 | |
1222 if (!(newoft->hdr.oft.hdr2 = calloc(1,newoft->hdr.oft.hdr2len))) { | |
1223 aim_frame_destroy(newoft); | |
1224 return -1; | |
1225 } | |
1226 | |
1227 /* protocol BS: nrecvd, recvcsum to 0, flags to 0x20. */ | |
1228 ft->fh.nrecvd = 0; | |
1229 ft->fh.recvcsum = 0; | |
1230 ft->fh.flags = 0x20; | |
1231 | |
1232 aim_oft_buildheader((unsigned char *)newoft->hdr.oft.hdr2, &(ft->fh)); | |
1233 | |
1234 newoft->lock = 0; | |
1235 aim_tx_enqueue(sess, newoft); | |
1236 | |
1237 faimdprintf(sess, 2, "faim: OFT: OFT file header enqueued.\n"); | |
1238 | |
1239 return i; | |
1240 #else | |
1241 return -1; | |
1242 #endif | |
1243 } | |
1244 | |
1245 static int handlehdr_getfile_sending(aim_session_t *sess, aim_conn_t *conn, fu8_t *hdr) | |
1246 { | |
1247 #if 0 | |
1248 struct aim_fileheader_t *fh; | |
1249 struct aim_filetransfer_priv *ft; | |
1250 struct aim_msgcookie_t *cook; | |
1251 struct command_tx_struct *newoft; | |
1252 aim_rxcallback_t userfunc; | |
1253 | |
1254 fh = aim_oft_getfh(hdr); | |
1255 | |
1256 if (!(cook = aim_checkcookie(sess, fh->bcookie, AIM_COOKIETYPE_OFTGET))) { | |
1257 free(fh); | |
1258 return -1; | |
1259 } | |
1260 | |
1261 free(fh); | |
1262 | |
1263 ft = cook->data; | |
1264 | |
1265 ft->state = 3; | |
1266 | |
1267 if (aim_cachecookie(sess, cook) == -1) | |
1268 return -1; | |
1269 | |
1270 faimdprintf(sess, 2, "faim: fileget: %s seems to want to send %s\n", ft->sn, ft->fh.name); | |
1271 | |
1272 if (!(newoft = aim_tx_new(sess, conn, AIM_FRAMETYPE_OFT, 0x0202, 0))) { | |
1273 faimdprintf(sess, 2, "faim: send_final_transfer: tx_new OFT failed\n"); | |
1274 return -1; | |
1275 } | |
1276 | |
1277 newoft->lock = 1; | |
1278 memcpy(newoft->hdr.oft.magic, "OFT2", 4); | |
1279 | |
1280 newoft->hdr.oft.hdr2len = 0x100 - 8; | |
1281 | |
1282 if (!(newoft->hdr.oft.hdr2 = calloc(1,newoft->hdr.oft.hdr2len))) { | |
1283 aim_frame_destroy(newoft); | |
1284 return -1; | |
1285 } | |
1286 | |
1287 aim_oft_buildheader((unsigned char *)newoft->hdr.oft.hdr2, &(ft->fh)); | |
1288 | |
1289 newoft->lock = 0; | |
1290 aim_tx_enqueue(sess, newoft); | |
1291 | |
1292 faimdprintf(sess, 2, "faim: OFT: OFT 0x0202 enqueued.\n"); | |
1293 | |
1294 if ( (userfunc = aim_callhandler(sess, conn, AIM_CB_FAM_OFT, AIM_CB_OFT_GETFILEFILEREQ)) == NULL) | |
1295 return 1; | |
1296 #else | |
1297 return -1; | |
1298 #endif | |
1299 } | |
1300 | |
1301 static int handlehdr_getfile_recv(aim_session_t *sess, aim_conn_t *conn, fu8_t *hdr) | |
1302 { | |
1303 #if 0 | |
1304 struct aim_fileheader_t *fh; | |
1305 struct aim_filetransfer_priv *ft; | |
1306 struct aim_msgcookie_t *cook; | |
1307 int ret = 1; | |
1308 aim_rxcallback_t userfunc; | |
1309 | |
1310 fh = aim_oft_getfh(hdr); | |
1311 | |
1312 if (!(cook = aim_checkcookie(sess, fh->bcookie, AIM_COOKIETYPE_OFTGET))) { | |
1313 free(fh); | |
1314 return -1; | |
1315 } | |
1316 | |
1317 ft = cook->data; | |
1318 | |
1319 faimdprintf(sess, 2, "faim: get_rend: looks like we're ready to send data.(oft 0x0202)\n"); | |
1320 | |
1321 if ( (userfunc = aim_callhandler(sess, conn, AIM_CB_FAM_OFT, AIM_CB_OFT_GETFILEFILESEND)) ) | |
1322 ret = userfunc(sess, NULL, conn, fh); | |
1323 | |
1324 free(fh); | |
1325 | |
1326 return ret; | |
1327 #else | |
1328 return -1; | |
1329 #endif | |
1330 } | |
1331 | |
1332 static int handlehdr_getfile_finish(aim_session_t *sess, aim_conn_t *conn, fu8_t *hdr) | |
1333 { | |
1334 #if 0 | |
1335 struct aim_fileheader_t *fh; | |
1336 aim_rxcallback_t userfunc; | |
1337 | |
1338 fh = aim_oft_getfh(hdr); | |
1339 | |
1340 faimdprintf(sess, 2, "faim: get_rend: looks like we're done with a transfer (oft 0x0204)\n"); | |
1341 | |
1342 if ( (userfunc = aim_callhandler(sess, conn, AIM_CB_FAM_OFT, AIM_CB_OFT_GETFILECOMPLETE)) ) | |
1343 userfunc(sess, NULL, conn, fh); | |
1344 | |
1345 free(fh); | |
1346 #endif | |
1347 | |
1348 return -1; | |
1349 } | |
812 | 1350 |
813 /** | 1351 /** |
814 * aim_get_command_rendezvous - OFT equivalent of aim_get_command | 1352 * aim_get_command_rendezvous - OFT equivalent of aim_get_command |
815 * @sess: session to work on | 1353 * @sess: session to work on |
816 * @conn: conn to pull data from | 1354 * @conn: conn to pull data from |
817 * | 1355 * |
818 * this reads and handles data from conn->fd. currently a little rough | 1356 * this reads and handles data from conn->fd. currently a little rough |
819 * around the edges | 1357 * around the edges |
820 */ | 1358 */ |
821 faim_internal int aim_get_command_rendezvous(struct aim_session_t *sess, struct aim_conn_t *conn) | 1359 faim_internal int aim_get_command_rendezvous(aim_session_t *sess, aim_conn_t *conn) |
822 { | 1360 { |
823 unsigned char hdrbuf1[6]; | 1361 fu8_t hdrbuf1[6]; |
824 unsigned char *hdr = NULL; | 1362 fu8_t *hdr = NULL; |
825 int hdrlen, hdrtype; | 1363 int hdrlen, hdrtype; |
826 int flags = 0; | 1364 int ret = -1; |
827 aim_rxcallback_t userfunc = NULL; | 1365 |
828 | 1366 if (!sess || !conn) |
829 if (!sess || !conn || !conn->priv) | 1367 return -1; |
830 return -1; | 1368 |
831 | 1369 memset(hdrbuf1, 0, sizeof(hdrbuf1)); |
832 memset(hdrbuf1, 0, sizeof(hdrbuf1)); | 1370 |
833 faim_mutex_lock(&conn->active); | 1371 /* I guess? I didn't understand any of that mess... */ |
834 | 1372 if (conn->subtype == AIM_CONN_SUBTYPE_OFT_GETFILE) |
835 /* gets locked down for the entirety */ | 1373 return getcommand_getfile(sess, conn); |
836 | 1374 |
837 if (conn->subtype == AIM_CONN_SUBTYPE_OFT_GETFILE ) { | 1375 /* XXX fix all the error cases here */ |
838 struct aim_filetransfer_priv *ft; | 1376 if (aim_recv(conn->fd, hdrbuf1, 6) < 6) { |
839 ft = conn->priv; | 1377 |
840 if (ft->state == 2) { | 1378 faimdprintf(sess, 2, "faim: rend: read error (fd: %i)\n", conn->fd); |
841 /* waiting on listing data */ | 1379 |
842 int ret = 0; | 1380 aim_conn_close(conn); |
843 char *listing; | 1381 |
844 struct command_tx_struct *newoft; | 1382 return -1; |
845 if (!(listing = malloc(ft->fh.size))) { | 1383 } |
846 faim_mutex_unlock(&conn->active); | 1384 |
847 return -1; | 1385 hdrlen = aimutil_get16(hdrbuf1+4); |
848 } | 1386 hdrlen -= 6; |
849 | 1387 |
850 ft->state = 0; | 1388 hdr = malloc(hdrlen); |
851 if (aim_recv(conn->fd, listing, ft->fh.size) != ft->fh.size) | 1389 |
852 faimdprintf(sess, 2, "OFT get: file %s was short. (0x%lx)\n", ft->fh.name, ft->fh.size); | 1390 if (aim_recv(conn->fd, hdr, hdrlen) < hdrlen) { |
853 | 1391 faimdprintf(sess, 2, "faim: rend: read2 error on %d (%d)\n", conn->fd, hdrlen); |
854 if (!(newoft = aim_tx_new(sess, conn, AIM_FRAMETYPE_OFT, 0x120b, 0))) { | 1392 free(hdr); |
855 faimdprintf(sess, 2, "faim: aim_get_command_rendezvous: getfile listing: tx_new OFT failed\n"); | 1393 aim_conn_close(conn); |
856 faim_mutex_unlock(&conn->active); | 1394 return -1; |
857 free(listing); | 1395 } |
858 aim_conn_close(conn); | 1396 |
859 return -1; | 1397 hdrtype = aimutil_get16(hdr); |
860 } | 1398 |
861 | 1399 if (hdrtype == 0x0001) |
862 newoft->lock = 1; | 1400 ret = handlehdr_directim(sess, conn, hdr); |
863 | 1401 else if (hdrtype == 0x1108) /* getfile listing.txt incoming tx->rx */ |
864 memcpy(newoft->hdr.oft.magic, "OFT2", 4); | 1402 ret = handlehdr_getfile_listing(sess, conn, hdr); |
865 newoft->hdr.oft.hdr2len = 0x100 - 8; | 1403 else if (hdrtype == 0x1209) /* get file listing ack rx->tx */ |
866 | 1404 ret = handlehdr_getfile_listing2(sess, conn, hdr); |
867 /* Protocol BS - set nrecvd to size of listing, recvcsum to | 1405 else if (hdrtype == 0x120b) /* get file listing rx confirm */ |
868 listing checksum, flags to 0 */ | 1406 ret = handlehdr_getfile_listing3(sess, conn, hdr); |
869 | 1407 else if (hdrtype == 0x120c) /* getfile request */ |
870 ft->fh.nrecvd = ft->fh.size; | 1408 ret = handlehdr_getfile_request(sess, conn, hdr); |
871 ft->fh.recvcsum = ft->fh.checksum; | 1409 else if (hdrtype == 0x0101) /* getfile sending data */ |
872 ft->fh.flags = 0; | 1410 ret = handlehdr_getfile_sending(sess, conn, hdr); |
873 | 1411 else if (hdrtype == 0x0202) /* getfile recv data */ |
874 if (!(newoft->hdr.oft.hdr2 = (char *)calloc(1,newoft->hdr.oft.hdr2len))) { | 1412 ret = handlehdr_getfile_recv(sess, conn, hdr); |
875 newoft->lock = 0; | 1413 else if (hdrtype == 0x0204) /* getfile finished */ |
876 aim_tx_destroy(newoft); | 1414 ret = handlehdr_getfile_finish(sess, conn, hdr); |
877 free(listing); | 1415 else { |
878 faim_mutex_unlock(&conn->active); | 1416 faimdprintf(sess, 2,"faim: OFT frame: uknown type %04x\n", hdrtype); |
879 return -1; | 1417 ret = -1; |
880 } | 1418 } |
881 | 1419 |
882 if (!(aim_oft_buildheader((unsigned char *)newoft->hdr.oft.hdr2, &(ft->fh)))) | 1420 free(hdr); |
883 faimdprintf(sess, 2, "eek! bh fail listing\n"); | 1421 |
884 | 1422 if (ret == -1) |
885 /* send the 120b */ | 1423 aim_conn_close(conn); |
886 newoft->lock = 0; | 1424 |
887 aim_tx_enqueue(sess, newoft); | 1425 return ret; |
888 if ( (userfunc = aim_callhandler(sess, conn, AIM_CB_FAM_OFT, AIM_CB_OFT_GETFILELISTING)) ) | 1426 } |
889 ret = userfunc(sess, NULL, conn, ft, listing); | 1427 |
890 | 1428 #if 0 |
891 faim_mutex_unlock(&conn->active); | |
892 free(listing); | |
893 return ret; | |
894 } | |
895 if (ft->state == 3) { | |
896 /* waiting on file data */ | |
897 if ( (userfunc = aim_callhandler(sess, conn, AIM_CB_FAM_OFT, AIM_CB_OFT_GETFILERECEIVE)) ) { | |
898 faim_mutex_unlock(&conn->active); | |
899 return userfunc(sess, NULL, conn, ft); | |
900 } | |
901 faim_mutex_unlock(&conn->active); | |
902 return 0; | |
903 } | |
904 if(ft->state == 4) { | |
905 if( (userfunc = aim_callhandler(sess, conn, AIM_CB_FAM_OFT, AIM_CB_OFT_GETFILESTATE4)) ) { | |
906 faim_mutex_unlock(&conn->active); | |
907 return userfunc(sess, NULL, conn); | |
908 } | |
909 faim_mutex_unlock(&conn->active); | |
910 aim_conn_close(conn); | |
911 return 0; | |
912 } | |
913 } | |
914 | |
915 if ( (hdrlen = aim_recv(conn->fd, hdrbuf1, 6)) < 6) { | |
916 faimdprintf(sess, 2, "faim: rend: read error (fd: %i) %02x%02x%02x%02x%02x%02x (%i)\n", | |
917 conn->fd, hdrbuf1[0],hdrbuf1[1],hdrbuf1[2],hdrbuf1[3],hdrbuf1[4],hdrbuf1[5],hdrlen); | |
918 faim_mutex_unlock(&conn->active); | |
919 if (hdrlen < 0) | |
920 perror("read"); | |
921 else { /* disconnected */ | |
922 char *screenname = NULL; | |
923 int ret; | |
924 struct aim_msgcookie_t *cook; | |
925 | |
926 switch(conn->subtype) { | |
927 case AIM_CONN_SUBTYPE_OFT_DIRECTIM: { | |
928 struct aim_directim_priv *priv = NULL; | |
929 if (!(priv = (struct aim_directim_priv *)conn->priv) ) | |
930 return -1; | |
931 | |
932 screenname = strdup(priv->sn); | |
933 | |
934 cook = aim_uncachecookie(sess, priv->cookie, AIM_COOKIETYPE_OFTIM); | |
935 aim_cookie_free(sess, cook); | |
936 if ( (userfunc = aim_callhandler(sess, conn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIMDISCONNECT)) ) { | |
937 aim_conn_close(conn); | |
938 ret = userfunc(sess, NULL, conn, screenname); | |
939 free(screenname); | |
940 return ret; | |
941 } | |
942 break; | |
943 } | |
944 case AIM_CONN_SUBTYPE_OFT_GETFILE: { | |
945 struct aim_filetransfer_priv *priv; | |
946 if (!(priv = (struct aim_filetransfer_priv *)conn->priv)) | |
947 return -1; | |
948 screenname = strdup(priv->sn); | |
949 | |
950 cook = aim_uncachecookie(sess, priv->cookie, AIM_COOKIETYPE_OFTGET); | |
951 | |
952 aim_cookie_free(sess, cook); | |
953 | |
954 if ( (userfunc = aim_callhandler(sess, conn, AIM_CB_FAM_OFT, AIM_CB_OFT_GETFILEDISCONNECT)) ) { | |
955 aim_conn_close(conn); | |
956 ret = userfunc(sess, NULL, conn, screenname); | |
957 free(screenname); | |
958 return ret; | |
959 } | |
960 break; | |
961 } | |
962 case AIM_CONN_SUBTYPE_OFT_SENDFILE: { | |
963 struct aim_filetransfer_priv *priv; | |
964 if (!(priv = (struct aim_filetransfer_priv *)conn->priv)) | |
965 return -1; | |
966 | |
967 screenname = strdup(priv->sn); | |
968 | |
969 cook = aim_uncachecookie(sess, priv->cookie, AIM_COOKIETYPE_OFTSEND); | |
970 aim_cookie_free(sess, cook); | |
971 if ( (userfunc = aim_callhandler(sess, conn, AIM_CB_FAM_OFT, AIM_CB_OFT_SENDFILEDISCONNECT)) ) { | |
972 aim_conn_close(conn); | |
973 ret = userfunc(sess, NULL, conn, screenname); | |
974 free(screenname); | |
975 return ret; | |
976 } | |
977 break; | |
978 } | |
979 } | |
980 | |
981 aim_conn_close(conn); | |
982 return -1; | |
983 } | |
984 } | |
985 | |
986 hdrlen = aimutil_get16(hdrbuf1+4); | |
987 hdrlen -= 6; | |
988 | |
989 if (!(hdr = malloc(hdrlen))) { | |
990 faim_mutex_unlock(&conn->active); | |
991 return -1; | |
992 } | |
993 | |
994 if (aim_recv(conn->fd, hdr, hdrlen) < hdrlen) { | |
995 perror("read"); | |
996 faimdprintf(sess, 2,"faim: rend: read2 error on %d (%d)\n", conn->fd, hdrlen); | |
997 free(hdr); | |
998 faim_mutex_unlock(&conn->active); | |
999 aim_conn_close(conn); | |
1000 return -1; | |
1001 } | |
1002 hdrtype = aimutil_get16(hdr); | |
1003 | |
1004 switch (hdrtype) { | |
1005 case 0x0001: { /* directim */ | |
1006 int payloadlength = 0; | |
1007 char *snptr = NULL; | |
1008 struct aim_directim_priv *priv; | |
1009 int i; | |
1010 | |
1011 if (!(priv = (struct aim_directim_priv *)calloc(1, sizeof(struct aim_directim_priv)))) { | |
1012 faim_mutex_unlock(&conn->active); | |
1013 free(hdr); | |
1014 return -1; | |
1015 } | |
1016 | |
1017 payloadlength = aimutil_get32(hdr+22); | |
1018 flags = aimutil_get16(hdr+32); | |
1019 snptr = (char *)hdr+38; | |
1020 strncpy(priv->sn, snptr, MAXSNLEN); | |
1021 | |
1022 faimdprintf(sess, 2, "faim: OFT frame: %04x / %04x / %04x / %s\n", hdrtype, payloadlength, flags, priv->sn); | |
1023 | |
1024 free(hdr); | |
1025 hdr = NULL; | |
1026 | |
1027 if (flags == 0x000e) { | |
1028 faim_mutex_unlock(&conn->active); | |
1029 if ( (userfunc = aim_callhandler(sess, conn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIMTYPING)) ) | |
1030 return userfunc(sess, NULL, conn); | |
1031 } else { | |
1032 | |
1033 if ((flags == 0x0000) && payloadlength) { | |
1034 unsigned char *msg; | |
1035 | |
1036 if (!(msg = calloc(1, payloadlength+1))) { | |
1037 faim_mutex_unlock(&conn->active); | |
1038 return -1; | |
1039 } | |
1040 | |
1041 if (aim_recv(conn->fd, msg, payloadlength) < payloadlength) { | |
1042 perror("read"); | |
1043 faimdprintf(sess, 2,"faim: rend: read3 error\n"); | |
1044 free(msg); | |
1045 faim_mutex_unlock(&conn->active); | |
1046 aim_conn_close(conn); | |
1047 return -1; | |
1048 } | |
1049 | |
1050 faim_mutex_unlock(&conn->active); | |
1051 msg[payloadlength] = 0x00; | |
1052 faimdprintf(sess, 2, "faim: directim: %s/%04x/%04x/%s\n", priv->sn, payloadlength, flags, msg); | |
1053 | |
1054 if ( (userfunc = aim_callhandler(sess, conn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIMINCOMING)) ) | |
1055 i = userfunc(sess, NULL, conn, msg); | |
1056 else { | |
1057 faimdprintf(sess, 0, "directim: %s/%04x/%04x/%s\n", priv->sn, payloadlength, flags, msg); | |
1058 i = 1; | |
1059 } | |
1060 | |
1061 free(msg); | |
1062 | |
1063 return i; | |
1064 } | |
1065 } | |
1066 break; | |
1067 } | |
1068 case 0x1108: { /* getfile listing.txt incoming tx->rx */ | |
1069 struct aim_filetransfer_priv *ft; | |
1070 struct aim_fileheader_t *fh; | |
1071 struct aim_msgcookie_t *cook; | |
1072 struct command_tx_struct *newoft; | |
1073 | |
1074 faimdprintf(sess, 2,"faim: rend: fileget 0x1108\n"); | |
1075 fh = aim_oft_getfh(hdr); | |
1076 | |
1077 free(hdr); | |
1078 hdr = NULL; | |
1079 | |
1080 faim_mutex_unlock(&conn->active); | |
1081 | |
1082 if (!(cook = aim_checkcookie(sess, fh->bcookie, AIM_COOKIETYPE_OFTGET))) { | |
1083 faim_mutex_unlock(&conn->active); | |
1084 free(fh); | |
1085 return -1; | |
1086 } | |
1087 | |
1088 ft = cook->data; | |
1089 | |
1090 /* we're waaaaiiiting.. for listing.txt */ | |
1091 ft->state = 2; | |
1092 | |
1093 memcpy(&(ft->fh), fh, sizeof(struct aim_fileheader_t)); | |
1094 free(fh); | |
1095 | |
1096 if(aim_cachecookie(sess, cook) == -1) { | |
1097 faimdprintf(sess, 1, "error caching cookie\n"); | |
1098 return -1; | |
1099 } | |
1100 | |
1101 if (!(newoft = aim_tx_new(sess, conn, AIM_FRAMETYPE_OFT, 0x1209, 0))) { | |
1102 aim_conn_close(conn); | |
1103 return -1; | |
1104 } | |
1105 | |
1106 memcpy(newoft->hdr.oft.magic, "OFT2", 4); | |
1107 newoft->hdr.oft.hdr2len = 0x100 - 8; | |
1108 | |
1109 if (!(newoft->hdr.oft.hdr2 = (char *)calloc(1,newoft->hdr.oft.hdr2len))) { | |
1110 newoft->lock = 0; | |
1111 aim_tx_destroy(newoft); | |
1112 return -1; | |
1113 } | |
1114 | |
1115 if (!(aim_oft_buildheader((unsigned char *)newoft->hdr.oft.hdr2, &(ft->fh)))) { | |
1116 newoft->lock = 0; | |
1117 aim_tx_destroy(newoft); | |
1118 return -1; | |
1119 } | |
1120 | |
1121 newoft->lock = 0; | |
1122 aim_tx_enqueue(sess, newoft); | |
1123 break; | |
1124 | |
1125 } | |
1126 case 0x1209: { /* get file listing ack rx->tx */ | |
1127 struct aim_filetransfer_priv *ft; | |
1128 struct aim_fileheader_t *fh; | |
1129 struct aim_msgcookie_t *cook; | |
1130 int ret = 0; | |
1131 | |
1132 if(!(fh = aim_oft_getfh(hdr))) { | |
1133 perror("getfh"); | |
1134 free(hdr); | |
1135 return -1; | |
1136 } | |
1137 | |
1138 free(hdr); | |
1139 hdr = NULL; | |
1140 | |
1141 faim_mutex_unlock(&conn->active); | |
1142 | |
1143 if (!(cook = aim_checkcookie(sess, fh->bcookie, AIM_COOKIETYPE_OFTGET))) | |
1144 faimdprintf(sess, 2, "shit, no cookie in 0x1209. (%i/%s)going to crash..\n", | |
1145 AIM_COOKIETYPE_OFTGET, fh->bcookie); | |
1146 | |
1147 ft = cook->data; | |
1148 | |
1149 if (ft->fh.size != fh->size) | |
1150 faimdprintf(sess, 2, "hrm. ft->fh.size (%ld) != fh->size (%ld). um. using ft->fh.size\n", | |
1151 ft->fh.size, fh->size); | |
1152 | |
1153 if ( (userfunc = aim_callhandler(sess, conn, AIM_CB_FAM_OFT, AIM_CB_OFT_GETFILELISTINGREQ))) | |
1154 ret = userfunc(sess, NULL, conn, fh); | |
1155 | |
1156 faimdprintf(sess, 2, "faim: get_command_rendezvous: hit end of 1209\n"); | |
1157 | |
1158 free(fh); | |
1159 | |
1160 return ret; | |
1161 | |
1162 break; | |
1163 } | |
1164 case 0x120b: { /* getfile listing.txt rx confirm */ | |
1165 struct aim_filetransfer_priv *ft; | |
1166 struct aim_msgcookie_t *cook; | |
1167 struct aim_fileheader_t *fh; | |
1168 | |
1169 fh = aim_oft_getfh(hdr); | |
1170 | |
1171 free(hdr); | |
1172 hdr = NULL; | |
1173 | |
1174 faim_mutex_unlock(&conn->active); | |
1175 | |
1176 if (!(cook = aim_checkcookie(sess, fh->bcookie, AIM_COOKIETYPE_OFTGET))) { | |
1177 free(fh); | |
1178 return -1; | |
1179 } | |
1180 | |
1181 free(fh); | |
1182 | |
1183 ft = cook->data; | |
1184 | |
1185 if (aim_cachecookie(sess, cook) == -1) { | |
1186 return -1; | |
1187 } | |
1188 | |
1189 if((userfunc = aim_callhandler(sess, conn, AIM_CB_FAM_OFT, AIM_CB_OFT_GETFILELISTINGRXCONFIRM))) | |
1190 return userfunc(sess, NULL, conn); | |
1191 | |
1192 break; | |
1193 } | |
1194 case 0x120c: { /* getfile file request */ | |
1195 struct aim_filetransfer_priv *ft; | |
1196 struct aim_msgcookie_t *cook; | |
1197 struct aim_fileheader_t *fh; | |
1198 struct command_tx_struct *newoft; | |
1199 int i = 0; | |
1200 | |
1201 fh = aim_oft_getfh(hdr); | |
1202 | |
1203 free(hdr); | |
1204 hdr = NULL; | |
1205 | |
1206 faim_mutex_unlock(&conn->active); | |
1207 | |
1208 if (!(cook = aim_checkcookie(sess, fh->bcookie, AIM_COOKIETYPE_OFTGET))) { | |
1209 faimdprintf(sess, 2, "no cookie in 120c\n"); | |
1210 return -1; | |
1211 } | |
1212 | |
1213 ft = cook->data; | |
1214 memcpy(&(ft->fh), fh, sizeof(struct aim_fileheader_t)); | |
1215 free(fh); | |
1216 | |
1217 aim_cachecookie(sess, cook); | |
1218 | |
1219 faimdprintf(sess, 2, "faim: fileget: %s seems to want %s\n", ft->sn, ft->fh.name); | |
1220 | |
1221 if ( (userfunc = aim_callhandler(sess, conn, AIM_CB_FAM_OFT, AIM_CB_OFT_GETFILEFILEREQ)) ) | |
1222 i = userfunc(sess, NULL, conn, &(ft->fh), cook->cookie); | |
1223 | |
1224 if (i < 0) | |
1225 return i; | |
1226 | |
1227 if (!(newoft = aim_tx_new(sess, conn, AIM_FRAMETYPE_OFT, 0x0101, 0))) { | |
1228 faimdprintf(sess, 2, "faim: send_final_transfer: tx_new OFT failed\n"); | |
1229 return -1; | |
1230 } | |
1231 | |
1232 newoft->lock = 1; | |
1233 memcpy(newoft->hdr.oft.magic, "OFT2", 4); | |
1234 newoft->hdr.oft.hdr2len = 0x100 - 8; | |
1235 | |
1236 if (!(newoft->hdr.oft.hdr2 = calloc(1,newoft->hdr.oft.hdr2len))) { | |
1237 newoft->lock = 0; | |
1238 aim_tx_destroy(newoft); | |
1239 return -1; | |
1240 } | |
1241 | |
1242 /* protocol BS: nrecvd, recvcsum to 0, flags to 0x20. */ | |
1243 ft->fh.nrecvd = 0; | |
1244 ft->fh.recvcsum = 0; | |
1245 ft->fh.flags = 0x20; | |
1246 | |
1247 aim_oft_buildheader((unsigned char *)newoft->hdr.oft.hdr2, &(ft->fh)); | |
1248 | |
1249 newoft->lock = 0; | |
1250 aim_tx_enqueue(sess, newoft); | |
1251 | |
1252 faimdprintf(sess, 2, "faim: OFT: OFT file header enqueued.\n"); | |
1253 | |
1254 return i; | |
1255 | |
1256 break; | |
1257 } | |
1258 case 0x0101: { /* getfile: sending data */ | |
1259 struct aim_fileheader_t *fh; | |
1260 struct aim_filetransfer_priv *ft; | |
1261 struct aim_msgcookie_t *cook; | |
1262 struct command_tx_struct *newoft; | |
1263 | |
1264 fh = aim_oft_getfh(hdr); | |
1265 | |
1266 free(hdr); | |
1267 hdr = NULL; | |
1268 | |
1269 faim_mutex_unlock(&conn->active); | |
1270 | |
1271 if (!(cook = aim_checkcookie(sess, fh->bcookie, AIM_COOKIETYPE_OFTGET))) { | |
1272 free(fh); | |
1273 return -1; | |
1274 } | |
1275 free(fh); | |
1276 | |
1277 ft = cook->data; | |
1278 | |
1279 ft->state = 3; | |
1280 | |
1281 if (aim_cachecookie(sess, cook) == -1) { | |
1282 perror("aim_cachecookie"); | |
1283 return -1; | |
1284 } | |
1285 | |
1286 faimdprintf(sess, 2, "faim: fileget: %s seems to want to send %s\n", ft->sn, ft->fh.name); | |
1287 | |
1288 if (!(newoft = aim_tx_new(sess, conn, AIM_FRAMETYPE_OFT, 0x0202, 0))) { | |
1289 aim_conn_close(conn); | |
1290 faimdprintf(sess, 2, "faim: send_final_transfer: tx_new OFT failed\n"); | |
1291 return -1; | |
1292 } | |
1293 | |
1294 newoft->lock = 1; | |
1295 memcpy(newoft->hdr.oft.magic, "OFT2", 4); | |
1296 | |
1297 newoft->hdr.oft.hdr2len = 0x100 - 8; | |
1298 | |
1299 if (!(newoft->hdr.oft.hdr2 = calloc(1,newoft->hdr.oft.hdr2len))) { | |
1300 newoft->lock = 0; | |
1301 aim_tx_destroy(newoft); | |
1302 return -1; | |
1303 } | |
1304 | |
1305 aim_oft_buildheader((unsigned char *)newoft->hdr.oft.hdr2, &(ft->fh)); | |
1306 | |
1307 newoft->lock = 0; | |
1308 aim_tx_enqueue(sess, newoft); | |
1309 | |
1310 faimdprintf(sess, 2, "faim: OFT: OFT 0x0202 enqueued.\n"); | |
1311 | |
1312 if ( (userfunc = aim_callhandler(sess, conn, AIM_CB_FAM_OFT, AIM_CB_OFT_GETFILEFILEREQ)) == NULL) | |
1313 return 1; | |
1314 | |
1315 break; | |
1316 } | |
1317 case 0x0202: { /* get file: ready to receive data */ | |
1318 struct aim_fileheader_t *fh; | |
1319 struct aim_filetransfer_priv *ft; | |
1320 struct aim_msgcookie_t *cook; | |
1321 int ret = 1; | |
1322 | |
1323 fh = aim_oft_getfh(hdr); | |
1324 | |
1325 free(hdr); | |
1326 hdr = NULL; | |
1327 | |
1328 faim_mutex_unlock(&conn->active); | |
1329 | |
1330 if (!(cook = aim_checkcookie(sess, fh->bcookie, AIM_COOKIETYPE_OFTGET))) { | |
1331 free(fh); | |
1332 return -1; | |
1333 } | |
1334 | |
1335 ft = cook->data; | |
1336 | |
1337 faimdprintf(sess, 2, "faim: get_rend: looks like we're ready to send data.(oft 0x0202)\n"); | |
1338 | |
1339 if ( (userfunc = aim_callhandler(sess, conn, AIM_CB_FAM_OFT, AIM_CB_OFT_GETFILEFILESEND)) ) | |
1340 ret = userfunc(sess, NULL, conn, fh); | |
1341 | |
1342 free(fh); | |
1343 | |
1344 return ret; | |
1345 break; | |
1346 } | |
1347 case 0x0204: { /* get file: finished. close it up */ | |
1348 int i; | |
1349 struct aim_fileheader_t *fh; | |
1350 | |
1351 if(!(fh = aim_oft_getfh(hdr))) | |
1352 return -1; | |
1353 | |
1354 free(hdr); | |
1355 hdr = NULL; | |
1356 | |
1357 faim_mutex_unlock(&conn->active); | |
1358 | |
1359 faimdprintf(sess, 2, "faim: get_rend: looks like we're done with a transfer (oft 0x0204)\n"); | |
1360 | |
1361 if ( (userfunc = aim_callhandler(sess, conn, AIM_CB_FAM_OFT, AIM_CB_OFT_GETFILECOMPLETE)) ) | |
1362 i = userfunc(sess, NULL, conn, fh); | |
1363 else | |
1364 i = 1; | |
1365 | |
1366 if (conn) | |
1367 aim_conn_close(conn); | |
1368 | |
1369 free(fh); | |
1370 | |
1371 return i; | |
1372 break; | |
1373 } | |
1374 default: { | |
1375 free(hdr); | |
1376 hdr = NULL; | |
1377 faimdprintf(sess, 2,"faim: OFT frame: uknown type %04x\n", hdrtype); | |
1378 faim_mutex_unlock(&conn->active); | |
1379 break; | |
1380 } | |
1381 } /* switch */ | |
1382 | |
1383 if (hdr) { | |
1384 faimdprintf(sess, 0, "hdr wasn't freed by a rendezvous switch case (hdrtype: %0x04x)!\n", hdrtype); | |
1385 free(hdr); | |
1386 hdr = NULL; | |
1387 } | |
1388 return 0; | |
1389 } | |
1390 | |
1391 /** | 1429 /** |
1392 * aim_oft_getfh - extracts an &aim_fileheader_t from buffer hdr. | 1430 * aim_oft_getfh - extracts an &aim_fileheader_t from buffer hdr. |
1393 * @hdr: buffer to extract header from | 1431 * @hdr: buffer to extract header from |
1394 * | 1432 * |
1395 * returns pointer to new struct on success; %NULL on error. | 1433 * returns pointer to new struct on success; %NULL on error. |
1456 i += 2; | 1494 i += 2; |
1457 memcpy(fh->name, hdr+i, 64); | 1495 memcpy(fh->name, hdr+i, 64); |
1458 i += 64; | 1496 i += 64; |
1459 return fh; | 1497 return fh; |
1460 } | 1498 } |
1499 #endif | |
1461 | 1500 |
1462 /** | 1501 /** |
1463 * aim_oft_checksum - calculate oft checksum of buffer | 1502 * aim_oft_checksum - calculate oft checksum of buffer |
1464 * @buffer: buffer of data to checksum | 1503 * @buffer: buffer of data to checksum |
1465 * @bufsize: size of buffer | 1504 * @bufsize: size of buffer |
1475 * | 1514 * |
1476 * | 1515 * |
1477 * Also, it's been said that this is incorrect as currently | 1516 * Also, it's been said that this is incorrect as currently |
1478 * written. You were warned. | 1517 * written. You were warned. |
1479 */ | 1518 */ |
1480 faim_export int aim_oft_checksum(struct aim_session_t *sess, char *buffer, int bufsize, int *checksum) | 1519 faim_export fu32_t aim_oft_checksum(aim_session_t *sess, const char *buffer, int bufsize, fu32_t *checksum) |
1481 { | 1520 { |
1482 short check0, check1; | 1521 return 0xdeadbeef; |
1522 #if 0 | |
1523 fu16_t check0, check1; | |
1483 int i; | 1524 int i; |
1525 | |
1484 check0 = ((*checksum & 0xFF000000) >> 16); | 1526 check0 = ((*checksum & 0xFF000000) >> 16); |
1485 check1 = ((*checksum & 0x00ff0000) >> 16); | 1527 check1 = ((*checksum & 0x00ff0000) >> 16); |
1486 for(i = 0; i < bufsize; i++) { | 1528 for(i = 0; i < bufsize; i++) { |
1487 if (i % 2) { /* use check1 -- second byte */ | 1529 if (i % 2) { /* use check1 -- second byte */ |
1488 if ( (short)buffer[i] > check1 ) { /* wrapping */ | 1530 if ( (short)buffer[i] > check1 ) { /* wrapping */ |
1522 check0 &= 0xff; | 1564 check0 &= 0xff; |
1523 check1 &= 0xff; | 1565 check1 &= 0xff; |
1524 | 1566 |
1525 *checksum = ((check0 * 0x1000000) + (check1 * 0x10000)); | 1567 *checksum = ((check0 * 0x1000000) + (check1 * 0x10000)); |
1526 return *checksum; | 1568 return *checksum; |
1569 #endif | |
1527 } | 1570 } |
1528 | 1571 |
1572 #if 0 | |
1529 /** | 1573 /** |
1530 * aim_oft_buildheader - fills a buffer with network-order fh data | 1574 * aim_oft_buildheader - fills a buffer with network-order fh data |
1531 * @dest: buffer to fill -- pre-alloced | 1575 * @dest: buffer to fill -- pre-alloced |
1532 * @fh: fh to get data from | 1576 * @fh: fh to get data from |
1533 * | 1577 * |
1534 * returns length written; -1 on error. | 1578 * returns length written; -1 on error. |
1535 * DOES NOT DO BOUNDS CHECKING! | 1579 * DOES NOT DO BOUNDS CHECKING! |
1536 * | 1580 * |
1537 */ | 1581 */ |
1538 faim_internal int aim_oft_buildheader(unsigned char *dest,struct aim_fileheader_t *fh) | 1582 static int oft_buildheader(unsigned char *dest, struct aim_fileheader_t *fh) |
1539 { | 1583 { |
1540 int i, curbyte; | 1584 int i, curbyte; |
1541 if (!dest || !fh) | 1585 if (!dest || !fh) |
1542 return -1; | 1586 return -1; |
1543 curbyte = 0; | 1587 curbyte = 0; |
1575 | 1619 |
1576 /* XXX: Filenames longer than 64B */ | 1620 /* XXX: Filenames longer than 64B */ |
1577 curbyte += 64; | 1621 curbyte += 64; |
1578 return curbyte; | 1622 return curbyte; |
1579 } | 1623 } |
1580 | 1624 #endif |
1581 | |
1582 /** | |
1583 * aim_tx_destroy - free's tx_command_t's | |
1584 * @command: the command to free | |
1585 * | |
1586 * if command is locked, doesn't free. | |
1587 * returns -1 on error (locked struct); 0 on success. | |
1588 * | |
1589 */ | |
1590 faim_internal int aim_tx_destroy(struct command_tx_struct *command){ | |
1591 if (command->lock) | |
1592 return -1; | |
1593 if (command->data) | |
1594 free(command->data); | |
1595 if (command->hdrtype == AIM_FRAMETYPE_OFT && command->hdr.oft.hdr2) | |
1596 free(command->hdr.oft.hdr2); | |
1597 free(command); | |
1598 return 0; | |
1599 } | |
1600 | 1625 |
1601 /** | 1626 /** |
1602 * aim_getfile_intitiate - Request an OFT getfile session | 1627 * aim_getfile_intitiate - Request an OFT getfile session |
1603 * @sess: your session, | 1628 * @sess: your session, |
1604 * @conn: the BOS conn, | 1629 * @conn: the BOS conn, |
1605 * @destsn is the SN to connect to. | 1630 * @destsn is the SN to connect to. |
1606 * | 1631 * |
1607 * returns a new &aim_conn_t on success, %NULL on error | 1632 * returns a new &aim_conn_t on success, %NULL on error |
1608 */ | 1633 */ |
1609 faim_export struct aim_conn_t *aim_getfile_initiate(struct aim_session_t *sess, struct aim_conn_t *conn, char *destsn) | 1634 faim_export aim_conn_t *aim_getfile_initiate(aim_session_t *sess, aim_conn_t *conn, const char *destsn) |
1610 { | 1635 { |
1636 return NULL; | |
1637 #if 0 | |
1611 struct command_tx_struct *newpacket; | 1638 struct command_tx_struct *newpacket; |
1612 struct aim_conn_t *newconn; | 1639 struct aim_conn_t *newconn; |
1613 struct aim_filetransfer_priv *priv; | 1640 struct aim_filetransfer_priv *priv; |
1614 struct aim_msgcookie_t *cookie; | 1641 struct aim_msgcookie_t *cookie; |
1615 int curbyte, i, listenfd; | 1642 int curbyte, i, listenfd; |
1743 newconn->subtype = AIM_CONN_SUBTYPE_OFT_GETFILE; | 1770 newconn->subtype = AIM_CONN_SUBTYPE_OFT_GETFILE; |
1744 newconn->priv = priv; | 1771 newconn->priv = priv; |
1745 faimdprintf(sess, 2,"faim: listening (fd = %d, unconnected)\n", newconn->fd); | 1772 faimdprintf(sess, 2,"faim: listening (fd = %d, unconnected)\n", newconn->fd); |
1746 | 1773 |
1747 return newconn; | 1774 return newconn; |
1775 #endif | |
1748 } | 1776 } |
1749 | 1777 |
1750 /** | 1778 /** |
1751 * aim_oft_getfile_request - request a particular file over an established getfile connection | 1779 * aim_oft_getfile_request - request a particular file over an established getfile connection |
1752 * @sess: your session | 1780 * @sess: your session |
1755 * @size: size of the file | 1783 * @size: size of the file |
1756 * | 1784 * |
1757 * | 1785 * |
1758 * returns -1 on error, 0 on successful enqueuing | 1786 * returns -1 on error, 0 on successful enqueuing |
1759 */ | 1787 */ |
1760 faim_export int aim_oft_getfile_request(struct aim_session_t *sess, struct aim_conn_t *conn, const unsigned char *name, const int size) | 1788 faim_export int aim_oft_getfile_request(aim_session_t *sess, aim_conn_t *conn, const char *name, int size) |
1761 { | 1789 { |
1790 return -EINVAL; | |
1791 #if 0 | |
1762 struct command_tx_struct *newoft; | 1792 struct command_tx_struct *newoft; |
1763 struct aim_filetransfer_priv *ft; | 1793 struct aim_filetransfer_priv *ft; |
1764 if (!sess || !conn || !conn->priv || !name) | 1794 if (!sess || !conn || !conn->priv || !name) |
1765 return -1; | 1795 return -1; |
1766 | 1796 |
1785 memcpy(ft->fh.name, name, strlen(name)); | 1815 memcpy(ft->fh.name, name, strlen(name)); |
1786 memset(ft->fh.name+strlen(name), 0, 1); | 1816 memset(ft->fh.name+strlen(name), 0, 1); |
1787 | 1817 |
1788 if (!(newoft->hdr.oft.hdr2 = (unsigned char *)calloc(1,newoft->hdr.oft.hdr2len))) { | 1818 if (!(newoft->hdr.oft.hdr2 = (unsigned char *)calloc(1,newoft->hdr.oft.hdr2len))) { |
1789 newoft->lock = 0; | 1819 newoft->lock = 0; |
1790 aim_tx_destroy(newoft); | 1820 aim_frame_destroy(newoft); |
1791 return -1; | 1821 return -1; |
1792 } | 1822 } |
1793 | 1823 |
1794 if (!(aim_oft_buildheader(newoft->hdr.oft.hdr2, &(ft->fh)))) { | 1824 if (!(aim_oft_buildheader(newoft->hdr.oft.hdr2, &(ft->fh)))) { |
1795 newoft->lock = 0; | 1825 newoft->lock = 0; |
1796 aim_tx_destroy(newoft); | 1826 aim_frame_destroy(newoft); |
1797 return -1; | 1827 return -1; |
1798 } | 1828 } |
1799 | 1829 |
1800 newoft->lock = 0; | 1830 newoft->lock = 0; |
1801 | 1831 |
1802 aim_tx_enqueue(sess, newoft); | 1832 aim_tx_enqueue(sess, newoft); |
1803 return 0; | 1833 return 0; |
1834 #endif | |
1804 } | 1835 } |
1805 | 1836 |
1806 /** | 1837 /** |
1807 * aim_oft_getfile_ack - acknowledge a getfile download as complete | 1838 * aim_oft_getfile_ack - acknowledge a getfile download as complete |
1808 * @sess: your session | 1839 * @sess: your session |
1810 * | 1841 * |
1811 * Call this function after you have read all the data in a particular | 1842 * Call this function after you have read all the data in a particular |
1812 * filetransfer. Returns -1 on error, 0 on apparent success | 1843 * filetransfer. Returns -1 on error, 0 on apparent success |
1813 * | 1844 * |
1814 */ | 1845 */ |
1815 faim_export int aim_oft_getfile_ack(struct aim_session_t *sess, struct aim_conn_t *conn) | 1846 faim_export int aim_oft_getfile_ack(aim_session_t *sess, aim_conn_t *conn) |
1816 { | 1847 { |
1848 return -EINVAL; | |
1849 #if 0 | |
1817 struct command_tx_struct *newoft; | 1850 struct command_tx_struct *newoft; |
1818 struct aim_filetransfer_priv *ft; | 1851 struct aim_filetransfer_priv *ft; |
1819 | 1852 |
1820 if (!sess || !conn || !conn->priv) | 1853 if (!sess || !conn || !conn->priv) |
1821 return -1; | 1854 return -1; |
1830 memcpy(newoft->hdr.oft.magic, "OFT2", 4); | 1863 memcpy(newoft->hdr.oft.magic, "OFT2", 4); |
1831 newoft->hdr.oft.hdr2len = 0x100-8; | 1864 newoft->hdr.oft.hdr2len = 0x100-8; |
1832 | 1865 |
1833 if (!(newoft->hdr.oft.hdr2 = (char *)calloc(1,newoft->hdr.oft.hdr2len))) { | 1866 if (!(newoft->hdr.oft.hdr2 = (char *)calloc(1,newoft->hdr.oft.hdr2len))) { |
1834 newoft->lock = 0; | 1867 newoft->lock = 0; |
1835 aim_tx_destroy(newoft); | 1868 aim_frame_destroy(newoft); |
1836 return -1; | 1869 return -1; |
1837 } | 1870 } |
1838 | 1871 |
1839 ft = (struct aim_filetransfer_priv *)conn->priv; | 1872 ft = (struct aim_filetransfer_priv *)conn->priv; |
1840 | 1873 |
1841 if (!(aim_oft_buildheader((unsigned char *)newoft->hdr.oft.hdr2, &(ft->fh)))) { | 1874 if (!(aim_oft_buildheader((unsigned char *)newoft->hdr.oft.hdr2, &(ft->fh)))) { |
1842 newoft->lock = 0; | 1875 newoft->lock = 0; |
1843 aim_tx_destroy(newoft); | 1876 aim_frame_destroy(newoft); |
1844 return -1; | 1877 return -1; |
1845 } | 1878 } |
1846 | 1879 |
1847 newoft->lock = 0; | 1880 newoft->lock = 0; |
1848 aim_tx_enqueue(sess, newoft); | 1881 aim_tx_enqueue(sess, newoft); |
1849 return 0; | 1882 return 0; |
1883 #endif | |
1850 } | 1884 } |
1851 | 1885 |
1852 /** | 1886 /** |
1853 * aim_oft_getfile_end - end a getfile. | 1887 * aim_oft_getfile_end - end a getfile. |
1854 * @sess: your session | 1888 * @sess: your session |
1855 * @conn: the getfile connection | 1889 * @conn: the getfile connection |
1856 * | 1890 * |
1857 * call this before you close the getfile connection if you're on the | 1891 * call this before you close the getfile connection if you're on the |
1858 * receiving/requesting end. | 1892 * receiving/requesting end. |
1859 */ | 1893 */ |
1860 faim_export int aim_oft_getfile_end(struct aim_session_t *sess, struct aim_conn_t *conn) | 1894 faim_export int aim_oft_getfile_end(aim_session_t *sess, aim_conn_t *conn) |
1861 { | 1895 { |
1896 return -EINVAL; | |
1897 #if 0 | |
1862 struct command_tx_struct *newoft; | 1898 struct command_tx_struct *newoft; |
1863 struct aim_filetransfer_priv *ft; | 1899 struct aim_filetransfer_priv *ft; |
1864 | 1900 |
1865 if (!sess || !conn || !conn->priv) | 1901 if (!sess || !conn || !conn->priv) |
1866 return -1; | 1902 return -1; |
1875 memcpy(newoft->hdr.oft.magic, "OFT2", 4); | 1911 memcpy(newoft->hdr.oft.magic, "OFT2", 4); |
1876 newoft->hdr.oft.hdr2len = 0x100 - 8; | 1912 newoft->hdr.oft.hdr2len = 0x100 - 8; |
1877 | 1913 |
1878 if (!(newoft->hdr.oft.hdr2 = (char *)calloc(1,newoft->hdr.oft.hdr2len))) { | 1914 if (!(newoft->hdr.oft.hdr2 = (char *)calloc(1,newoft->hdr.oft.hdr2len))) { |
1879 newoft->lock = 0; | 1915 newoft->lock = 0; |
1880 aim_tx_destroy(newoft); | 1916 aim_frame_destroy(newoft); |
1881 return -1; | 1917 return -1; |
1882 } | 1918 } |
1883 | 1919 |
1884 ft = (struct aim_filetransfer_priv *)conn->priv; | 1920 ft = (struct aim_filetransfer_priv *)conn->priv; |
1885 ft->state = 4; /* no longer wanting data */ | 1921 ft->state = 4; /* no longer wanting data */ |
1887 ft->fh.recvcsum = ft->fh.checksum; | 1923 ft->fh.recvcsum = ft->fh.checksum; |
1888 ft->fh.flags = 0x21; | 1924 ft->fh.flags = 0x21; |
1889 | 1925 |
1890 if (!(aim_oft_buildheader((unsigned char *)newoft->hdr.oft.hdr2, &(ft->fh)))) { | 1926 if (!(aim_oft_buildheader((unsigned char *)newoft->hdr.oft.hdr2, &(ft->fh)))) { |
1891 newoft->lock = 0; | 1927 newoft->lock = 0; |
1892 aim_tx_destroy(newoft); | 1928 aim_frame_destroy(newoft); |
1893 return -1; | 1929 return -1; |
1894 } | 1930 } |
1895 | 1931 |
1896 newoft->lock = 0; | 1932 newoft->lock = 0; |
1897 aim_tx_enqueue(sess, newoft); | 1933 aim_tx_enqueue(sess, newoft); |
1898 | 1934 |
1899 return 0; | 1935 return 0; |
1900 } | 1936 #endif /* 0 */ |
1937 } | |
1938 |