| |
1 /* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
| |
2 /* |
| |
3 $Id: udp.c 1162 2000-11-28 02:22:42Z warmenhoven $ |
| |
4 $Log$ |
| |
5 Revision 1.1 2000/11/28 02:22:42 warmenhoven |
| |
6 icq. whoop de doo |
| |
7 |
| |
8 Revision 1.23 2000/07/09 22:19:35 bills |
| |
9 added new *Close functions, use *Close functions instead of *Delete |
| |
10 where correct, and misc cleanup |
| |
11 |
| |
12 Revision 1.22 2000/07/09 18:25:44 denis |
| |
13 icq_UpdateNewUserInfo() now returns seq1 instead of seq2 since it |
| |
14 isn't META function. |
| |
15 |
| |
16 Revision 1.21 2000/06/25 16:43:19 denis |
| |
17 icq_SendMetaInfoReq() was added. |
| |
18 All icq_*Meta*() functions now returns sequence number 2 because their |
| |
19 replies from the server are synced with it. |
| |
20 |
| |
21 Revision 1.20 2000/06/15 01:50:39 bills |
| |
22 removed *Seq functions |
| |
23 |
| |
24 Revision 1.19 2000/05/10 19:06:59 denis |
| |
25 UDP outgoing packet queue was implemented. |
| |
26 |
| |
27 Revision 1.18 2000/05/03 18:34:43 denis |
| |
28 icq_UpdateNewUserInfo() was added. |
| |
29 All icq_UpdateMetaInfo*() now return their sequence number. |
| |
30 |
| |
31 Revision 1.17 2000/04/10 16:36:04 denis |
| |
32 Some more Win32 compatibility from Guillaume Rosanis <grs@mail.com> |
| |
33 |
| |
34 Revision 1.16 2000/04/06 19:03:07 denis |
| |
35 return sequence number |
| |
36 |
| |
37 Revision 1.15 2000/04/06 16:36:18 denis |
| |
38 So called "Online List problem" bug with Long Contact List was fixed. |
| |
39 icq_*Send*Seq() functions with specified sequence number were added. |
| |
40 |
| |
41 Revision 1.14 2000/04/05 14:37:02 denis |
| |
42 Applied patch from "Guillaume R." <grs@mail.com> for basic Win32 |
| |
43 compatibility. |
| |
44 |
| |
45 Revision 1.13 1999/12/27 11:12:35 denis |
| |
46 icq_UpdateMetaInfoSecurity() added for setting "My authorization is |
| |
47 required", "Web Aware" and "IP Publishing". |
| |
48 |
| |
49 Revision 1.12 1999/10/14 11:43:28 denis |
| |
50 icq_UpdateMetaInfo* functions added. |
| |
51 |
| |
52 Revision 1.11 1999/10/07 18:36:27 denis |
| |
53 proxy.h file removed. |
| |
54 |
| |
55 Revision 1.10 1999/10/04 13:36:17 denis |
| |
56 Cleanups. |
| |
57 |
| |
58 Revision 1.9 1999/09/29 20:15:30 bills |
| |
59 tcp port wasn't being sent properly in login packet |
| |
60 |
| |
61 Revision 1.8 1999/09/29 17:13:45 denis |
| |
62 Webaware functions enabled without success even with UDP v5 - need more |
| |
63 investigations. |
| |
64 |
| |
65 Revision 1.7 1999/07/18 20:22:16 bills |
| |
66 changed to use new byte-order functions & contact list functions |
| |
67 |
| |
68 Revision 1.6 1999/07/16 15:46:00 denis |
| |
69 Cleaned up. |
| |
70 |
| |
71 Revision 1.5 1999/07/16 12:40:53 denis |
| |
72 ICQ UDP v5 implemented. |
| |
73 Encription for ICQ UDP v5 implemented. |
| |
74 icq_Packet* unified interface for UDP packets implemented. |
| |
75 Multipacket support of ICQ UDP v5 support added. |
| |
76 |
| |
77 Revision 1.4 1999/07/12 15:13:43 cproch |
| |
78 - added definition of ICQLINK to hold session-specific global variabled |
| |
79 applications which have more than one connection are now possible |
| |
80 - changed nearly every function defintion to support ICQLINK parameter |
| |
81 |
| |
82 Revision 1.3 1999/04/29 09:40:52 denis |
| |
83 Unsuccessful attempt to implement web presence (webaware) feature |
| |
84 |
| |
85 Revision 1.2 1999/04/14 15:04:13 denis |
| |
86 Cleanups for "strict" compiling (-ansi -pedantic) |
| |
87 Switched from icq_Log callback to icq_Fmt function. |
| |
88 |
| |
89 Revision 1.1 1999/03/24 11:37:38 denis |
| |
90 Underscored files with TCP stuff renamed. |
| |
91 TCP stuff cleaned up |
| |
92 Function names changed to corresponding names. |
| |
93 icqlib.c splitted to many small files by subject. |
| |
94 C++ comments changed to ANSI C comments. |
| |
95 |
| |
96 */ |
| |
97 |
| |
98 #ifndef _WIN32 |
| |
99 #include <unistd.h> |
| |
100 #endif |
| |
101 |
| |
102 #ifdef _WIN32 |
| |
103 #include <winsock.h> |
| |
104 #endif |
| |
105 |
| |
106 #include <stdlib.h> |
| |
107 |
| |
108 #include "icqtypes.h" |
| |
109 #include "icqlib.h" |
| |
110 #include "udp.h" |
| |
111 #include "queue.h" |
| |
112 |
| |
113 #include "stdpackets.h" |
| |
114 #include "icqbyteorder.h" |
| |
115 |
| |
116 static const BYTE icq_UDPTable[] = { |
| |
117 0x59, 0x60, 0x37, 0x6B, 0x65, 0x62, 0x46, 0x48, 0x53, 0x61, 0x4C, 0x59, 0x60, 0x57, 0x5B, 0x3D, |
| |
118 0x5E, 0x34, 0x6D, 0x36, 0x50, 0x3F, 0x6F, 0x67, 0x53, 0x61, 0x4C, 0x59, 0x40, 0x47, 0x63, 0x39, |
| |
119 0x50, 0x5F, 0x5F, 0x3F, 0x6F, 0x47, 0x43, 0x69, 0x48, 0x33, 0x31, 0x64, 0x35, 0x5A, 0x4A, 0x42, |
| |
120 0x56, 0x40, 0x67, 0x53, 0x41, 0x07, 0x6C, 0x49, 0x58, 0x3B, 0x4D, 0x46, 0x68, 0x43, 0x69, 0x48, |
| |
121 0x33, 0x31, 0x44, 0x65, 0x62, 0x46, 0x48, 0x53, 0x41, 0x07, 0x6C, 0x69, 0x48, 0x33, 0x51, 0x54, |
| |
122 0x5D, 0x4E, 0x6C, 0x49, 0x38, 0x4B, 0x55, 0x4A, 0x62, 0x46, 0x48, 0x33, 0x51, 0x34, 0x6D, 0x36, |
| |
123 0x50, 0x5F, 0x5F, 0x5F, 0x3F, 0x6F, 0x47, 0x63, 0x59, 0x40, 0x67, 0x33, 0x31, 0x64, 0x35, 0x5A, |
| |
124 0x6A, 0x52, 0x6E, 0x3C, 0x51, 0x34, 0x6D, 0x36, 0x50, 0x5F, 0x5F, 0x3F, 0x4F, 0x37, 0x4B, 0x35, |
| |
125 0x5A, 0x4A, 0x62, 0x66, 0x58, 0x3B, 0x4D, 0x66, 0x58, 0x5B, 0x5D, 0x4E, 0x6C, 0x49, 0x58, 0x3B, |
| |
126 0x4D, 0x66, 0x58, 0x3B, 0x4D, 0x46, 0x48, 0x53, 0x61, 0x4C, 0x59, 0x40, 0x67, 0x33, 0x31, 0x64, |
| |
127 0x55, 0x6A, 0x32, 0x3E, 0x44, 0x45, 0x52, 0x6E, 0x3C, 0x31, 0x64, 0x55, 0x6A, 0x52, 0x4E, 0x6C, |
| |
128 0x69, 0x48, 0x53, 0x61, 0x4C, 0x39, 0x30, 0x6F, 0x47, 0x63, 0x59, 0x60, 0x57, 0x5B, 0x3D, 0x3E, |
| |
129 0x64, 0x35, 0x3A, 0x3A, 0x5A, 0x6A, 0x52, 0x4E, 0x6C, 0x69, 0x48, 0x53, 0x61, 0x6C, 0x49, 0x58, |
| |
130 0x3B, 0x4D, 0x46, 0x68, 0x63, 0x39, 0x50, 0x5F, 0x5F, 0x3F, 0x6F, 0x67, 0x53, 0x41, 0x25, 0x41, |
| |
131 0x3C, 0x51, 0x54, 0x3D, 0x5E, 0x54, 0x5D, 0x4E, 0x4C, 0x39, 0x50, 0x5F, 0x5F, 0x5F, 0x3F, 0x6F, |
| |
132 0x47, 0x43, 0x69, 0x48, 0x33, 0x51, 0x54, 0x5D, 0x6E, 0x3C, 0x31, 0x64, 0x35, 0x5A, 0x00, 0x00, |
| |
133 }; |
| |
134 |
| |
135 void icq_UDPCheckCode(icq_Packet *p) |
| |
136 { |
| |
137 DWORD num1, num2; |
| |
138 DWORD r1,r2; |
| |
139 |
| |
140 num1 = p->data[8]; |
| |
141 num1 <<= 8; |
| |
142 num1 += p->data[4]; |
| |
143 num1 <<= 8; |
| |
144 num1 += p->data[2]; |
| |
145 num1 <<= 8; |
| |
146 num1 += p->data[6]; |
| |
147 |
| |
148 r1 = 0x18 + (rand() % (p->length - 0x18)); |
| |
149 r2 = rand() & 0xff; |
| |
150 |
| |
151 num2 = r1; |
| |
152 num2 <<= 8; |
| |
153 num2 += p->data[r1]; |
| |
154 num2 <<= 8; |
| |
155 num2 += r2; |
| |
156 num2 <<= 8; |
| |
157 num2 += icq_UDPTable[r2]; |
| |
158 num2 ^= 0xFF00FF; |
| |
159 |
| |
160 icq_PacketGoto(p, 0x14); |
| |
161 icq_PacketAppend32(p, num1 ^ num2); |
| |
162 } |
| |
163 |
| |
164 DWORD icq_UDPScramble(DWORD cc) |
| |
165 { |
| |
166 DWORD a[5]; |
| |
167 |
| |
168 a[0] = cc & 0x0000001F; |
| |
169 a[1] = cc & 0x03E003E0; |
| |
170 a[2] = cc & 0xF8000400; |
| |
171 a[3] = cc & 0x0000F800; |
| |
172 a[4] = cc & 0x041F0000; |
| |
173 |
| |
174 a[0] <<= 0x0C; |
| |
175 a[1] <<= 0x01; |
| |
176 a[2] >>= 0x0A; |
| |
177 a[3] <<= 0x10; |
| |
178 a[4] >>= 0x0F; |
| |
179 |
| |
180 return a[0] + a[1] + a[2] + a[3] + a[4]; |
| |
181 } |
| |
182 |
| |
183 void icq_UDPEncode(icq_Packet *p) |
| |
184 { |
| |
185 DWORD checkcode; |
| |
186 DWORD code1, code2, code3; |
| |
187 DWORD pos; |
| |
188 DWORD data; |
| |
189 |
| |
190 icq_UDPCheckCode(p); |
| |
191 icq_PacketGoto(p, 20); |
| |
192 checkcode = icq_PacketRead32(p); |
| |
193 code1 = p->length * 0x68656c6cL; |
| |
194 code2 = code1 + checkcode; |
| |
195 pos = 0x0A; |
| |
196 |
| |
197 for(; pos < p->length; pos+=4) |
| |
198 { |
| |
199 code3 = code2 + icq_UDPTable[pos & 0xFF]; |
| |
200 data = icqtohl(*(DWORD *)((p->data)+pos)); |
| |
201 data ^= code3; |
| |
202 *(DWORD*)((p->data)+pos)=htoicql(data); |
| |
203 } |
| |
204 checkcode = icq_UDPScramble(checkcode); |
| |
205 *(DWORD *)((p->data)+0x14)=htoicql(checkcode); |
| |
206 } |
| |
207 |
| |
208 /********************************************************* |
| |
209 icq_UDPSockWrite and icq_UDPSockRead are for _UDP_ packets |
| |
210 proxy support for TCP sockets is different! |
| |
211 *********************************************************/ |
| |
212 int icq_UDPSockWriteDirect(ICQLINK *link, icq_Packet *p) |
| |
213 { |
| |
214 char tmpbuf[ICQ_PACKET_DATA_SIZE]; |
| |
215 |
| |
216 if(link->icq_UDPSok <= 3) |
| |
217 { |
| |
218 icq_FmtLog(link, ICQ_LOG_ERROR, "Bad socket!\n"); |
| |
219 return -1; |
| |
220 } |
| |
221 |
| |
222 icq_UDPEncode(p); |
| |
223 if(!link->icq_UseProxy) |
| |
224 { |
| |
225 #ifdef _WIN32 |
| |
226 return send(link->icq_UDPSok, p->data, p->length, 0); |
| |
227 #else |
| |
228 return write(link->icq_UDPSok, p->data, p->length); |
| |
229 #endif |
| |
230 } |
| |
231 else |
| |
232 { |
| |
233 tmpbuf[0] = 0; /* reserved */ |
| |
234 tmpbuf[1] = 0; /* reserved */ |
| |
235 tmpbuf[2] = 0; /* standalone packet */ |
| |
236 tmpbuf[3] = 1; /* address type IP v4 */ |
| |
237 *(unsigned long*)&tmpbuf[4] = htonl(link->icq_ProxyDestIP); |
| |
238 *(unsigned short*)&tmpbuf[8] = htons(link->icq_ProxyDestPort); |
| |
239 memcpy(&tmpbuf[10], p->data, p->length); |
| |
240 #ifdef _WIN32 |
| |
241 return send(link->icq_UDPSok, tmpbuf, p->length+10, 0)-10; |
| |
242 #else |
| |
243 return write(link->icq_UDPSok, tmpbuf, p->length+10)-10; |
| |
244 #endif |
| |
245 } |
| |
246 } |
| |
247 |
| |
248 int icq_UDPSockWrite(ICQLINK *link, icq_Packet *p) |
| |
249 { |
| |
250 icq_Packet *qp; |
| |
251 WORD cmd = icq_PacketReadUDPOutCmd(p); |
| |
252 if(cmd != UDP_CMD_ACK && cmd != UDP_CMD_SEND_TEXT_CODE) |
| |
253 { |
| |
254 qp = (icq_Packet*)malloc(sizeof(icq_Packet)); |
| |
255 memcpy(qp, p, sizeof(icq_Packet)); |
| |
256 icq_UDPQueuePut(link, qp, 1); |
| |
257 if(link->icq_SetTimeout) |
| |
258 link->icq_SetTimeout(link, icq_UDPQueueInterval(link)); |
| |
259 } |
| |
260 return icq_UDPSockWriteDirect(link, p); |
| |
261 } |
| |
262 |
| |
263 int icq_UDPSockRead(ICQLINK *link, icq_Packet *p) |
| |
264 { |
| |
265 int res; |
| |
266 char tmpbuf[ICQ_PACKET_DATA_SIZE]; |
| |
267 |
| |
268 if(!link->icq_UseProxy) |
| |
269 { |
| |
270 #ifdef _WIN32 |
| |
271 res = recv(link->icq_UDPSok, p->data, ICQ_PACKET_DATA_SIZE, 0); |
| |
272 #else |
| |
273 res = read(link->icq_UDPSok, p->data, ICQ_PACKET_DATA_SIZE); |
| |
274 #endif |
| |
275 p->length = res; |
| |
276 return res; |
| |
277 } |
| |
278 else |
| |
279 { |
| |
280 #ifdef _WIN32 |
| |
281 res = recv(link->icq_UDPSok, tmpbuf, ICQ_PACKET_DATA_SIZE, 0); |
| |
282 #else |
| |
283 res = read(link->icq_UDPSok, tmpbuf, ICQ_PACKET_DATA_SIZE); |
| |
284 #endif |
| |
285 if(res<0) |
| |
286 return res; |
| |
287 memcpy(p->data, &tmpbuf[10], res-10); |
| |
288 p->length = res-10; |
| |
289 return res-10; |
| |
290 } |
| |
291 } |
| |
292 |
| |
293 void icq_HandleTimeout(ICQLINK *link) |
| |
294 { |
| |
295 icq_UDPQueueItem *ptr = 0; |
| |
296 icq_Packet *sp = 0, *pack = 0; |
| |
297 int attempt; |
| |
298 while(icq_UDPQueueInterval(link) == 0) |
| |
299 { |
| |
300 ptr = (icq_UDPQueueItem*)list_first(link->icq_UDPQueue); |
| |
301 attempt = ptr->attempts + 1; |
| |
302 if(attempt > 6) |
| |
303 { |
| |
304 icq_Disconnect(link); |
| |
305 if(link->icq_Disconnected) |
| |
306 link->icq_Disconnected(link); |
| |
307 return; |
| |
308 } |
| |
309 pack = icq_UDPQueueGet(link); |
| |
310 sp = (icq_Packet*)malloc(sizeof(icq_Packet)); |
| |
311 memcpy(sp, pack, sizeof(icq_Packet)); |
| |
312 icq_UDPQueuePut(link, pack, attempt); |
| |
313 if(link->icq_SetTimeout) |
| |
314 link->icq_SetTimeout(link, icq_UDPQueueInterval(link)); |
| |
315 icq_UDPSockWriteDirect(link, sp); |
| |
316 icq_PacketDelete(sp); |
| |
317 } |
| |
318 } |
| |
319 |
| |
320 /**************************************** |
| |
321 This must be called every 2 min. |
| |
322 so the server knows we're still alive. |
| |
323 JAVA client sends two different commands |
| |
324 so we do also :) |
| |
325 *****************************************/ |
| |
326 WORD icq_KeepAlive(ICQLINK *link) /* V5 */ |
| |
327 { |
| |
328 icq_Packet *p = icq_UDPCreateStdSeqPacket(link, UDP_CMD_KEEP_ALIVE, link->icq_UDPSeqNum1++); |
| |
329 icq_PacketAppend32(p, rand()); |
| |
330 icq_UDPSockWrite(link, p); |
| |
331 icq_PacketDelete(p); |
| |
332 |
| |
333 /* icq_Packet *p = icq_UDPCreateStdPacket(UDP_CMD_KEEP_ALIVE); |
| |
334 icq_UDPSockWrite(icq_UDPSok, p); |
| |
335 icq_PacketDelete(p);*/ |
| |
336 /* p = icq_UDPCreateStdPacket(UDP_CMD_KEEP_ALIVE2); |
| |
337 icq_UDPSockWrite(icq_Sok, p); |
| |
338 icq_PacketDelete(p);*/ |
| |
339 |
| |
340 icq_FmtLog(link, ICQ_LOG_MESSAGE, "Send Keep Alive packet to the server\n"); |
| |
341 |
| |
342 return link->icq_UDPSeqNum1-1; |
| |
343 } |
| |
344 |
| |
345 /********************************** |
| |
346 This must be called to remove |
| |
347 messages from the server |
| |
348 ***********************************/ |
| |
349 void icq_SendGotMessages(ICQLINK *link) /* V5 */ |
| |
350 { |
| |
351 icq_Packet *p = icq_UDPCreateStdPacket(link, UDP_CMD_ACK_MESSAGES); |
| |
352 icq_PacketAppend32(p, rand()); |
| |
353 icq_UDPSockWrite(link, p); |
| |
354 icq_PacketDelete(p); |
| |
355 } |
| |
356 |
| |
357 /************************************* |
| |
358 this sends over the contact list |
| |
359 *************************************/ |
| |
360 void icq_SendContactList(ICQLINK *link) /* V5 */ |
| |
361 { |
| |
362 char num_used; |
| |
363 icq_ContactItem *ptr = icq_ContactGetFirst(link); |
| |
364 |
| |
365 while(ptr) |
| |
366 { |
| |
367 icq_Packet *p = icq_UDPCreateStdPacket(link, UDP_CMD_CONT_LIST); |
| |
368 |
| |
369 num_used = 0; |
| |
370 icq_PacketAdvance(p,1); |
| |
371 while(ptr && num_used<64) |
| |
372 { |
| |
373 icq_PacketAppend32(p, ptr->uin); |
| |
374 num_used++; |
| |
375 ptr = icq_ContactGetNext(ptr); |
| |
376 } |
| |
377 icq_PacketGotoUDPOutData(p, 0); |
| |
378 icq_PacketAppend8(p, num_used); |
| |
379 icq_UDPSockWrite(link, p); |
| |
380 icq_PacketDelete(p); |
| |
381 } |
| |
382 } |
| |
383 |
| |
384 void icq_SendNewUser(ICQLINK *link, unsigned long uin) /* V5 */ |
| |
385 { |
| |
386 icq_Packet *p = icq_UDPCreateStdPacket(link, UDP_CMD_ADD_TO_LIST); |
| |
387 icq_PacketAppend32(p, uin); |
| |
388 icq_UDPSockWrite(link, p); |
| |
389 icq_PacketDelete(p); |
| |
390 } |
| |
391 |
| |
392 /************************************* |
| |
393 this sends over the visible list |
| |
394 that allows certain users to see you |
| |
395 if you're invisible. |
| |
396 *************************************/ |
| |
397 void icq_SendVisibleList(ICQLINK *link) /* V5 */ |
| |
398 { |
| |
399 char num_used; |
| |
400 icq_ContactItem *ptr = icq_ContactGetFirst(link); |
| |
401 icq_Packet *p = icq_UDPCreateStdPacket(link, UDP_CMD_VIS_LIST); |
| |
402 |
| |
403 num_used = 0; |
| |
404 icq_PacketAdvance(p,1); |
| |
405 while(ptr) |
| |
406 { |
| |
407 if(ptr->vis_list) |
| |
408 { |
| |
409 icq_PacketAppend32(p, ptr->uin); |
| |
410 num_used++; |
| |
411 } |
| |
412 ptr = icq_ContactGetNext(ptr); |
| |
413 } |
| |
414 if(num_used != 0) |
| |
415 { |
| |
416 icq_PacketGotoUDPOutData(p, 0); |
| |
417 icq_PacketAppend8(p, num_used); |
| |
418 icq_UDPSockWrite(link, p); |
| |
419 } |
| |
420 icq_PacketDelete(p); |
| |
421 } |
| |
422 |
| |
423 void icq_SendInvisibleList(ICQLINK *link) /* V5 */ |
| |
424 { |
| |
425 char num_used; |
| |
426 icq_ContactItem *ptr = icq_ContactGetFirst(link); |
| |
427 icq_Packet *p = icq_UDPCreateStdPacket(link, UDP_CMD_INVIS_LIST); |
| |
428 |
| |
429 num_used = 0; |
| |
430 icq_PacketAdvance(p,1); |
| |
431 while(ptr) |
| |
432 { |
| |
433 if(ptr->vis_list) |
| |
434 { |
| |
435 icq_PacketAppend32(p, ptr->uin); |
| |
436 num_used++; |
| |
437 } |
| |
438 ptr = icq_ContactGetNext(ptr); |
| |
439 } |
| |
440 if(num_used != 0) |
| |
441 { |
| |
442 icq_PacketGotoUDPOutData(p, 0); |
| |
443 icq_PacketAppend8(p, num_used); |
| |
444 icq_UDPSockWrite(link, p); |
| |
445 } |
| |
446 icq_PacketDelete(p); |
| |
447 } |
| |
448 |
| |
449 /************************************** |
| |
450 This sends the second login command |
| |
451 this is necessary to finish logging in. |
| |
452 ***************************************/ |
| |
453 void icq_SendLogin1(ICQLINK *link) /* V5 */ |
| |
454 { |
| |
455 icq_Packet *p = icq_UDPCreateStdPacket(link, UDP_CMD_LOGIN_1); |
| |
456 icq_PacketAppend32(p, rand()); |
| |
457 icq_UDPSockWrite(link, p); |
| |
458 icq_PacketDelete(p); |
| |
459 } |
| |
460 |
| |
461 /************************************ |
| |
462 This procedure logins into the server with icq_Uin and pass |
| |
463 on the socket icq_Sok and gives our ip and port. |
| |
464 It does NOT wait for any kind of a response. |
| |
465 *************************************/ |
| |
466 void icq_Login(ICQLINK *link, DWORD status) /* V5 */ |
| |
467 { |
| |
468 icq_Packet *p; |
| |
469 |
| |
470 memset(link->icq_UDPServMess, FALSE, sizeof(link->icq_UDPServMess)); |
| |
471 link->icq_UDPSession = rand() & 0x3FFFFFFF; |
| |
472 link->icq_UDPSeqNum1 = rand() & 0x7FFF; |
| |
473 link->icq_UDPSeqNum2 = 1; |
| |
474 |
| |
475 p = icq_UDPCreateStdPacket(link, UDP_CMD_LOGIN); |
| |
476 icq_PacketAppend32(p, time(0L)); |
| |
477 icq_PacketAppend32n(p, link->icq_TCPSrvPort); |
| |
478 /*icq_PacketAppend16(p, 0); |
| |
479 icq_PacketAppend16n(p, htons(link->icq_OurPort));*/ |
| |
480 icq_PacketAppendString(p, link->icq_Password); |
| |
481 icq_PacketAppend32(p, LOGIN_X1_DEF); |
| |
482 icq_PacketAppend32n(p, htonl(link->icq_OurIP)); |
| |
483 if(link->icq_UseProxy) |
| |
484 icq_PacketAppend8(p, LOGIN_SNDONLY_TCP); |
| |
485 else |
| |
486 icq_PacketAppend8(p, LOGIN_SNDRCV_TCP); |
| |
487 icq_PacketAppend32(p, status); |
| |
488 icq_PacketAppend32(p, LOGIN_X3_DEF); |
| |
489 icq_PacketAppend32(p, LOGIN_X4_DEF); |
| |
490 icq_PacketAppend32(p, LOGIN_X5_DEF); |
| |
491 |
| |
492 icq_UDPSockWrite(link, p); |
| |
493 icq_PacketDelete(p); |
| |
494 } |
| |
495 |
| |
496 /********************** |
| |
497 Logs off ICQ |
| |
498 ***********************/ |
| |
499 void icq_Logout(ICQLINK *link) /* V5 */ |
| |
500 { |
| |
501 icq_Packet *p = icq_UDPCreateStdSeqPacket(link, UDP_CMD_SEND_TEXT_CODE, link->icq_UDPSeqNum1++); |
| |
502 icq_PacketAppendString(p, "B_USER_DISCONNECTED"); |
| |
503 icq_PacketAppend8(p, 5); |
| |
504 icq_PacketAppend8(p, 0); |
| |
505 icq_UDPSockWrite(link, p); |
| |
506 icq_PacketDelete(p); |
| |
507 } |
| |
508 |
| |
509 /******************************* |
| |
510 This routine sends the aknowlegement cmd to the |
| |
511 server it appears that this must be done after |
| |
512 everything the server sends us |
| |
513 *******************************/ |
| |
514 void icq_UDPAck(ICQLINK *link, int seq) /* V5 */ |
| |
515 { |
| |
516 icq_Packet *p = icq_UDPCreateStdSeqPacket(link, UDP_CMD_ACK, seq); |
| |
517 icq_PacketAppend32(p, rand()); |
| |
518 |
| |
519 icq_FmtLog(link, ICQ_LOG_MESSAGE, "Acking\n"); |
| |
520 icq_UDPSockWrite(link, p); |
| |
521 icq_PacketDelete(p); |
| |
522 } |
| |
523 |
| |
524 /*************************************************** |
| |
525 Sends a message thru the server to uin. Text is the |
| |
526 message to send. |
| |
527 ***************************************************/ |
| |
528 WORD icq_UDPSendMessage(ICQLINK *link, DWORD uin, const char *text) /* V5 */ |
| |
529 { |
| |
530 char buf[512]; /* message may be only 450 bytes long */ |
| |
531 icq_Packet *p; |
| |
532 |
| |
533 strncpy(buf, text, 512); |
| |
534 icq_RusConv("kw", buf); |
| |
535 |
| |
536 p = icq_UDPCreateStdPacket(link, UDP_CMD_SEND_THRU_SRV); |
| |
537 icq_PacketAppend32(p, uin); |
| |
538 icq_PacketAppend16(p, TYPE_MSG); |
| |
539 icq_PacketAppendString(p, buf); |
| |
540 |
| |
541 icq_UDPSockWrite(link, p); |
| |
542 icq_PacketDelete(p); |
| |
543 return link->icq_UDPSeqNum1-1; |
| |
544 } |
| |
545 |
| |
546 WORD icq_UDPSendURL(ICQLINK *link, DWORD uin, const char *url, const char *descr) /* V5 */ |
| |
547 { |
| |
548 char buf1[512], buf2[512]; |
| |
549 icq_Packet *p; |
| |
550 |
| |
551 strncpy(buf1, descr, 512); |
| |
552 icq_RusConv("kw", buf1); |
| |
553 strncpy(buf2, url, 512); |
| |
554 |
| |
555 p = icq_UDPCreateStdPacket(link, UDP_CMD_SEND_THRU_SRV); |
| |
556 icq_PacketAppend32(p, uin); |
| |
557 icq_PacketAppend16(p, TYPE_URL); |
| |
558 icq_PacketAppend16(p, strlen(buf1)+strlen(buf2)+2); /* length + the NULL + 0xFE delimiter */ |
| |
559 icq_PacketAppendStringFE(p, buf1); |
| |
560 icq_PacketAppendString0(p, buf2); |
| |
561 |
| |
562 icq_UDPSockWrite(link, p); |
| |
563 icq_PacketDelete(p); |
| |
564 return link->icq_UDPSeqNum1-1; |
| |
565 } |
| |
566 |
| |
567 /************************************************** |
| |
568 Sends a authorization to the server so the Mirabilis |
| |
569 client can add the user. |
| |
570 ***************************************************/ |
| |
571 WORD icq_SendAuthMsg(ICQLINK *link, DWORD uin) /* V5 */ |
| |
572 { |
| |
573 icq_Packet *p = icq_UDPCreateStdPacket(link, UDP_CMD_SEND_THRU_SRV); |
| |
574 icq_PacketAppend32(p, uin); |
| |
575 icq_PacketAppend32(p, TYPE_AUTH); |
| |
576 icq_PacketAppend16(p, 0); |
| |
577 icq_UDPSockWrite(link, p); |
| |
578 icq_PacketDelete(p); |
| |
579 |
| |
580 return link->icq_UDPSeqNum1-1; |
| |
581 } |
| |
582 |
| |
583 /************************************************** |
| |
584 Changes the users status on the server |
| |
585 ***************************************************/ |
| |
586 void icq_ChangeStatus(ICQLINK *link, DWORD status) /* V5 */ |
| |
587 { |
| |
588 icq_Packet *p = icq_UDPCreateStdPacket(link, UDP_CMD_STATUS_CHANGE); |
| |
589 icq_PacketAppend32(p, status); |
| |
590 link->icq_Status = status; |
| |
591 icq_UDPSockWrite(link, p); |
| |
592 icq_PacketDelete(p); |
| |
593 } |
| |
594 |
| |
595 /******************************************************** |
| |
596 Sends a request to the server for info on a specific user |
| |
597 *********************************************************/ |
| |
598 WORD icq_SendInfoReq(ICQLINK *link, DWORD uin) /* V5 */ |
| |
599 { |
| |
600 icq_Packet *p = icq_UDPCreateStdPacket(link, UDP_CMD_INFO_REQ); |
| |
601 icq_PacketAppend32(p, uin); |
| |
602 icq_UDPSockWrite(link, p); |
| |
603 icq_PacketDelete(p); |
| |
604 return link->icq_UDPSeqNum1-1; |
| |
605 } |
| |
606 |
| |
607 /******************************************************** |
| |
608 Sends a request to the server for info on a specific user |
| |
609 *********************************************************/ |
| |
610 WORD icq_SendExtInfoReq(ICQLINK *link, DWORD uin) /* V5 */ |
| |
611 { |
| |
612 icq_Packet *p = icq_UDPCreateStdPacket(link, UDP_CMD_EXT_INFO_REQ); |
| |
613 icq_PacketAppend32(p, uin); |
| |
614 icq_UDPSockWrite(link, p); |
| |
615 icq_PacketDelete(p); |
| |
616 return link->icq_UDPSeqNum1-1; |
| |
617 } |
| |
618 |
| |
619 /************************************************************** |
| |
620 Initializes a server search for the information specified |
| |
621 ***************************************************************/ |
| |
622 void icq_SendSearchReq(ICQLINK *link, const char *email, const char *nick, const char *first, |
| |
623 const char *last) /* V5 */ |
| |
624 { |
| |
625 icq_Packet *p = icq_UDPCreateStdPacket(link, UDP_CMD_SEARCH_USER); |
| |
626 icq_PacketAppendString(p, nick); |
| |
627 icq_PacketAppendString(p, first); |
| |
628 icq_PacketAppendString(p, last); |
| |
629 icq_PacketAppendString(p, email); |
| |
630 icq_UDPSockWrite(link, p); |
| |
631 icq_PacketDelete(p); |
| |
632 } |
| |
633 |
| |
634 /************************************************************** |
| |
635 Initializes a server search for the information specified |
| |
636 ***************************************************************/ |
| |
637 void icq_SendSearchUINReq(ICQLINK *link, DWORD uin) /* V5 */ |
| |
638 { |
| |
639 icq_Packet *p = icq_UDPCreateStdPacket(link, UDP_CMD_SEARCH_UIN); |
| |
640 icq_PacketAppend32(p, uin); |
| |
641 icq_UDPSockWrite(link, p); |
| |
642 icq_PacketDelete(p); |
| |
643 } |
| |
644 |
| |
645 /************************************************** |
| |
646 Registers a new uin in the ICQ network |
| |
647 ***************************************************/ |
| |
648 void icq_RegNewUser(ICQLINK *link, const char *pass) /* V5 */ |
| |
649 { |
| |
650 char pass8[9]; |
| |
651 icq_Packet *p = icq_UDPCreateStdSeqPacket(link, UDP_CMD_REG_NEW_USER, link->icq_UDPSeqNum1++); |
| |
652 strncpy(pass8, pass, 8); |
| |
653 icq_PacketAppendString(p, pass8); |
| |
654 icq_PacketAppend32(p, 0xA0); |
| |
655 icq_PacketAppend32(p, 0x2461); |
| |
656 icq_PacketAppend32(p, 0xA00000); |
| |
657 icq_PacketAppend32(p, 0x00); |
| |
658 icq_PacketGoto(p, 6); |
| |
659 icq_PacketAppend32(p, 0); |
| |
660 icq_PacketAppend32(p, rand()); |
| |
661 icq_UDPSockWrite(link, p); |
| |
662 icq_FmtLog(link, ICQ_LOG_MESSAGE, "Send RegNewUser packet to the server\n"); |
| |
663 icq_PacketDelete(p); |
| |
664 } |
| |
665 |
| |
666 WORD icq_UpdateUserInfo(ICQLINK *link, const char *nick, const char *first, const char *last, |
| |
667 const char *email) /* V5 */ |
| |
668 { |
| |
669 icq_Packet *p = icq_UDPCreateStdPacket(link, UDP_CMD_UPDATE_INFO); |
| |
670 icq_PacketAppendString(p, nick); |
| |
671 icq_PacketAppendString(p, first); |
| |
672 icq_PacketAppendString(p, last); |
| |
673 icq_PacketAppendString(p, email); |
| |
674 /* auth (byte)? */ |
| |
675 icq_UDPSockWrite(link, p); |
| |
676 icq_PacketDelete(p); |
| |
677 return link->icq_UDPSeqNum1-1; |
| |
678 } |
| |
679 |
| |
680 WORD icq_UpdateAuthInfo(ICQLINK *link, DWORD auth) /* V5 */ |
| |
681 { |
| |
682 icq_Packet *p = icq_UDPCreateStdPacket(link, UDP_CMD_UPDATE_AUTH); |
| |
683 icq_PacketAppend32(p, auth); /* NOT auth? */ |
| |
684 icq_UDPSockWrite(link, p); |
| |
685 icq_PacketDelete(p); |
| |
686 return link->icq_UDPSeqNum1-1; |
| |
687 } |
| |
688 |
| |
689 WORD icq_UpdateMetaInfoSet(ICQLINK *link, const char *nick, const char *first, const char *last, |
| |
690 const char *email, const char *email2, const char *email3, |
| |
691 const char *city, const char *state, const char *phone, const char *fax, |
| |
692 const char *street, const char *cellular, unsigned long zip, |
| |
693 unsigned short cnt_code, unsigned char cnt_stat, unsigned char emailhide) |
| |
694 { |
| |
695 icq_Packet *p = icq_UDPCreateStdPacket(link, UDP_CMD_META_USER); |
| |
696 icq_PacketAppend16(p, META_CMD_SET_INFO); |
| |
697 icq_PacketAppendString(p, nick); |
| |
698 icq_PacketAppendString(p, first); |
| |
699 icq_PacketAppendString(p, last); |
| |
700 icq_PacketAppendString(p, email); |
| |
701 icq_PacketAppendString(p, email2); |
| |
702 icq_PacketAppendString(p, email3); |
| |
703 icq_PacketAppendString(p, city); |
| |
704 icq_PacketAppendString(p, state); |
| |
705 icq_PacketAppendString(p, phone); |
| |
706 icq_PacketAppendString(p, fax); |
| |
707 icq_PacketAppendString(p, street); |
| |
708 icq_PacketAppendString(p, cellular); |
| |
709 icq_PacketAppend32(p, zip); |
| |
710 icq_PacketAppend16(p, cnt_code); |
| |
711 icq_PacketAppend8(p, cnt_stat); |
| |
712 icq_PacketAppend8(p, emailhide); |
| |
713 icq_UDPSockWrite(link, p); |
| |
714 icq_PacketDelete(p); |
| |
715 return link->icq_UDPSeqNum2-1; |
| |
716 } |
| |
717 |
| |
718 WORD icq_UpdateMetaInfoHomepage(ICQLINK *link, unsigned char age, const char *homepage, |
| |
719 unsigned char year, unsigned char month, unsigned char day, |
| |
720 unsigned char lang1, unsigned char lang2, unsigned char lang3) |
| |
721 { |
| |
722 icq_Packet *p = icq_UDPCreateStdPacket(link, UDP_CMD_META_USER); |
| |
723 icq_PacketAppend16(p, META_CMD_SET_HOMEPAGE); |
| |
724 icq_PacketAppend8(p, age); |
| |
725 icq_PacketAppend16(p, 0x0200); |
| |
726 icq_PacketAppendString(p, homepage); |
| |
727 icq_PacketAppend8(p, year); |
| |
728 icq_PacketAppend8(p, month); |
| |
729 icq_PacketAppend8(p, day); |
| |
730 icq_PacketAppend8(p, 0xFF /* lang1 */); |
| |
731 icq_PacketAppend8(p, 0xFF /* lang2 */); |
| |
732 icq_PacketAppend8(p, 0xFF /* lang3 */); |
| |
733 icq_UDPSockWrite(link, p); |
| |
734 icq_PacketDelete(p); |
| |
735 return link->icq_UDPSeqNum2-1; |
| |
736 } |
| |
737 |
| |
738 WORD icq_UpdateMetaInfoAbout(ICQLINK *link, const char *about) |
| |
739 { |
| |
740 icq_Packet *p = icq_UDPCreateStdPacket(link, UDP_CMD_META_USER); |
| |
741 icq_PacketAppend16(p, META_CMD_SET_ABOUT); |
| |
742 icq_PacketAppendString(p, about); |
| |
743 icq_UDPSockWrite(link, p); |
| |
744 icq_PacketDelete(p); |
| |
745 return link->icq_UDPSeqNum2-1; |
| |
746 } |
| |
747 |
| |
748 WORD icq_UpdateMetaInfoSecurity(ICQLINK *link, unsigned char reqauth, unsigned char webpresence, |
| |
749 unsigned char pubip) |
| |
750 { |
| |
751 icq_Packet *p = icq_UDPCreateStdPacket(link, UDP_CMD_META_USER); |
| |
752 icq_PacketAppend16(p, META_CMD_SET_SECURE); |
| |
753 icq_PacketAppend8(p, !reqauth); |
| |
754 icq_PacketAppend8(p, webpresence); |
| |
755 icq_PacketAppend8(p, pubip); |
| |
756 icq_UDPSockWrite(link, p); |
| |
757 icq_PacketDelete(p); |
| |
758 return link->icq_UDPSeqNum2-1; |
| |
759 } |
| |
760 |
| |
761 WORD icq_UpdateNewUserInfo(ICQLINK *link, const char *nick, const char *first, const char *last, |
| |
762 const char *email) /* V5 */ |
| |
763 { |
| |
764 icq_Packet *p = icq_UDPCreateStdPacket(link, UDP_CMD_NEW_USER_INFO); |
| |
765 icq_PacketAppendString(p, nick); |
| |
766 icq_PacketAppendString(p, first); |
| |
767 icq_PacketAppendString(p, last); |
| |
768 icq_PacketAppendString(p, email); |
| |
769 icq_PacketAppend8(p, 1); |
| |
770 icq_PacketAppend8(p, 1); |
| |
771 icq_PacketAppend8(p, 1); |
| |
772 icq_UDPSockWrite(link, p); |
| |
773 icq_PacketDelete(p); |
| |
774 return link->icq_UDPSeqNum1-1; |
| |
775 } |
| |
776 |
| |
777 WORD icq_SendMetaInfoReq(ICQLINK *link, unsigned long uin) |
| |
778 { |
| |
779 icq_Packet *p = icq_UDPCreateStdPacket(link, UDP_CMD_META_USER); |
| |
780 icq_PacketAppend16(p, META_CMD_REQ_INFO); |
| |
781 icq_PacketAppend32(p, uin); |
| |
782 icq_UDPSockWrite(link, p); |
| |
783 icq_PacketDelete(p); |
| |
784 return link->icq_UDPSeqNum2-1; |
| |
785 } |