Mercurial > pidgin
annotate src/protocols/gg/lib/libgadu.c @ 12007:8724718d387f
[gaim-migrate @ 14300]
Further updates to gg from Bartosz Oler. This makes the login and token retrieval processes asynchronous. There are also some encoding fixes and various cleanups. There are some changes from me to make it work on win32.
committer: Tailor Script <tailor@pidgin.im>
author | Daniel Atallah <daniel.atallah@gmail.com> |
---|---|
date | Tue, 08 Nov 2005 19:45:09 +0000 |
parents | 3c536224f0d0 |
children | 9cbc5967fbfd |
rev | line source |
---|---|
12007
8724718d387f
[gaim-migrate @ 14300]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11546
diff
changeset
|
1 /* $Id: libgadu.c 14300 2005-11-08 19:45:09Z datallah $ */ |
11360 | 2 |
3 /* | |
4 * (C) Copyright 2001-2003 Wojtek Kaniewski <wojtekka@irc.pl> | |
5 * Robert J. Woźny <speedy@ziew.org> | |
6 * Arkadiusz Miśkiewicz <arekm@pld-linux.org> | |
7 * Tomasz Chiliński <chilek@chilan.com> | |
8 * | |
9 * This program is free software; you can redistribute it and/or modify | |
10 * it under the terms of the GNU Lesser General Public License Version | |
11 * 2.1 as published by the Free Software Foundation. | |
12 * | |
13 * This program is distributed in the hope that it will be useful, | |
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
16 * GNU Lesser General Public License for more details. | |
17 * | |
18 * You should have received a copy of the GNU Lesser General Public | |
19 * License along with this program; if not, write to the Free Software | |
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, | |
21 * USA. | |
22 */ | |
23 | |
24 #include <sys/types.h> | |
11546
3c536224f0d0
[gaim-migrate @ 13801]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11360
diff
changeset
|
25 #ifndef _WIN32 |
11360 | 26 #include <sys/wait.h> |
27 #include <sys/socket.h> | |
28 #include <netinet/in.h> | |
29 #include <arpa/inet.h> | |
30 #ifdef sun | |
31 # include <sys/filio.h> | |
32 #endif | |
11546
3c536224f0d0
[gaim-migrate @ 13801]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11360
diff
changeset
|
33 #else |
3c536224f0d0
[gaim-migrate @ 13801]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11360
diff
changeset
|
34 #include <io.h> |
3c536224f0d0
[gaim-migrate @ 13801]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11360
diff
changeset
|
35 #include <fcntl.h> |
3c536224f0d0
[gaim-migrate @ 13801]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11360
diff
changeset
|
36 #include <errno.h> |
3c536224f0d0
[gaim-migrate @ 13801]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11360
diff
changeset
|
37 #define SHUT_RDWR SD_BOTH |
3c536224f0d0
[gaim-migrate @ 13801]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11360
diff
changeset
|
38 #endif |
11360 | 39 |
40 #include "libgadu-config.h" | |
41 | |
42 #include <errno.h> | |
11546
3c536224f0d0
[gaim-migrate @ 13801]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11360
diff
changeset
|
43 #ifndef _WIN32 |
11360 | 44 #include <netdb.h> |
11546
3c536224f0d0
[gaim-migrate @ 13801]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11360
diff
changeset
|
45 #endif |
11360 | 46 #ifdef __GG_LIBGADU_HAVE_PTHREAD |
47 # include <pthread.h> | |
48 #endif | |
49 #include <stdarg.h> | |
50 #include <stdio.h> | |
51 #include <stdlib.h> | |
52 #include <string.h> | |
53 #include <unistd.h> | |
54 #ifdef __GG_LIBGADU_HAVE_OPENSSL | |
55 # include <openssl/err.h> | |
56 # include <openssl/rand.h> | |
57 #endif | |
58 | |
59 #include "compat.h" | |
60 #include "libgadu.h" | |
61 | |
62 int gg_debug_level = 0; | |
63 void (*gg_debug_handler)(int level, const char *format, va_list ap) = NULL; | |
64 | |
65 int gg_dcc_port = 0; | |
66 unsigned long gg_dcc_ip = 0; | |
67 | |
68 unsigned long gg_local_ip = 0; | |
69 /* | |
70 * zmienne opisujące parametry proxy http. | |
71 */ | |
72 char *gg_proxy_host = NULL; | |
73 int gg_proxy_port = 0; | |
74 int gg_proxy_enabled = 0; | |
75 int gg_proxy_http_only = 0; | |
76 char *gg_proxy_username = NULL; | |
77 char *gg_proxy_password = NULL; | |
78 | |
79 #ifndef lint | |
80 static char rcsid[] | |
81 #ifdef __GNUC__ | |
82 __attribute__ ((unused)) | |
83 #endif | |
12007
8724718d387f
[gaim-migrate @ 14300]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11546
diff
changeset
|
84 = "$Id: libgadu.c 14300 2005-11-08 19:45:09Z datallah $"; |
11360 | 85 #endif |
86 | |
12007
8724718d387f
[gaim-migrate @ 14300]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11546
diff
changeset
|
87 #ifdef _WIN32 |
8724718d387f
[gaim-migrate @ 14300]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11546
diff
changeset
|
88 /** |
8724718d387f
[gaim-migrate @ 14300]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11546
diff
changeset
|
89 * Deal with the fact that you can't select() on a win32 file fd. |
8724718d387f
[gaim-migrate @ 14300]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11546
diff
changeset
|
90 * This makes it practically impossible to tie into gaim's event loop. |
8724718d387f
[gaim-migrate @ 14300]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11546
diff
changeset
|
91 * |
8724718d387f
[gaim-migrate @ 14300]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11546
diff
changeset
|
92 * -This is thanks to Tor Lillqvist. |
8724718d387f
[gaim-migrate @ 14300]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11546
diff
changeset
|
93 * XXX - Move this to where the rest of the the win32 compatiblity stuff goes when we push the changes back to libgadu. |
8724718d387f
[gaim-migrate @ 14300]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11546
diff
changeset
|
94 */ |
8724718d387f
[gaim-migrate @ 14300]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11546
diff
changeset
|
95 static int |
8724718d387f
[gaim-migrate @ 14300]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11546
diff
changeset
|
96 socket_pipe (int *fds) |
8724718d387f
[gaim-migrate @ 14300]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11546
diff
changeset
|
97 { |
8724718d387f
[gaim-migrate @ 14300]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11546
diff
changeset
|
98 SOCKET temp, socket1 = -1, socket2 = -1; |
8724718d387f
[gaim-migrate @ 14300]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11546
diff
changeset
|
99 struct sockaddr_in saddr; |
8724718d387f
[gaim-migrate @ 14300]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11546
diff
changeset
|
100 int len; |
8724718d387f
[gaim-migrate @ 14300]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11546
diff
changeset
|
101 u_long arg; |
8724718d387f
[gaim-migrate @ 14300]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11546
diff
changeset
|
102 fd_set read_set, write_set; |
8724718d387f
[gaim-migrate @ 14300]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11546
diff
changeset
|
103 struct timeval tv; |
8724718d387f
[gaim-migrate @ 14300]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11546
diff
changeset
|
104 |
8724718d387f
[gaim-migrate @ 14300]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11546
diff
changeset
|
105 temp = socket(AF_INET, SOCK_STREAM, 0); |
8724718d387f
[gaim-migrate @ 14300]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11546
diff
changeset
|
106 |
8724718d387f
[gaim-migrate @ 14300]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11546
diff
changeset
|
107 if (temp == INVALID_SOCKET) { |
8724718d387f
[gaim-migrate @ 14300]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11546
diff
changeset
|
108 goto out0; |
8724718d387f
[gaim-migrate @ 14300]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11546
diff
changeset
|
109 } |
8724718d387f
[gaim-migrate @ 14300]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11546
diff
changeset
|
110 |
8724718d387f
[gaim-migrate @ 14300]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11546
diff
changeset
|
111 arg = 1; |
8724718d387f
[gaim-migrate @ 14300]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11546
diff
changeset
|
112 if (ioctlsocket(temp, FIONBIO, &arg) == SOCKET_ERROR) { |
8724718d387f
[gaim-migrate @ 14300]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11546
diff
changeset
|
113 goto out0; |
8724718d387f
[gaim-migrate @ 14300]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11546
diff
changeset
|
114 } |
8724718d387f
[gaim-migrate @ 14300]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11546
diff
changeset
|
115 |
8724718d387f
[gaim-migrate @ 14300]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11546
diff
changeset
|
116 memset(&saddr, 0, sizeof(saddr)); |
8724718d387f
[gaim-migrate @ 14300]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11546
diff
changeset
|
117 saddr.sin_family = AF_INET; |
8724718d387f
[gaim-migrate @ 14300]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11546
diff
changeset
|
118 saddr.sin_port = 0; |
8724718d387f
[gaim-migrate @ 14300]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11546
diff
changeset
|
119 saddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); |
8724718d387f
[gaim-migrate @ 14300]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11546
diff
changeset
|
120 |
8724718d387f
[gaim-migrate @ 14300]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11546
diff
changeset
|
121 if (bind(temp, (struct sockaddr *)&saddr, sizeof (saddr))) { |
8724718d387f
[gaim-migrate @ 14300]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11546
diff
changeset
|
122 goto out0; |
8724718d387f
[gaim-migrate @ 14300]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11546
diff
changeset
|
123 } |
8724718d387f
[gaim-migrate @ 14300]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11546
diff
changeset
|
124 |
8724718d387f
[gaim-migrate @ 14300]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11546
diff
changeset
|
125 if (listen(temp, 1) == SOCKET_ERROR) { |
8724718d387f
[gaim-migrate @ 14300]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11546
diff
changeset
|
126 goto out0; |
8724718d387f
[gaim-migrate @ 14300]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11546
diff
changeset
|
127 } |
8724718d387f
[gaim-migrate @ 14300]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11546
diff
changeset
|
128 |
8724718d387f
[gaim-migrate @ 14300]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11546
diff
changeset
|
129 len = sizeof(saddr); |
8724718d387f
[gaim-migrate @ 14300]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11546
diff
changeset
|
130 if (getsockname(temp, (struct sockaddr *)&saddr, &len)) { |
8724718d387f
[gaim-migrate @ 14300]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11546
diff
changeset
|
131 goto out0; |
8724718d387f
[gaim-migrate @ 14300]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11546
diff
changeset
|
132 } |
8724718d387f
[gaim-migrate @ 14300]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11546
diff
changeset
|
133 |
8724718d387f
[gaim-migrate @ 14300]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11546
diff
changeset
|
134 socket1 = socket(AF_INET, SOCK_STREAM, 0); |
8724718d387f
[gaim-migrate @ 14300]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11546
diff
changeset
|
135 |
8724718d387f
[gaim-migrate @ 14300]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11546
diff
changeset
|
136 if (socket1 == INVALID_SOCKET) { |
8724718d387f
[gaim-migrate @ 14300]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11546
diff
changeset
|
137 goto out0; |
8724718d387f
[gaim-migrate @ 14300]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11546
diff
changeset
|
138 } |
8724718d387f
[gaim-migrate @ 14300]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11546
diff
changeset
|
139 |
8724718d387f
[gaim-migrate @ 14300]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11546
diff
changeset
|
140 arg = 1; |
8724718d387f
[gaim-migrate @ 14300]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11546
diff
changeset
|
141 if (ioctlsocket(socket1, FIONBIO, &arg) == SOCKET_ERROR) { |
8724718d387f
[gaim-migrate @ 14300]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11546
diff
changeset
|
142 goto out1; |
8724718d387f
[gaim-migrate @ 14300]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11546
diff
changeset
|
143 } |
8724718d387f
[gaim-migrate @ 14300]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11546
diff
changeset
|
144 |
8724718d387f
[gaim-migrate @ 14300]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11546
diff
changeset
|
145 if (connect(socket1, (struct sockaddr *)&saddr, len) != SOCKET_ERROR || |
8724718d387f
[gaim-migrate @ 14300]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11546
diff
changeset
|
146 WSAGetLastError() != WSAEWOULDBLOCK) { |
8724718d387f
[gaim-migrate @ 14300]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11546
diff
changeset
|
147 goto out1; |
8724718d387f
[gaim-migrate @ 14300]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11546
diff
changeset
|
148 } |
8724718d387f
[gaim-migrate @ 14300]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11546
diff
changeset
|
149 |
8724718d387f
[gaim-migrate @ 14300]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11546
diff
changeset
|
150 FD_ZERO(&read_set); |
8724718d387f
[gaim-migrate @ 14300]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11546
diff
changeset
|
151 FD_SET(temp, &read_set); |
8724718d387f
[gaim-migrate @ 14300]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11546
diff
changeset
|
152 |
8724718d387f
[gaim-migrate @ 14300]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11546
diff
changeset
|
153 tv.tv_sec = 0; |
8724718d387f
[gaim-migrate @ 14300]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11546
diff
changeset
|
154 tv.tv_usec = 0; |
8724718d387f
[gaim-migrate @ 14300]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11546
diff
changeset
|
155 |
8724718d387f
[gaim-migrate @ 14300]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11546
diff
changeset
|
156 if (select(0, &read_set, NULL, NULL, NULL) == SOCKET_ERROR) { |
8724718d387f
[gaim-migrate @ 14300]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11546
diff
changeset
|
157 goto out1; |
8724718d387f
[gaim-migrate @ 14300]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11546
diff
changeset
|
158 } |
8724718d387f
[gaim-migrate @ 14300]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11546
diff
changeset
|
159 |
8724718d387f
[gaim-migrate @ 14300]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11546
diff
changeset
|
160 if (!FD_ISSET(temp, &read_set)) { |
8724718d387f
[gaim-migrate @ 14300]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11546
diff
changeset
|
161 goto out1; |
8724718d387f
[gaim-migrate @ 14300]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11546
diff
changeset
|
162 } |
8724718d387f
[gaim-migrate @ 14300]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11546
diff
changeset
|
163 |
8724718d387f
[gaim-migrate @ 14300]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11546
diff
changeset
|
164 socket2 = accept(temp, (struct sockaddr *) &saddr, &len); |
8724718d387f
[gaim-migrate @ 14300]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11546
diff
changeset
|
165 if (socket2 == INVALID_SOCKET) { |
8724718d387f
[gaim-migrate @ 14300]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11546
diff
changeset
|
166 goto out1; |
8724718d387f
[gaim-migrate @ 14300]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11546
diff
changeset
|
167 } |
8724718d387f
[gaim-migrate @ 14300]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11546
diff
changeset
|
168 |
8724718d387f
[gaim-migrate @ 14300]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11546
diff
changeset
|
169 FD_ZERO(&write_set); |
8724718d387f
[gaim-migrate @ 14300]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11546
diff
changeset
|
170 FD_SET(socket1, &write_set); |
8724718d387f
[gaim-migrate @ 14300]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11546
diff
changeset
|
171 |
8724718d387f
[gaim-migrate @ 14300]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11546
diff
changeset
|
172 tv.tv_sec = 0; |
8724718d387f
[gaim-migrate @ 14300]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11546
diff
changeset
|
173 tv.tv_usec = 0; |
8724718d387f
[gaim-migrate @ 14300]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11546
diff
changeset
|
174 |
8724718d387f
[gaim-migrate @ 14300]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11546
diff
changeset
|
175 if (select(0, NULL, &write_set, NULL, NULL) == SOCKET_ERROR) { |
8724718d387f
[gaim-migrate @ 14300]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11546
diff
changeset
|
176 goto out2; |
8724718d387f
[gaim-migrate @ 14300]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11546
diff
changeset
|
177 } |
8724718d387f
[gaim-migrate @ 14300]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11546
diff
changeset
|
178 |
8724718d387f
[gaim-migrate @ 14300]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11546
diff
changeset
|
179 if (!FD_ISSET(socket1, &write_set)) { |
8724718d387f
[gaim-migrate @ 14300]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11546
diff
changeset
|
180 goto out2; |
8724718d387f
[gaim-migrate @ 14300]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11546
diff
changeset
|
181 } |
8724718d387f
[gaim-migrate @ 14300]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11546
diff
changeset
|
182 |
8724718d387f
[gaim-migrate @ 14300]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11546
diff
changeset
|
183 arg = 0; |
8724718d387f
[gaim-migrate @ 14300]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11546
diff
changeset
|
184 if (ioctlsocket(socket1, FIONBIO, &arg) == SOCKET_ERROR) { |
8724718d387f
[gaim-migrate @ 14300]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11546
diff
changeset
|
185 goto out2; |
8724718d387f
[gaim-migrate @ 14300]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11546
diff
changeset
|
186 } |
8724718d387f
[gaim-migrate @ 14300]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11546
diff
changeset
|
187 |
8724718d387f
[gaim-migrate @ 14300]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11546
diff
changeset
|
188 arg = 0; |
8724718d387f
[gaim-migrate @ 14300]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11546
diff
changeset
|
189 if (ioctlsocket(socket2, FIONBIO, &arg) == SOCKET_ERROR) { |
8724718d387f
[gaim-migrate @ 14300]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11546
diff
changeset
|
190 goto out2; |
8724718d387f
[gaim-migrate @ 14300]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11546
diff
changeset
|
191 } |
8724718d387f
[gaim-migrate @ 14300]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11546
diff
changeset
|
192 |
8724718d387f
[gaim-migrate @ 14300]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11546
diff
changeset
|
193 fds[0] = socket1; |
8724718d387f
[gaim-migrate @ 14300]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11546
diff
changeset
|
194 fds[1] = socket2; |
8724718d387f
[gaim-migrate @ 14300]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11546
diff
changeset
|
195 |
8724718d387f
[gaim-migrate @ 14300]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11546
diff
changeset
|
196 closesocket (temp); |
8724718d387f
[gaim-migrate @ 14300]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11546
diff
changeset
|
197 |
8724718d387f
[gaim-migrate @ 14300]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11546
diff
changeset
|
198 return 0; |
8724718d387f
[gaim-migrate @ 14300]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11546
diff
changeset
|
199 |
8724718d387f
[gaim-migrate @ 14300]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11546
diff
changeset
|
200 out2: |
8724718d387f
[gaim-migrate @ 14300]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11546
diff
changeset
|
201 closesocket (socket2); |
8724718d387f
[gaim-migrate @ 14300]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11546
diff
changeset
|
202 out1: |
8724718d387f
[gaim-migrate @ 14300]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11546
diff
changeset
|
203 closesocket (socket1); |
8724718d387f
[gaim-migrate @ 14300]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11546
diff
changeset
|
204 out0: |
8724718d387f
[gaim-migrate @ 14300]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11546
diff
changeset
|
205 closesocket (temp); |
8724718d387f
[gaim-migrate @ 14300]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11546
diff
changeset
|
206 errno = EIO; /* XXX */ |
8724718d387f
[gaim-migrate @ 14300]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11546
diff
changeset
|
207 |
8724718d387f
[gaim-migrate @ 14300]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11546
diff
changeset
|
208 return -1; |
8724718d387f
[gaim-migrate @ 14300]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11546
diff
changeset
|
209 } |
8724718d387f
[gaim-migrate @ 14300]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11546
diff
changeset
|
210 #endif |
8724718d387f
[gaim-migrate @ 14300]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11546
diff
changeset
|
211 |
11360 | 212 /* |
213 * gg_libgadu_version() | |
214 * | |
215 * zwraca wersję libgadu. | |
216 * | |
217 * - brak | |
218 * | |
219 * wersja libgadu. | |
220 */ | |
221 const char *gg_libgadu_version() | |
222 { | |
223 return GG_LIBGADU_VERSION; | |
224 } | |
225 | |
226 /* | |
227 * gg_fix32() | |
228 * | |
229 * zamienia kolejność bajtów w liczbie 32-bitowej tak, by odpowiadała | |
230 * kolejności bajtów w protokole GG. ze względu na LE-owość serwera, | |
231 * zamienia tylko na maszynach BE-wych. | |
232 * | |
233 * - x - liczba do zamiany | |
234 * | |
235 * liczba z odpowiednią kolejnością bajtów. | |
236 */ | |
237 uint32_t gg_fix32(uint32_t x) | |
238 { | |
239 #ifndef __GG_LIBGADU_BIGENDIAN | |
240 return x; | |
241 #else | |
242 return (uint32_t) | |
243 (((x & (uint32_t) 0x000000ffU) << 24) | | |
244 ((x & (uint32_t) 0x0000ff00U) << 8) | | |
245 ((x & (uint32_t) 0x00ff0000U) >> 8) | | |
246 ((x & (uint32_t) 0xff000000U) >> 24)); | |
12007
8724718d387f
[gaim-migrate @ 14300]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11546
diff
changeset
|
247 #endif |
11360 | 248 } |
249 | |
250 /* | |
251 * gg_fix16() | |
252 * | |
253 * zamienia kolejność bajtów w liczbie 16-bitowej tak, by odpowiadała | |
254 * kolejności bajtów w protokole GG. ze względu na LE-owość serwera, | |
255 * zamienia tylko na maszynach BE-wych. | |
256 * | |
257 * - x - liczba do zamiany | |
258 * | |
259 * liczba z odpowiednią kolejnością bajtów. | |
260 */ | |
261 uint16_t gg_fix16(uint16_t x) | |
262 { | |
263 #ifndef __GG_LIBGADU_BIGENDIAN | |
264 return x; | |
265 #else | |
266 return (uint16_t) | |
267 (((x & (uint16_t) 0x00ffU) << 8) | | |
268 ((x & (uint16_t) 0xff00U) >> 8)); | |
269 #endif | |
270 } | |
271 | |
272 /* | |
273 * gg_login_hash() // funkcja wewnętrzna | |
274 * | |
275 * liczy hash z hasła i danego seeda. | |
276 * | |
277 * - password - hasło do hashowania | |
278 * - seed - wartość podana przez serwer | |
279 * | |
280 * hash. | |
281 */ | |
282 unsigned int gg_login_hash(const unsigned char *password, unsigned int seed) | |
283 { | |
284 unsigned int x, y, z; | |
285 | |
286 y = seed; | |
287 | |
288 for (x = 0; *password; password++) { | |
289 x = (x & 0xffffff00) | *password; | |
290 y ^= x; | |
291 y += x; | |
292 x <<= 8; | |
293 y ^= x; | |
294 x <<= 8; | |
295 y -= x; | |
296 x <<= 8; | |
297 y ^= x; | |
298 | |
299 z = y & 0x1F; | |
300 y = (y << z) | (y >> (32 - z)); | |
301 } | |
302 | |
303 return y; | |
304 } | |
305 | |
11546
3c536224f0d0
[gaim-migrate @ 13801]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11360
diff
changeset
|
306 #ifndef _WIN32 |
3c536224f0d0
[gaim-migrate @ 13801]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11360
diff
changeset
|
307 |
11360 | 308 /* |
309 * gg_resolve() // funkcja wewnętrzna | |
310 * | |
311 * tworzy potok, forkuje się i w drugim procesie zaczyna resolvować | |
312 * podanego hosta. zapisuje w sesji deskryptor potoku. jeśli coś tam | |
313 * będzie gotowego, znaczy, że można wczytać struct in_addr. jeśli | |
314 * nie znajdzie, zwraca INADDR_NONE. | |
315 * | |
316 * - fd - wskaźnik gdzie wrzucić deskryptor | |
317 * - pid - gdzie wrzucić pid procesu potomnego | |
318 * - hostname - nazwa hosta do zresolvowania | |
319 * | |
320 * 0, -1. | |
321 */ | |
322 int gg_resolve(int *fd, int *pid, const char *hostname) | |
323 { | |
324 int pipes[2], res; | |
325 struct in_addr a; | |
326 int errno2; | |
327 | |
328 gg_debug(GG_DEBUG_FUNCTION, "** gg_resolve(%p, %p, \"%s\");\n", fd, pid, hostname); | |
329 | |
330 if (!fd || !pid) { | |
331 errno = EFAULT; | |
332 return -1; | |
333 } | |
334 | |
335 if (pipe(pipes) == -1) | |
336 return -1; | |
337 | |
338 if ((res = fork()) == -1) { | |
339 errno2 = errno; | |
340 close(pipes[0]); | |
341 close(pipes[1]); | |
342 errno = errno2; | |
343 return -1; | |
344 } | |
345 | |
346 if (!res) { | |
347 if ((a.s_addr = inet_addr(hostname)) == INADDR_NONE) { | |
348 struct in_addr *hn; | |
349 | |
350 if (!(hn = gg_gethostbyname(hostname))) | |
351 a.s_addr = INADDR_NONE; | |
352 else { | |
353 a.s_addr = hn->s_addr; | |
354 free(hn); | |
355 } | |
356 } | |
357 | |
358 write(pipes[1], &a, sizeof(a)); | |
359 | |
360 exit(0); | |
361 } | |
362 | |
363 close(pipes[1]); | |
364 | |
365 *fd = pipes[0]; | |
366 *pid = res; | |
367 | |
368 return 0; | |
369 } | |
11546
3c536224f0d0
[gaim-migrate @ 13801]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11360
diff
changeset
|
370 #endif |
11360 | 371 |
372 #ifdef __GG_LIBGADU_HAVE_PTHREAD | |
373 | |
374 struct gg_resolve_pthread_data { | |
375 char *hostname; | |
376 int fd; | |
377 }; | |
378 | |
379 static void *gg_resolve_pthread_thread(void *arg) | |
380 { | |
381 struct gg_resolve_pthread_data *d = arg; | |
382 struct in_addr a; | |
383 | |
384 pthread_detach(pthread_self()); | |
385 | |
386 if ((a.s_addr = inet_addr(d->hostname)) == INADDR_NONE) { | |
387 struct in_addr *hn; | |
388 | |
389 if (!(hn = gg_gethostbyname(d->hostname))) | |
390 a.s_addr = INADDR_NONE; | |
391 else { | |
392 a.s_addr = hn->s_addr; | |
393 free(hn); | |
394 } | |
395 } | |
396 | |
397 write(d->fd, &a, sizeof(a)); | |
398 close(d->fd); | |
399 | |
400 free(d->hostname); | |
401 d->hostname = NULL; | |
402 | |
403 free(d); | |
404 | |
405 pthread_exit(NULL); | |
406 | |
407 return NULL; /* żeby kompilator nie marudził */ | |
408 } | |
409 | |
410 /* | |
411 * gg_resolve_pthread() // funkcja wewnętrzna | |
412 * | |
413 * tworzy potok, nowy wątek i w nim zaczyna resolvować podanego hosta. | |
414 * zapisuje w sesji deskryptor potoku. jeśli coś tam będzie gotowego, | |
415 * znaczy, że można wczytać struct in_addr. jeśli nie znajdzie, zwraca | |
416 * INADDR_NONE. | |
417 * | |
418 * - fd - wskaźnik do zmiennej przechowującej desktyptor resolvera | |
419 * - resolver - wskaźnik do wskaźnika resolvera | |
420 * - hostname - nazwa hosta do zresolvowania | |
421 * | |
422 * 0, -1. | |
423 */ | |
424 int gg_resolve_pthread(int *fd, void **resolver, const char *hostname) | |
425 { | |
426 struct gg_resolve_pthread_data *d = NULL; | |
427 pthread_t *tmp; | |
428 int pipes[2], new_errno; | |
429 | |
430 gg_debug(GG_DEBUG_FUNCTION, "** gg_resolve_pthread(%p, %p, \"%s\");\n", fd, resolver, hostname); | |
431 | |
432 if (!resolver || !fd || !hostname) { | |
433 gg_debug(GG_DEBUG_MISC, "// gg_resolve_pthread() invalid arguments\n"); | |
434 errno = EFAULT; | |
435 return -1; | |
436 } | |
437 | |
438 if (!(tmp = malloc(sizeof(pthread_t)))) { | |
439 gg_debug(GG_DEBUG_MISC, "// gg_resolve_pthread() out of memory for pthread id\n"); | |
440 return -1; | |
441 } | |
442 | |
443 if (pipe(pipes) == -1) { | |
444 gg_debug(GG_DEBUG_MISC, "// gg_resolve_pthread() unable to create pipes (errno=%d, %s)\n", errno, strerror(errno)); | |
445 free(tmp); | |
446 return -1; | |
447 } | |
448 | |
449 if (!(d = malloc(sizeof(*d)))) { | |
450 gg_debug(GG_DEBUG_MISC, "// gg_resolve_pthread() out of memory\n"); | |
451 new_errno = errno; | |
452 goto cleanup; | |
453 } | |
454 | |
455 d->hostname = NULL; | |
456 | |
457 if (!(d->hostname = strdup(hostname))) { | |
458 gg_debug(GG_DEBUG_MISC, "// gg_resolve_pthread() out of memory\n"); | |
459 new_errno = errno; | |
460 goto cleanup; | |
461 } | |
462 | |
463 d->fd = pipes[1]; | |
464 | |
465 if (pthread_create(tmp, NULL, gg_resolve_pthread_thread, d)) { | |
466 gg_debug(GG_DEBUG_MISC, "// gg_resolve_phread() unable to create thread\n"); | |
467 new_errno = errno; | |
468 goto cleanup; | |
469 } | |
470 | |
471 gg_debug(GG_DEBUG_MISC, "// gg_resolve_pthread() %p\n", tmp); | |
472 | |
473 *resolver = tmp; | |
474 | |
475 *fd = pipes[0]; | |
476 | |
477 return 0; | |
478 | |
479 cleanup: | |
480 if (d) { | |
481 free(d->hostname); | |
482 free(d); | |
483 } | |
484 | |
485 close(pipes[0]); | |
486 close(pipes[1]); | |
487 | |
488 free(tmp); | |
489 | |
490 errno = new_errno; | |
491 | |
492 return -1; | |
493 } | |
494 | |
11546
3c536224f0d0
[gaim-migrate @ 13801]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11360
diff
changeset
|
495 #elif defined _WIN32 |
3c536224f0d0
[gaim-migrate @ 13801]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11360
diff
changeset
|
496 |
3c536224f0d0
[gaim-migrate @ 13801]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11360
diff
changeset
|
497 struct gg_resolve_win32thread_data { |
3c536224f0d0
[gaim-migrate @ 13801]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11360
diff
changeset
|
498 char *hostname; |
3c536224f0d0
[gaim-migrate @ 13801]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11360
diff
changeset
|
499 int fd; |
3c536224f0d0
[gaim-migrate @ 13801]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11360
diff
changeset
|
500 }; |
3c536224f0d0
[gaim-migrate @ 13801]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11360
diff
changeset
|
501 |
3c536224f0d0
[gaim-migrate @ 13801]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11360
diff
changeset
|
502 static DWORD WINAPI gg_resolve_win32thread_thread(LPVOID arg) |
3c536224f0d0
[gaim-migrate @ 13801]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11360
diff
changeset
|
503 { |
3c536224f0d0
[gaim-migrate @ 13801]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11360
diff
changeset
|
504 struct gg_resolve_win32thread_data *d = arg; |
3c536224f0d0
[gaim-migrate @ 13801]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11360
diff
changeset
|
505 struct in_addr a; |
3c536224f0d0
[gaim-migrate @ 13801]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11360
diff
changeset
|
506 |
3c536224f0d0
[gaim-migrate @ 13801]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11360
diff
changeset
|
507 if ((a.s_addr = inet_addr(d->hostname)) == INADDR_NONE) { |
3c536224f0d0
[gaim-migrate @ 13801]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11360
diff
changeset
|
508 struct in_addr *hn; |
3c536224f0d0
[gaim-migrate @ 13801]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11360
diff
changeset
|
509 |
3c536224f0d0
[gaim-migrate @ 13801]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11360
diff
changeset
|
510 if (!(hn = gg_gethostbyname(d->hostname))) |
3c536224f0d0
[gaim-migrate @ 13801]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11360
diff
changeset
|
511 a.s_addr = INADDR_NONE; |
3c536224f0d0
[gaim-migrate @ 13801]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11360
diff
changeset
|
512 else { |
3c536224f0d0
[gaim-migrate @ 13801]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11360
diff
changeset
|
513 a.s_addr = hn->s_addr; |
3c536224f0d0
[gaim-migrate @ 13801]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11360
diff
changeset
|
514 free(hn); |
3c536224f0d0
[gaim-migrate @ 13801]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11360
diff
changeset
|
515 } |
3c536224f0d0
[gaim-migrate @ 13801]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11360
diff
changeset
|
516 } |
3c536224f0d0
[gaim-migrate @ 13801]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11360
diff
changeset
|
517 |
3c536224f0d0
[gaim-migrate @ 13801]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11360
diff
changeset
|
518 write(d->fd, &a, sizeof(a)); |
3c536224f0d0
[gaim-migrate @ 13801]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11360
diff
changeset
|
519 close(d->fd); |
3c536224f0d0
[gaim-migrate @ 13801]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11360
diff
changeset
|
520 |
3c536224f0d0
[gaim-migrate @ 13801]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11360
diff
changeset
|
521 free(d->hostname); |
3c536224f0d0
[gaim-migrate @ 13801]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11360
diff
changeset
|
522 d->hostname = NULL; |
3c536224f0d0
[gaim-migrate @ 13801]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11360
diff
changeset
|
523 |
3c536224f0d0
[gaim-migrate @ 13801]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11360
diff
changeset
|
524 free(d); |
3c536224f0d0
[gaim-migrate @ 13801]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11360
diff
changeset
|
525 |
3c536224f0d0
[gaim-migrate @ 13801]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11360
diff
changeset
|
526 return 0; |
3c536224f0d0
[gaim-migrate @ 13801]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11360
diff
changeset
|
527 } |
3c536224f0d0
[gaim-migrate @ 13801]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11360
diff
changeset
|
528 |
3c536224f0d0
[gaim-migrate @ 13801]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11360
diff
changeset
|
529 |
3c536224f0d0
[gaim-migrate @ 13801]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11360
diff
changeset
|
530 int gg_resolve_win32thread(int *fd, void **resolver, const char *hostname) |
3c536224f0d0
[gaim-migrate @ 13801]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11360
diff
changeset
|
531 { |
3c536224f0d0
[gaim-migrate @ 13801]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11360
diff
changeset
|
532 struct gg_resolve_win32thread_data *d = NULL; |
3c536224f0d0
[gaim-migrate @ 13801]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11360
diff
changeset
|
533 HANDLE h; |
3c536224f0d0
[gaim-migrate @ 13801]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11360
diff
changeset
|
534 DWORD dwTId; |
3c536224f0d0
[gaim-migrate @ 13801]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11360
diff
changeset
|
535 int pipes[2], new_errno; |
3c536224f0d0
[gaim-migrate @ 13801]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11360
diff
changeset
|
536 |
3c536224f0d0
[gaim-migrate @ 13801]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11360
diff
changeset
|
537 gg_debug(GG_DEBUG_FUNCTION, "** gg_resolve_win32thread(%p, %p, \"%s\");\n", fd, resolver, hostname); |
3c536224f0d0
[gaim-migrate @ 13801]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11360
diff
changeset
|
538 |
3c536224f0d0
[gaim-migrate @ 13801]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11360
diff
changeset
|
539 if (!resolver || !fd || !hostname) { |
3c536224f0d0
[gaim-migrate @ 13801]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11360
diff
changeset
|
540 gg_debug(GG_DEBUG_MISC, "// gg_resolve_win32thread() invalid arguments\n"); |
3c536224f0d0
[gaim-migrate @ 13801]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11360
diff
changeset
|
541 errno = EFAULT; |
3c536224f0d0
[gaim-migrate @ 13801]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11360
diff
changeset
|
542 return -1; |
3c536224f0d0
[gaim-migrate @ 13801]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11360
diff
changeset
|
543 } |
3c536224f0d0
[gaim-migrate @ 13801]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11360
diff
changeset
|
544 |
12007
8724718d387f
[gaim-migrate @ 14300]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11546
diff
changeset
|
545 if (socket_pipe(pipes) == -1) { |
11546
3c536224f0d0
[gaim-migrate @ 13801]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11360
diff
changeset
|
546 gg_debug(GG_DEBUG_MISC, "// gg_resolve_win32thread() unable to create pipes (errno=%d, %s)\n", errno, strerror(errno)); |
3c536224f0d0
[gaim-migrate @ 13801]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11360
diff
changeset
|
547 return -1; |
3c536224f0d0
[gaim-migrate @ 13801]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11360
diff
changeset
|
548 } |
3c536224f0d0
[gaim-migrate @ 13801]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11360
diff
changeset
|
549 |
3c536224f0d0
[gaim-migrate @ 13801]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11360
diff
changeset
|
550 if (!(d = malloc(sizeof(*d)))) { |
3c536224f0d0
[gaim-migrate @ 13801]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11360
diff
changeset
|
551 gg_debug(GG_DEBUG_MISC, "// gg_resolve_win32thread() out of memory\n"); |
3c536224f0d0
[gaim-migrate @ 13801]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11360
diff
changeset
|
552 new_errno = GetLastError(); |
3c536224f0d0
[gaim-migrate @ 13801]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11360
diff
changeset
|
553 goto cleanup; |
3c536224f0d0
[gaim-migrate @ 13801]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11360
diff
changeset
|
554 } |
3c536224f0d0
[gaim-migrate @ 13801]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11360
diff
changeset
|
555 |
3c536224f0d0
[gaim-migrate @ 13801]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11360
diff
changeset
|
556 d->hostname = NULL; |
3c536224f0d0
[gaim-migrate @ 13801]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11360
diff
changeset
|
557 |
3c536224f0d0
[gaim-migrate @ 13801]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11360
diff
changeset
|
558 if (!(d->hostname = strdup(hostname))) { |
3c536224f0d0
[gaim-migrate @ 13801]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11360
diff
changeset
|
559 gg_debug(GG_DEBUG_MISC, "// gg_resolve_win32thread() out of memory\n"); |
3c536224f0d0
[gaim-migrate @ 13801]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11360
diff
changeset
|
560 new_errno = GetLastError(); |
3c536224f0d0
[gaim-migrate @ 13801]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11360
diff
changeset
|
561 goto cleanup; |
3c536224f0d0
[gaim-migrate @ 13801]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11360
diff
changeset
|
562 } |
3c536224f0d0
[gaim-migrate @ 13801]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11360
diff
changeset
|
563 |
3c536224f0d0
[gaim-migrate @ 13801]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11360
diff
changeset
|
564 d->fd = pipes[1]; |
3c536224f0d0
[gaim-migrate @ 13801]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11360
diff
changeset
|
565 |
3c536224f0d0
[gaim-migrate @ 13801]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11360
diff
changeset
|
566 h = CreateThread(NULL, 0, gg_resolve_win32thread_thread, |
3c536224f0d0
[gaim-migrate @ 13801]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11360
diff
changeset
|
567 d, 0, &dwTId); |
3c536224f0d0
[gaim-migrate @ 13801]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11360
diff
changeset
|
568 |
3c536224f0d0
[gaim-migrate @ 13801]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11360
diff
changeset
|
569 if (h == NULL) { |
3c536224f0d0
[gaim-migrate @ 13801]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11360
diff
changeset
|
570 gg_debug(GG_DEBUG_MISC, "// gg_resolve_win32thread() unable to create thread\n"); |
3c536224f0d0
[gaim-migrate @ 13801]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11360
diff
changeset
|
571 new_errno = GetLastError(); |
3c536224f0d0
[gaim-migrate @ 13801]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11360
diff
changeset
|
572 goto cleanup; |
3c536224f0d0
[gaim-migrate @ 13801]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11360
diff
changeset
|
573 } |
3c536224f0d0
[gaim-migrate @ 13801]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11360
diff
changeset
|
574 |
3c536224f0d0
[gaim-migrate @ 13801]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11360
diff
changeset
|
575 *resolver = h; |
3c536224f0d0
[gaim-migrate @ 13801]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11360
diff
changeset
|
576 *fd = pipes[0]; |
3c536224f0d0
[gaim-migrate @ 13801]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11360
diff
changeset
|
577 |
3c536224f0d0
[gaim-migrate @ 13801]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11360
diff
changeset
|
578 return 0; |
3c536224f0d0
[gaim-migrate @ 13801]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11360
diff
changeset
|
579 |
3c536224f0d0
[gaim-migrate @ 13801]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11360
diff
changeset
|
580 cleanup: |
3c536224f0d0
[gaim-migrate @ 13801]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11360
diff
changeset
|
581 if (d) { |
3c536224f0d0
[gaim-migrate @ 13801]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11360
diff
changeset
|
582 free(d->hostname); |
3c536224f0d0
[gaim-migrate @ 13801]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11360
diff
changeset
|
583 free(d); |
3c536224f0d0
[gaim-migrate @ 13801]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11360
diff
changeset
|
584 } |
3c536224f0d0
[gaim-migrate @ 13801]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11360
diff
changeset
|
585 |
3c536224f0d0
[gaim-migrate @ 13801]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11360
diff
changeset
|
586 close(pipes[0]); |
3c536224f0d0
[gaim-migrate @ 13801]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11360
diff
changeset
|
587 close(pipes[1]); |
3c536224f0d0
[gaim-migrate @ 13801]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11360
diff
changeset
|
588 |
3c536224f0d0
[gaim-migrate @ 13801]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11360
diff
changeset
|
589 errno = new_errno; |
3c536224f0d0
[gaim-migrate @ 13801]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11360
diff
changeset
|
590 |
3c536224f0d0
[gaim-migrate @ 13801]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11360
diff
changeset
|
591 return -1; |
3c536224f0d0
[gaim-migrate @ 13801]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11360
diff
changeset
|
592 |
3c536224f0d0
[gaim-migrate @ 13801]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11360
diff
changeset
|
593 } |
11360 | 594 #endif |
595 | |
596 /* | |
597 * gg_read() // funkcja pomocnicza | |
598 * | |
599 * czyta z gniazda określoną ilość bajtów. bierze pod uwagę, czy mamy | |
600 * połączenie zwykłe czy TLS. | |
601 * | |
602 * - sess - sesja, | |
603 * - buf - bufor, | |
604 * - length - ilość bajtów, | |
605 * | |
606 * takie same wartości jak read(). | |
607 */ | |
608 int gg_read(struct gg_session *sess, char *buf, int length) | |
609 { | |
610 int res; | |
611 | |
612 #ifdef __GG_LIBGADU_HAVE_OPENSSL | |
613 if (sess->ssl) { | |
614 int err; | |
615 | |
616 res = SSL_read(sess->ssl, buf, length); | |
617 | |
618 if (res < 0) { | |
619 err = SSL_get_error(sess->ssl, res); | |
620 | |
621 if (err == SSL_ERROR_WANT_READ) | |
622 errno = EAGAIN; | |
623 | |
624 return -1; | |
625 } | |
626 } else | |
627 #endif | |
628 res = read(sess->fd, buf, length); | |
629 | |
630 return res; | |
631 } | |
632 | |
633 /* | |
634 * gg_write() // funkcja pomocnicza | |
635 * | |
636 * zapisuje do gniazda określoną ilość bajtów. bierze pod uwagę, czy mamy | |
637 * połączenie zwykłe czy TLS. | |
638 * | |
639 * - sess - sesja, | |
640 * - buf - bufor, | |
641 * - length - ilość bajtów, | |
642 * | |
643 * takie same wartości jak write(). | |
644 */ | |
645 int gg_write(struct gg_session *sess, const char *buf, int length) | |
646 { | |
647 int res = 0; | |
648 | |
649 #ifdef __GG_LIBGADU_HAVE_OPENSSL | |
650 if (sess->ssl) { | |
651 int err; | |
652 | |
653 res = SSL_write(sess->ssl, buf, length); | |
654 | |
655 if (res < 0) { | |
656 err = SSL_get_error(sess->ssl, res); | |
657 | |
658 if (err == SSL_ERROR_WANT_WRITE) | |
659 errno = EAGAIN; | |
660 | |
661 return -1; | |
662 } | |
663 } else | |
664 #endif | |
665 { | |
666 int written = 0; | |
667 | |
668 while (written < length) { | |
669 res = write(sess->fd, buf + written, length - written); | |
670 | |
671 if (res == -1) { | |
672 if (errno == EAGAIN) | |
673 continue; | |
674 else | |
675 break; | |
676 } else { | |
677 written += res; | |
678 res = written; | |
679 } | |
680 } | |
681 } | |
682 | |
683 return res; | |
684 } | |
685 | |
686 /* | |
687 * gg_recv_packet() // funkcja wewnętrzna | |
688 * | |
689 * odbiera jeden pakiet i zwraca wskaźnik do niego. pamięć po nim | |
690 * należy zwolnić za pomocą free(). | |
691 * | |
692 * - sess - opis sesji | |
693 * | |
694 * w przypadku błędu NULL, kod błędu w errno. należy zwrócić uwagę, że gdy | |
695 * połączenie jest nieblokujące, a kod błędu wynosi EAGAIN, nie udało się | |
696 * odczytać całego pakietu i nie należy tego traktować jako błąd. | |
697 */ | |
698 void *gg_recv_packet(struct gg_session *sess) | |
699 { | |
700 struct gg_header h; | |
701 char *buf = NULL; | |
702 int ret = 0; | |
703 unsigned int offset, size = 0; | |
704 | |
705 gg_debug(GG_DEBUG_FUNCTION, "** gg_recv_packet(%p);\n", sess); | |
706 | |
707 if (!sess) { | |
708 errno = EFAULT; | |
709 return NULL; | |
710 } | |
711 | |
712 if (sess->recv_left < 1) { | |
713 if (sess->header_buf) { | |
714 memcpy(&h, sess->header_buf, sess->header_done); | |
715 gg_debug(GG_DEBUG_MISC, "// gg_recv_packet() header recv: resuming last read (%d bytes left)\n", sizeof(h) - sess->header_done); | |
716 free(sess->header_buf); | |
717 sess->header_buf = NULL; | |
718 } else | |
719 sess->header_done = 0; | |
720 | |
721 while (sess->header_done < sizeof(h)) { | |
722 ret = gg_read(sess, (char*) &h + sess->header_done, sizeof(h) - sess->header_done); | |
723 | |
724 gg_debug(GG_DEBUG_MISC, "// gg_recv_packet() header recv(%d,%p,%d) = %d\n", sess->fd, &h + sess->header_done, sizeof(h) - sess->header_done, ret); | |
725 | |
726 if (!ret) { | |
727 errno = ECONNRESET; | |
728 gg_debug(GG_DEBUG_MISC, "// gg_recv_packet() header recv() failed: connection broken\n"); | |
729 return NULL; | |
730 } | |
731 | |
732 if (ret == -1) { | |
733 if (errno == EINTR) { | |
734 gg_debug(GG_DEBUG_MISC, "// gg_recv_packet() header recv() interrupted system call, resuming\n"); | |
735 continue; | |
736 } | |
737 | |
738 if (errno == EAGAIN) { | |
739 gg_debug(GG_DEBUG_MISC, "// gg_recv_packet() header recv() incomplete header received\n"); | |
740 | |
741 if (!(sess->header_buf = malloc(sess->header_done))) { | |
742 gg_debug(GG_DEBUG_MISC, "// gg_recv_packet() header recv() not enough memory\n"); | |
743 return NULL; | |
744 } | |
745 | |
746 memcpy(sess->header_buf, &h, sess->header_done); | |
747 | |
748 return NULL; | |
749 } | |
750 | |
751 gg_debug(GG_DEBUG_MISC, "// gg_recv_packet() header recv() failed: errno=%d, %s\n", errno, strerror(errno)); | |
752 | |
753 return NULL; | |
754 } | |
755 | |
756 sess->header_done += ret; | |
757 | |
758 } | |
759 | |
760 h.type = gg_fix32(h.type); | |
761 h.length = gg_fix32(h.length); | |
762 } else | |
763 memcpy(&h, sess->recv_buf, sizeof(h)); | |
764 | |
765 /* jakieś sensowne limity na rozmiar pakietu */ | |
766 if (h.length > 65535) { | |
767 gg_debug(GG_DEBUG_MISC, "// gg_recv_packet() invalid packet length (%d)\n", h.length); | |
768 errno = ERANGE; | |
769 return NULL; | |
770 } | |
771 | |
772 if (sess->recv_left > 0) { | |
773 gg_debug(GG_DEBUG_MISC, "// gg_recv_packet() resuming last gg_recv_packet()\n"); | |
774 size = sess->recv_left; | |
775 offset = sess->recv_done; | |
776 buf = sess->recv_buf; | |
777 } else { | |
778 if (!(buf = malloc(sizeof(h) + h.length + 1))) { | |
779 gg_debug(GG_DEBUG_MISC, "// gg_recv_packet() not enough memory for packet data\n"); | |
780 return NULL; | |
781 } | |
782 | |
783 memcpy(buf, &h, sizeof(h)); | |
784 | |
785 offset = 0; | |
786 size = h.length; | |
787 } | |
788 | |
789 while (size > 0) { | |
790 ret = gg_read(sess, buf + sizeof(h) + offset, size); | |
791 gg_debug(GG_DEBUG_MISC, "// gg_recv_packet() body recv(%d,%p,%d) = %d\n", sess->fd, buf + sizeof(h) + offset, size, ret); | |
792 if (!ret) { | |
793 gg_debug(GG_DEBUG_MISC, "// gg_recv_packet() body recv() failed: connection broken\n"); | |
794 errno = ECONNRESET; | |
795 return NULL; | |
796 } | |
797 if (ret > -1 && ret <= size) { | |
798 offset += ret; | |
799 size -= ret; | |
800 } else if (ret == -1) { | |
801 int errno2 = errno; | |
802 | |
803 gg_debug(GG_DEBUG_MISC, "// gg_recv_packet() body recv() failed (errno=%d, %s)\n", errno, strerror(errno)); | |
804 errno = errno2; | |
805 | |
806 if (errno == EAGAIN) { | |
807 gg_debug(GG_DEBUG_MISC, "// gg_recv_packet() %d bytes received, %d left\n", offset, size); | |
808 sess->recv_buf = buf; | |
809 sess->recv_left = size; | |
810 sess->recv_done = offset; | |
811 return NULL; | |
812 } | |
813 if (errno != EINTR) { | |
814 free(buf); | |
815 return NULL; | |
816 } | |
817 } | |
818 } | |
819 | |
820 sess->recv_left = 0; | |
821 | |
822 if ((gg_debug_level & GG_DEBUG_DUMP)) { | |
823 unsigned int i; | |
824 | |
825 gg_debug(GG_DEBUG_DUMP, "// gg_recv_packet(%.2x)", h.type); | |
826 for (i = 0; i < sizeof(h) + h.length; i++) | |
827 gg_debug(GG_DEBUG_DUMP, " %.2x", (unsigned char) buf[i]); | |
828 gg_debug(GG_DEBUG_DUMP, "\n"); | |
829 } | |
830 | |
831 return buf; | |
832 } | |
833 | |
834 /* | |
835 * gg_send_packet() // funkcja wewnętrzna | |
836 * | |
837 * konstruuje pakiet i wysyła go do serwera. | |
838 * | |
839 * - sock - deskryptor gniazda | |
840 * - type - typ pakietu | |
841 * - payload_1 - pierwsza część pakietu | |
842 * - payload_length_1 - długość pierwszej części | |
843 * - payload_2 - druga część pakietu | |
844 * - payload_length_2 - długość drugiej części | |
845 * - ... - kolejne części pakietu i ich długości | |
846 * - NULL - końcowym parametr (konieczny!) | |
847 * | |
848 * jeśli się powiodło, zwraca 0, w przypadku błędu -1. jeśli errno == ENOMEM, | |
849 * zabrakło pamięci. inaczej był błąd przy wysyłaniu pakietu. dla errno == 0 | |
850 * nie wysłano całego pakietu. | |
851 */ | |
852 int gg_send_packet(struct gg_session *sess, int type, ...) | |
853 { | |
854 struct gg_header *h; | |
855 char *tmp; | |
856 unsigned int tmp_length; | |
857 void *payload; | |
858 unsigned int payload_length; | |
859 va_list ap; | |
860 int res; | |
861 | |
862 gg_debug(GG_DEBUG_FUNCTION, "** gg_send_packet(%p, 0x%.2x, ...)\n", sess, type); | |
863 | |
864 tmp_length = sizeof(struct gg_header); | |
865 | |
866 if (!(tmp = malloc(tmp_length))) { | |
867 gg_debug(GG_DEBUG_MISC, "// gg_send_packet() not enough memory for packet header\n"); | |
868 return -1; | |
869 } | |
870 | |
871 va_start(ap, type); | |
872 | |
873 payload = va_arg(ap, void *); | |
874 | |
875 while (payload) { | |
876 char *tmp2; | |
877 | |
878 payload_length = va_arg(ap, unsigned int); | |
879 | |
880 if (!(tmp2 = realloc(tmp, tmp_length + payload_length))) { | |
881 gg_debug(GG_DEBUG_MISC, "// gg_send_packet() not enough memory for payload\n"); | |
882 free(tmp); | |
883 va_end(ap); | |
884 return -1; | |
885 } | |
886 | |
887 tmp = tmp2; | |
888 | |
889 memcpy(tmp + tmp_length, payload, payload_length); | |
890 tmp_length += payload_length; | |
891 | |
892 payload = va_arg(ap, void *); | |
893 } | |
894 | |
895 va_end(ap); | |
896 | |
897 h = (struct gg_header*) tmp; | |
898 h->type = gg_fix32(type); | |
899 h->length = gg_fix32(tmp_length - sizeof(struct gg_header)); | |
900 | |
901 if ((gg_debug_level & GG_DEBUG_DUMP)) { | |
902 unsigned int i; | |
903 | |
904 gg_debug(GG_DEBUG_DUMP, "// gg_send_packet(0x%.2x)", gg_fix32(h->type)); | |
905 for (i = 0; i < tmp_length; ++i) | |
906 gg_debug(GG_DEBUG_DUMP, " %.2x", (unsigned char) tmp[i]); | |
907 gg_debug(GG_DEBUG_DUMP, "\n"); | |
908 } | |
909 | |
910 if ((res = gg_write(sess, tmp, tmp_length)) < tmp_length) { | |
911 gg_debug(GG_DEBUG_MISC, "// gg_send_packet() write() failed. res = %d, errno = %d (%s)\n", res, errno, strerror(errno)); | |
912 free(tmp); | |
913 return -1; | |
914 } | |
915 | |
916 free(tmp); | |
917 return 0; | |
918 } | |
919 | |
920 /* | |
921 * gg_session_callback() // funkcja wewnętrzna | |
922 * | |
923 * wywoływany z gg_session->callback, wykonuje gg_watch_fd() i pakuje | |
924 * do gg_session->event jego wynik. | |
925 */ | |
926 static int gg_session_callback(struct gg_session *s) | |
927 { | |
928 if (!s) { | |
929 errno = EFAULT; | |
930 return -1; | |
931 } | |
932 | |
933 return ((s->event = gg_watch_fd(s)) != NULL) ? 0 : -1; | |
934 } | |
935 | |
936 /* | |
937 * gg_login() | |
938 * | |
939 * rozpoczyna procedurę łączenia się z serwerem. resztę obsługuje się przez | |
940 * gg_watch_fd(). | |
941 * | |
942 * UWAGA! program musi obsłużyć SIGCHLD, jeśli łączy się asynchronicznie, | |
943 * żeby poprawnie zamknąć proces resolvera. | |
944 * | |
945 * - p - struktura opisująca początkowy stan. wymagane pola: uin, | |
946 * password | |
947 * | |
948 * w przypadku błędu NULL, jeśli idzie dobrze (async) albo poszło | |
949 * dobrze (sync), zwróci wskaźnik do zaalokowanej struct gg_session. | |
950 */ | |
951 struct gg_session *gg_login(const struct gg_login_params *p) | |
952 { | |
953 struct gg_session *sess = NULL; | |
954 char *hostname; | |
955 int port; | |
956 | |
957 if (!p) { | |
958 gg_debug(GG_DEBUG_FUNCTION, "** gg_login(%p);\n", p); | |
959 errno = EFAULT; | |
960 return NULL; | |
961 } | |
962 | |
963 gg_debug(GG_DEBUG_FUNCTION, "** gg_login(%p: [uin=%u, async=%d, ...]);\n", p, p->uin, p->async); | |
964 | |
965 if (!(sess = malloc(sizeof(struct gg_session)))) { | |
966 gg_debug(GG_DEBUG_MISC, "// gg_login() not enough memory for session data\n"); | |
967 goto fail; | |
968 } | |
969 | |
970 memset(sess, 0, sizeof(struct gg_session)); | |
971 | |
972 if (!p->password || !p->uin) { | |
973 gg_debug(GG_DEBUG_MISC, "// gg_login() invalid arguments. uin and password needed\n"); | |
974 errno = EFAULT; | |
975 goto fail; | |
976 } | |
977 | |
978 if (!(sess->password = strdup(p->password))) { | |
979 gg_debug(GG_DEBUG_MISC, "// gg_login() not enough memory for password\n"); | |
980 goto fail; | |
981 } | |
982 | |
983 if (p->status_descr && !(sess->initial_descr = strdup(p->status_descr))) { | |
984 gg_debug(GG_DEBUG_MISC, "// gg_login() not enough memory for status\n"); | |
985 goto fail; | |
986 } | |
987 | |
988 sess->uin = p->uin; | |
989 sess->state = GG_STATE_RESOLVING; | |
990 sess->check = GG_CHECK_READ; | |
991 sess->timeout = GG_DEFAULT_TIMEOUT; | |
992 sess->async = p->async; | |
993 sess->type = GG_SESSION_GG; | |
994 sess->initial_status = p->status; | |
995 sess->callback = gg_session_callback; | |
996 sess->destroy = gg_free_session; | |
997 sess->port = (p->server_port) ? p->server_port : ((gg_proxy_enabled) ? GG_HTTPS_PORT : GG_DEFAULT_PORT); | |
998 sess->server_addr = p->server_addr; | |
999 sess->external_port = p->external_port; | |
1000 sess->external_addr = p->external_addr; | |
1001 sess->protocol_version = (p->protocol_version) ? p->protocol_version : GG_DEFAULT_PROTOCOL_VERSION; | |
1002 if (p->era_omnix) | |
1003 sess->protocol_version |= GG_ERA_OMNIX_MASK; | |
1004 if (p->has_audio) | |
1005 sess->protocol_version |= GG_HAS_AUDIO_MASK; | |
1006 sess->client_version = (p->client_version) ? strdup(p->client_version) : NULL; | |
1007 sess->last_sysmsg = p->last_sysmsg; | |
1008 sess->image_size = p->image_size; | |
1009 sess->pid = -1; | |
1010 | |
1011 if (p->tls == 1) { | |
1012 #ifdef __GG_LIBGADU_HAVE_OPENSSL | |
1013 char buf[1024]; | |
1014 | |
1015 OpenSSL_add_ssl_algorithms(); | |
1016 | |
1017 if (!RAND_status()) { | |
1018 char rdata[1024]; | |
1019 struct { | |
1020 time_t time; | |
1021 void *ptr; | |
1022 } rstruct; | |
1023 | |
1024 time(&rstruct.time); | |
1025 rstruct.ptr = (void *) &rstruct; | |
1026 | |
1027 RAND_seed((void *) rdata, sizeof(rdata)); | |
1028 RAND_seed((void *) &rstruct, sizeof(rstruct)); | |
1029 } | |
1030 | |
1031 sess->ssl_ctx = SSL_CTX_new(TLSv1_client_method()); | |
1032 | |
1033 if (!sess->ssl_ctx) { | |
1034 ERR_error_string_n(ERR_get_error(), buf, sizeof(buf)); | |
1035 gg_debug(GG_DEBUG_MISC, "// gg_login() SSL_CTX_new() failed: %s\n", buf); | |
1036 goto fail; | |
1037 } | |
1038 | |
1039 SSL_CTX_set_verify(sess->ssl_ctx, SSL_VERIFY_NONE, NULL); | |
1040 | |
1041 sess->ssl = SSL_new(sess->ssl_ctx); | |
1042 | |
1043 if (!sess->ssl) { | |
1044 ERR_error_string_n(ERR_get_error(), buf, sizeof(buf)); | |
1045 gg_debug(GG_DEBUG_MISC, "// gg_login() SSL_new() failed: %s\n", buf); | |
1046 goto fail; | |
1047 } | |
1048 #else | |
1049 gg_debug(GG_DEBUG_MISC, "// gg_login() client requested TLS but no support compiled in\n"); | |
1050 #endif | |
1051 } | |
1052 | |
1053 if (gg_proxy_enabled) { | |
1054 hostname = gg_proxy_host; | |
1055 sess->proxy_port = port = gg_proxy_port; | |
1056 } else { | |
1057 hostname = GG_APPMSG_HOST; | |
1058 port = GG_APPMSG_PORT; | |
1059 } | |
1060 | |
1061 if (!p->async) { | |
1062 struct in_addr a; | |
1063 | |
1064 if (!p->server_addr || !p->server_port) { | |
1065 if ((a.s_addr = inet_addr(hostname)) == INADDR_NONE) { | |
1066 struct in_addr *hn; | |
1067 | |
1068 if (!(hn = gg_gethostbyname(hostname))) { | |
1069 gg_debug(GG_DEBUG_MISC, "// gg_login() host \"%s\" not found\n", hostname); | |
1070 goto fail; | |
1071 } else { | |
1072 a.s_addr = hn->s_addr; | |
1073 free(hn); | |
1074 } | |
1075 } | |
1076 } else { | |
1077 a.s_addr = p->server_addr; | |
1078 port = p->server_port; | |
1079 } | |
1080 | |
1081 sess->hub_addr = a.s_addr; | |
1082 | |
1083 if (gg_proxy_enabled) | |
1084 sess->proxy_addr = a.s_addr; | |
1085 | |
1086 if ((sess->fd = gg_connect(&a, port, 0)) == -1) { | |
1087 gg_debug(GG_DEBUG_MISC, "// gg_login() connection failed (errno=%d, %s)\n", errno, strerror(errno)); | |
1088 goto fail; | |
1089 } | |
1090 | |
1091 if (p->server_addr && p->server_port) | |
1092 sess->state = GG_STATE_CONNECTING_GG; | |
1093 else | |
1094 sess->state = GG_STATE_CONNECTING_HUB; | |
1095 | |
1096 while (sess->state != GG_STATE_CONNECTED) { | |
1097 struct gg_event *e; | |
1098 | |
1099 if (!(e = gg_watch_fd(sess))) { | |
1100 gg_debug(GG_DEBUG_MISC, "// gg_login() critical error in gg_watch_fd()\n"); | |
1101 goto fail; | |
1102 } | |
1103 | |
1104 if (e->type == GG_EVENT_CONN_FAILED) { | |
1105 errno = EACCES; | |
1106 gg_debug(GG_DEBUG_MISC, "// gg_login() could not login\n"); | |
1107 gg_event_free(e); | |
1108 goto fail; | |
1109 } | |
1110 | |
1111 gg_event_free(e); | |
1112 } | |
1113 | |
1114 return sess; | |
1115 } | |
1116 | |
1117 if (!sess->server_addr || gg_proxy_enabled) { | |
11546
3c536224f0d0
[gaim-migrate @ 13801]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11360
diff
changeset
|
1118 #ifdef __GG_LIBGADU_HAVE_PTHREAD |
3c536224f0d0
[gaim-migrate @ 13801]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11360
diff
changeset
|
1119 if (gg_resolve_pthread(&sess->fd, &sess->resolver, hostname)) { |
3c536224f0d0
[gaim-migrate @ 13801]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11360
diff
changeset
|
1120 #elif defined _WIN32 |
3c536224f0d0
[gaim-migrate @ 13801]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11360
diff
changeset
|
1121 if (gg_resolve_win32thread(&sess->fd, &sess->resolver, hostname)) { |
3c536224f0d0
[gaim-migrate @ 13801]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11360
diff
changeset
|
1122 #else |
11360 | 1123 if (gg_resolve(&sess->fd, &sess->pid, hostname)) { |
1124 #endif | |
1125 gg_debug(GG_DEBUG_MISC, "// gg_login() resolving failed (errno=%d, %s)\n", errno, strerror(errno)); | |
1126 goto fail; | |
1127 } | |
1128 } else { | |
1129 if ((sess->fd = gg_connect(&sess->server_addr, sess->port, sess->async)) == -1) { | |
1130 gg_debug(GG_DEBUG_MISC, "// gg_login() direct connection failed (errno=%d, %s)\n", errno, strerror(errno)); | |
1131 goto fail; | |
1132 } | |
1133 sess->state = GG_STATE_CONNECTING_GG; | |
1134 sess->check = GG_CHECK_WRITE; | |
1135 } | |
1136 | |
1137 return sess; | |
1138 | |
1139 fail: | |
1140 if (sess) { | |
1141 if (sess->password) | |
1142 free(sess->password); | |
1143 if (sess->initial_descr) | |
1144 free(sess->initial_descr); | |
1145 free(sess); | |
1146 } | |
1147 | |
1148 return NULL; | |
1149 } | |
1150 | |
1151 /* | |
1152 * gg_free_session() | |
1153 * | |
1154 * próbuje zamknąć połączenia i zwalnia pamięć zajmowaną przez sesję. | |
1155 * | |
1156 * - sess - opis sesji | |
1157 */ | |
1158 void gg_free_session(struct gg_session *sess) | |
1159 { | |
1160 if (!sess) | |
1161 return; | |
1162 | |
1163 /* XXX dopisać zwalnianie i zamykanie wszystkiego, co mogło zostać */ | |
1164 | |
1165 if (sess->password) | |
1166 free(sess->password); | |
1167 | |
1168 if (sess->initial_descr) | |
1169 free(sess->initial_descr); | |
1170 | |
1171 if (sess->client_version) | |
1172 free(sess->client_version); | |
1173 | |
1174 if (sess->header_buf) | |
1175 free(sess->header_buf); | |
1176 | |
1177 #ifdef __GG_LIBGADU_HAVE_OPENSSL | |
1178 if (sess->ssl) | |
1179 SSL_free(sess->ssl); | |
1180 | |
1181 if (sess->ssl_ctx) | |
1182 SSL_CTX_free(sess->ssl_ctx); | |
1183 #endif | |
1184 | |
1185 #ifdef __GG_LIBGADU_HAVE_PTHREAD | |
1186 if (sess->resolver) { | |
1187 pthread_cancel(*((pthread_t*) sess->resolver)); | |
1188 free(sess->resolver); | |
1189 sess->resolver = NULL; | |
1190 } | |
11546
3c536224f0d0
[gaim-migrate @ 13801]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11360
diff
changeset
|
1191 #elif defined _WIN32 |
3c536224f0d0
[gaim-migrate @ 13801]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11360
diff
changeset
|
1192 if (sess->resolver) { |
3c536224f0d0
[gaim-migrate @ 13801]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11360
diff
changeset
|
1193 HANDLE h = sess->resolver; |
3c536224f0d0
[gaim-migrate @ 13801]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11360
diff
changeset
|
1194 TerminateThread(h, 0); |
3c536224f0d0
[gaim-migrate @ 13801]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11360
diff
changeset
|
1195 CloseHandle(h); |
3c536224f0d0
[gaim-migrate @ 13801]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11360
diff
changeset
|
1196 sess->resolver = NULL; |
3c536224f0d0
[gaim-migrate @ 13801]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11360
diff
changeset
|
1197 } |
11360 | 1198 #else |
1199 if (sess->pid != -1) | |
1200 waitpid(sess->pid, NULL, WNOHANG); | |
1201 #endif | |
1202 | |
1203 if (sess->fd != -1) | |
1204 close(sess->fd); | |
1205 | |
1206 while (sess->images) | |
1207 gg_image_queue_remove(sess, sess->images, 1); | |
1208 | |
1209 free(sess); | |
1210 } | |
1211 | |
1212 /* | |
1213 * gg_change_status() | |
1214 * | |
1215 * zmienia status użytkownika. przydatne do /away i /busy oraz /quit. | |
1216 * | |
1217 * - sess - opis sesji | |
1218 * - status - nowy status użytkownika | |
1219 * | |
1220 * 0, -1. | |
1221 */ | |
1222 int gg_change_status(struct gg_session *sess, int status) | |
1223 { | |
1224 struct gg_new_status p; | |
1225 | |
1226 gg_debug(GG_DEBUG_FUNCTION, "** gg_change_status(%p, %d);\n", sess, status); | |
1227 | |
1228 if (!sess) { | |
1229 errno = EFAULT; | |
1230 return -1; | |
1231 } | |
1232 | |
1233 if (sess->state != GG_STATE_CONNECTED) { | |
1234 errno = ENOTCONN; | |
1235 return -1; | |
1236 } | |
1237 | |
1238 p.status = gg_fix32(status); | |
1239 | |
1240 sess->status = status; | |
1241 | |
1242 return gg_send_packet(sess, GG_NEW_STATUS, &p, sizeof(p), NULL); | |
1243 } | |
1244 | |
1245 /* | |
1246 * gg_change_status_descr() | |
1247 * | |
1248 * zmienia status użytkownika na opisowy. | |
1249 * | |
1250 * - sess - opis sesji | |
1251 * - status - nowy status użytkownika | |
1252 * - descr - opis statusu | |
1253 * | |
1254 * 0, -1. | |
1255 */ | |
1256 int gg_change_status_descr(struct gg_session *sess, int status, const char *descr) | |
1257 { | |
1258 struct gg_new_status p; | |
1259 | |
1260 gg_debug(GG_DEBUG_FUNCTION, "** gg_change_status_descr(%p, %d, \"%s\");\n", sess, status, descr); | |
1261 | |
1262 if (!sess || !descr) { | |
1263 errno = EFAULT; | |
1264 return -1; | |
1265 } | |
1266 | |
1267 if (sess->state != GG_STATE_CONNECTED) { | |
1268 errno = ENOTCONN; | |
1269 return -1; | |
1270 } | |
1271 | |
1272 p.status = gg_fix32(status); | |
1273 | |
1274 sess->status = status; | |
1275 | |
1276 return gg_send_packet(sess, GG_NEW_STATUS, &p, sizeof(p), descr, (strlen(descr) > GG_STATUS_DESCR_MAXSIZE) ? GG_STATUS_DESCR_MAXSIZE : strlen(descr), NULL); | |
1277 } | |
1278 | |
1279 /* | |
1280 * gg_change_status_descr_time() | |
1281 * | |
1282 * zmienia status użytkownika na opisowy z godziną powrotu. | |
1283 * | |
1284 * - sess - opis sesji | |
1285 * - status - nowy status użytkownika | |
1286 * - descr - opis statusu | |
1287 * - time - czas w formacie uniksowym | |
1288 * | |
1289 * 0, -1. | |
1290 */ | |
1291 int gg_change_status_descr_time(struct gg_session *sess, int status, const char *descr, int time) | |
1292 { | |
1293 struct gg_new_status p; | |
1294 uint32_t newtime; | |
1295 | |
1296 gg_debug(GG_DEBUG_FUNCTION, "** gg_change_status_descr_time(%p, %d, \"%s\", %d);\n", sess, status, descr, time); | |
1297 | |
1298 if (!sess || !descr || !time) { | |
1299 errno = EFAULT; | |
1300 return -1; | |
1301 } | |
1302 | |
1303 if (sess->state != GG_STATE_CONNECTED) { | |
1304 errno = ENOTCONN; | |
1305 return -1; | |
1306 } | |
1307 | |
1308 p.status = gg_fix32(status); | |
1309 | |
1310 sess->status = status; | |
1311 | |
1312 newtime = gg_fix32(time); | |
1313 | |
1314 return gg_send_packet(sess, GG_NEW_STATUS, &p, sizeof(p), descr, (strlen(descr) > GG_STATUS_DESCR_MAXSIZE) ? GG_STATUS_DESCR_MAXSIZE : strlen(descr), &newtime, sizeof(newtime), NULL); | |
1315 } | |
1316 | |
1317 /* | |
1318 * gg_logoff() | |
1319 * | |
1320 * wylogowuje użytkownika i zamyka połączenie, ale nie zwalnia pamięci. | |
1321 * | |
1322 * - sess - opis sesji | |
1323 */ | |
1324 void gg_logoff(struct gg_session *sess) | |
1325 { | |
1326 if (!sess) | |
1327 return; | |
1328 | |
1329 gg_debug(GG_DEBUG_FUNCTION, "** gg_logoff(%p);\n", sess); | |
1330 | |
1331 if (GG_S_NA(sess->status & ~GG_STATUS_FRIENDS_MASK)) | |
1332 gg_change_status(sess, GG_STATUS_NOT_AVAIL); | |
1333 | |
1334 #ifdef __GG_LIBGADU_HAVE_OPENSSL | |
1335 if (sess->ssl) | |
1336 SSL_shutdown(sess->ssl); | |
1337 #endif | |
1338 | |
1339 #ifdef __GG_LIBGADU_HAVE_PTHREAD | |
1340 if (sess->resolver) { | |
1341 pthread_cancel(*((pthread_t*) sess->resolver)); | |
1342 free(sess->resolver); | |
1343 sess->resolver = NULL; | |
1344 } | |
11546
3c536224f0d0
[gaim-migrate @ 13801]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11360
diff
changeset
|
1345 #elif defined _WIN32 |
3c536224f0d0
[gaim-migrate @ 13801]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11360
diff
changeset
|
1346 if (sess->resolver) { |
3c536224f0d0
[gaim-migrate @ 13801]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11360
diff
changeset
|
1347 HANDLE h = sess->resolver; |
3c536224f0d0
[gaim-migrate @ 13801]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11360
diff
changeset
|
1348 TerminateThread(h, 0); |
3c536224f0d0
[gaim-migrate @ 13801]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11360
diff
changeset
|
1349 CloseHandle(h); |
3c536224f0d0
[gaim-migrate @ 13801]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11360
diff
changeset
|
1350 sess->resolver = NULL; |
3c536224f0d0
[gaim-migrate @ 13801]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11360
diff
changeset
|
1351 } |
11360 | 1352 #else |
1353 if (sess->pid != -1) { | |
1354 waitpid(sess->pid, NULL, WNOHANG); | |
1355 sess->pid = -1; | |
1356 } | |
1357 #endif | |
1358 | |
1359 if (sess->fd != -1) { | |
1360 shutdown(sess->fd, SHUT_RDWR); | |
1361 close(sess->fd); | |
1362 sess->fd = -1; | |
1363 } | |
1364 } | |
1365 | |
1366 /* | |
1367 * gg_image_request() | |
1368 * | |
1369 * wysyła żądanie wysłania obrazka o podanych parametrach. | |
1370 * | |
1371 * - sess - opis sesji | |
1372 * - recipient - numer adresata | |
1373 * - size - rozmiar obrazka | |
1374 * - crc32 - suma kontrolna obrazka | |
1375 * | |
1376 * 0/-1 | |
1377 */ | |
1378 int gg_image_request(struct gg_session *sess, uin_t recipient, int size, uint32_t crc32) | |
1379 { | |
1380 struct gg_send_msg s; | |
1381 struct gg_msg_image_request r; | |
1382 char dummy = 0; | |
1383 int res; | |
1384 | |
1385 gg_debug(GG_DEBUG_FUNCTION, "** gg_image_request(%p, %d, %u, 0x%.4x);\n", sess, recipient, size, crc32); | |
1386 | |
1387 if (!sess) { | |
1388 errno = EFAULT; | |
1389 return -1; | |
1390 } | |
1391 | |
1392 if (sess->state != GG_STATE_CONNECTED) { | |
1393 errno = ENOTCONN; | |
1394 return -1; | |
1395 } | |
1396 | |
1397 if (size < 0) { | |
1398 errno = EINVAL; | |
1399 return -1; | |
1400 } | |
1401 | |
1402 s.recipient = gg_fix32(recipient); | |
1403 s.seq = gg_fix32(0); | |
1404 s.msgclass = gg_fix32(GG_CLASS_MSG); | |
1405 | |
1406 r.flag = 0x04; | |
1407 r.size = gg_fix32(size); | |
1408 r.crc32 = gg_fix32(crc32); | |
1409 | |
1410 res = gg_send_packet(sess, GG_SEND_MSG, &s, sizeof(s), &dummy, 1, &r, sizeof(r), NULL); | |
1411 | |
1412 if (!res) { | |
1413 struct gg_image_queue *q = malloc(sizeof(*q)); | |
1414 char *buf; | |
1415 | |
1416 if (!q) { | |
1417 gg_debug(GG_DEBUG_MISC, "// gg_image_request() not enough memory for image queue\n"); | |
1418 return -1; | |
1419 } | |
1420 | |
1421 buf = malloc(size); | |
1422 if (size && !buf) | |
1423 { | |
1424 gg_debug(GG_DEBUG_MISC, "// gg_image_request() not enough memory for image\n"); | |
1425 free(q); | |
1426 return -1; | |
1427 } | |
1428 | |
1429 memset(q, 0, sizeof(*q)); | |
1430 | |
1431 q->sender = recipient; | |
1432 q->size = size; | |
1433 q->crc32 = crc32; | |
1434 q->image = buf; | |
1435 | |
1436 if (!sess->images) | |
1437 sess->images = q; | |
1438 else { | |
1439 struct gg_image_queue *qq; | |
1440 | |
1441 for (qq = sess->images; qq->next; qq = qq->next) | |
1442 ; | |
1443 | |
1444 qq->next = q; | |
1445 } | |
1446 } | |
1447 | |
1448 return res; | |
1449 } | |
1450 | |
1451 /* | |
1452 * gg_image_reply() | |
1453 * | |
1454 * wysyła żądany obrazek. | |
1455 * | |
1456 * - sess - opis sesji | |
1457 * - recipient - numer adresata | |
1458 * - filename - nazwa pliku | |
1459 * - image - bufor z obrazkiem | |
1460 * - size - rozmiar obrazka | |
1461 * | |
1462 * 0/-1 | |
1463 */ | |
1464 int gg_image_reply(struct gg_session *sess, uin_t recipient, const char *filename, const char *image, int size) | |
1465 { | |
1466 struct gg_msg_image_reply *r; | |
1467 struct gg_send_msg s; | |
1468 const char *tmp; | |
1469 char buf[1910]; | |
1470 int res = -1; | |
1471 | |
1472 gg_debug(GG_DEBUG_FUNCTION, "** gg_image_reply(%p, %d, \"%s\", %p, %d);\n", sess, recipient, filename, image, size); | |
1473 | |
1474 if (!sess || !filename || !image) { | |
1475 errno = EFAULT; | |
1476 return -1; | |
1477 } | |
1478 | |
1479 if (sess->state != GG_STATE_CONNECTED) { | |
1480 errno = ENOTCONN; | |
1481 return -1; | |
1482 } | |
1483 | |
1484 if (size < 0) { | |
1485 errno = EINVAL; | |
1486 return -1; | |
1487 } | |
1488 | |
1489 /* wytnij ścieżki, zostaw tylko nazwę pliku */ | |
1490 while ((tmp = strrchr(filename, '/')) || (tmp = strrchr(filename, '\\'))) | |
1491 filename = tmp + 1; | |
1492 | |
1493 if (strlen(filename) < 1 || strlen(filename) > 1024) { | |
1494 errno = EINVAL; | |
1495 return -1; | |
1496 } | |
1497 | |
1498 s.recipient = gg_fix32(recipient); | |
1499 s.seq = gg_fix32(0); | |
1500 s.msgclass = gg_fix32(GG_CLASS_MSG); | |
1501 | |
1502 buf[0] = 0; | |
1503 r = (void*) &buf[1]; | |
1504 | |
1505 r->flag = 0x05; | |
1506 r->size = gg_fix32(size); | |
1507 r->crc32 = gg_fix32(gg_crc32(0, image, size)); | |
1508 | |
1509 while (size > 0) { | |
1510 int buflen, chunklen; | |
1511 | |
1512 /* \0 + struct gg_msg_image_reply */ | |
1513 buflen = sizeof(struct gg_msg_image_reply) + 1; | |
1514 | |
1515 /* w pierwszym kawałku jest nazwa pliku */ | |
1516 if (r->flag == 0x05) { | |
1517 strcpy(buf + buflen, filename); | |
1518 buflen += strlen(filename) + 1; | |
1519 } | |
1520 | |
1521 chunklen = (size >= sizeof(buf) - buflen) ? (sizeof(buf) - buflen) : size; | |
1522 | |
1523 memcpy(buf + buflen, image, chunklen); | |
1524 size -= chunklen; | |
1525 image += chunklen; | |
1526 | |
1527 res = gg_send_packet(sess, GG_SEND_MSG, &s, sizeof(s), buf, buflen + chunklen, NULL); | |
1528 | |
1529 if (res == -1) | |
1530 break; | |
1531 | |
1532 r->flag = 0x06; | |
1533 } | |
1534 | |
1535 return res; | |
1536 } | |
1537 | |
1538 /* | |
1539 * gg_send_message_ctcp() | |
1540 * | |
1541 * wysyła wiadomość do innego użytkownika. zwraca losowy numer | |
1542 * sekwencyjny, który można zignorować albo wykorzystać do potwierdzenia. | |
1543 * | |
1544 * - sess - opis sesji | |
1545 * - msgclass - rodzaj wiadomości | |
1546 * - recipient - numer adresata | |
1547 * - message - treść wiadomości | |
1548 * - message_len - długość | |
1549 * | |
1550 * numer sekwencyjny wiadomości lub -1 w przypadku błędu. | |
1551 */ | |
1552 int gg_send_message_ctcp(struct gg_session *sess, int msgclass, uin_t recipient, const unsigned char *message, int message_len) | |
1553 { | |
1554 struct gg_send_msg s; | |
1555 | |
1556 gg_debug(GG_DEBUG_FUNCTION, "** gg_send_message_ctcp(%p, %d, %u, ...);\n", sess, msgclass, recipient); | |
1557 | |
1558 if (!sess) { | |
1559 errno = EFAULT; | |
1560 return -1; | |
1561 } | |
1562 | |
1563 if (sess->state != GG_STATE_CONNECTED) { | |
1564 errno = ENOTCONN; | |
1565 return -1; | |
1566 } | |
1567 | |
1568 s.recipient = gg_fix32(recipient); | |
1569 s.seq = gg_fix32(0); | |
1570 s.msgclass = gg_fix32(msgclass); | |
1571 | |
1572 return gg_send_packet(sess, GG_SEND_MSG, &s, sizeof(s), message, message_len, NULL); | |
1573 } | |
1574 | |
1575 /* | |
1576 * gg_send_message() | |
1577 * | |
1578 * wysyła wiadomość do innego użytkownika. zwraca losowy numer | |
1579 * sekwencyjny, który można zignorować albo wykorzystać do potwierdzenia. | |
1580 * | |
1581 * - sess - opis sesji | |
1582 * - msgclass - rodzaj wiadomości | |
1583 * - recipient - numer adresata | |
1584 * - message - treść wiadomości | |
1585 * | |
1586 * numer sekwencyjny wiadomości lub -1 w przypadku błędu. | |
1587 */ | |
1588 int gg_send_message(struct gg_session *sess, int msgclass, uin_t recipient, const unsigned char *message) | |
1589 { | |
1590 gg_debug(GG_DEBUG_FUNCTION, "** gg_send_message(%p, %d, %u, %p)\n", sess, msgclass, recipient, message); | |
1591 | |
1592 return gg_send_message_richtext(sess, msgclass, recipient, message, NULL, 0); | |
1593 } | |
1594 | |
1595 /* | |
1596 * gg_send_message_richtext() | |
1597 * | |
1598 * wysyła kolorową wiadomość do innego użytkownika. zwraca losowy numer | |
1599 * sekwencyjny, który można zignorować albo wykorzystać do potwierdzenia. | |
1600 * | |
1601 * - sess - opis sesji | |
1602 * - msgclass - rodzaj wiadomości | |
1603 * - recipient - numer adresata | |
1604 * - message - treść wiadomości | |
1605 * - format - informacje o formatowaniu | |
1606 * - formatlen - długość informacji o formatowaniu | |
1607 * | |
1608 * numer sekwencyjny wiadomości lub -1 w przypadku błędu. | |
1609 */ | |
1610 int gg_send_message_richtext(struct gg_session *sess, int msgclass, uin_t recipient, const unsigned char *message, const unsigned char *format, int formatlen) | |
1611 { | |
1612 struct gg_send_msg s; | |
1613 | |
1614 gg_debug(GG_DEBUG_FUNCTION, "** gg_send_message_richtext(%p, %d, %u, %p, %p, %d);\n", sess, msgclass, recipient, message, format, formatlen); | |
1615 | |
1616 if (!sess) { | |
1617 errno = EFAULT; | |
1618 return -1; | |
1619 } | |
1620 | |
1621 if (sess->state != GG_STATE_CONNECTED) { | |
1622 errno = ENOTCONN; | |
1623 return -1; | |
1624 } | |
1625 | |
1626 if (!message) { | |
1627 errno = EFAULT; | |
1628 return -1; | |
1629 } | |
1630 | |
1631 s.recipient = gg_fix32(recipient); | |
1632 if (!sess->seq) | |
1633 sess->seq = 0x01740000 | (rand() & 0xffff); | |
1634 s.seq = gg_fix32(sess->seq); | |
1635 s.msgclass = gg_fix32(msgclass); | |
1636 sess->seq += (rand() % 0x300) + 0x300; | |
1637 | |
1638 if (gg_send_packet(sess, GG_SEND_MSG, &s, sizeof(s), message, strlen(message) + 1, format, formatlen, NULL) == -1) | |
1639 return -1; | |
1640 | |
1641 return gg_fix32(s.seq); | |
1642 } | |
1643 | |
1644 /* | |
1645 * gg_send_message_confer() | |
1646 * | |
1647 * wysyła wiadomość do kilku użytkownikow (konferencja). zwraca losowy numer | |
1648 * sekwencyjny, który można zignorować albo wykorzystać do potwierdzenia. | |
1649 * | |
1650 * - sess - opis sesji | |
1651 * - msgclass - rodzaj wiadomości | |
1652 * - recipients_count - ilość adresatów | |
1653 * - recipients - numerki adresatów | |
1654 * - message - treść wiadomości | |
1655 * | |
1656 * numer sekwencyjny wiadomości lub -1 w przypadku błędu. | |
1657 */ | |
1658 int gg_send_message_confer(struct gg_session *sess, int msgclass, int recipients_count, uin_t *recipients, const unsigned char *message) | |
1659 { | |
1660 gg_debug(GG_DEBUG_FUNCTION, "** gg_send_message_confer(%p, %d, %d, %p, %p);\n", sess, msgclass, recipients_count, recipients, message); | |
1661 | |
1662 return gg_send_message_confer_richtext(sess, msgclass, recipients_count, recipients, message, NULL, 0); | |
1663 } | |
1664 | |
1665 /* | |
1666 * gg_send_message_confer_richtext() | |
1667 * | |
1668 * wysyła kolorową wiadomość do kilku użytkownikow (konferencja). zwraca | |
1669 * losowy numer sekwencyjny, który można zignorować albo wykorzystać do | |
1670 * potwierdzenia. | |
1671 * | |
1672 * - sess - opis sesji | |
1673 * - msgclass - rodzaj wiadomości | |
1674 * - recipients_count - ilość adresatów | |
1675 * - recipients - numerki adresatów | |
1676 * - message - treść wiadomości | |
1677 * - format - informacje o formatowaniu | |
1678 * - formatlen - długość informacji o formatowaniu | |
1679 * | |
1680 * numer sekwencyjny wiadomości lub -1 w przypadku błędu. | |
1681 */ | |
1682 int gg_send_message_confer_richtext(struct gg_session *sess, int msgclass, int recipients_count, uin_t *recipients, const unsigned char *message, const unsigned char *format, int formatlen) | |
1683 { | |
1684 struct gg_send_msg s; | |
1685 struct gg_msg_recipients r; | |
1686 int i, j, k; | |
1687 uin_t *recps; | |
1688 | |
1689 gg_debug(GG_DEBUG_FUNCTION, "** gg_send_message_confer_richtext(%p, %d, %d, %p, %p, %p, %d);\n", sess, msgclass, recipients_count, recipients, message, format, formatlen); | |
1690 | |
1691 if (!sess) { | |
1692 errno = EFAULT; | |
1693 return -1; | |
1694 } | |
1695 | |
1696 if (sess->state != GG_STATE_CONNECTED) { | |
1697 errno = ENOTCONN; | |
1698 return -1; | |
1699 } | |
1700 | |
1701 if (!message || recipients_count <= 0 || recipients_count > 0xffff || !recipients) { | |
1702 errno = EINVAL; | |
1703 return -1; | |
1704 } | |
1705 | |
1706 r.flag = 0x01; | |
1707 r.count = gg_fix32(recipients_count - 1); | |
1708 | |
1709 if (!sess->seq) | |
1710 sess->seq = 0x01740000 | (rand() & 0xffff); | |
1711 s.seq = gg_fix32(sess->seq); | |
1712 s.msgclass = gg_fix32(msgclass); | |
1713 | |
1714 recps = malloc(sizeof(uin_t) * recipients_count); | |
1715 if (!recps) | |
1716 return -1; | |
1717 | |
1718 for (i = 0; i < recipients_count; i++) { | |
1719 | |
1720 s.recipient = gg_fix32(recipients[i]); | |
1721 | |
1722 for (j = 0, k = 0; j < recipients_count; j++) | |
1723 if (recipients[j] != recipients[i]) { | |
1724 recps[k] = gg_fix32(recipients[j]); | |
1725 k++; | |
1726 } | |
1727 | |
1728 if (!i) | |
1729 sess->seq += (rand() % 0x300) + 0x300; | |
1730 | |
1731 if (gg_send_packet(sess, GG_SEND_MSG, &s, sizeof(s), message, strlen(message) + 1, &r, sizeof(r), recps, (recipients_count - 1) * sizeof(uin_t), format, formatlen, NULL) == -1) { | |
1732 free(recps); | |
1733 return -1; | |
1734 } | |
1735 } | |
1736 | |
1737 free(recps); | |
1738 | |
1739 return gg_fix32(s.seq); | |
1740 } | |
1741 | |
1742 /* | |
1743 * gg_ping() | |
1744 * | |
1745 * wysyła do serwera pakiet ping. | |
1746 * | |
1747 * - sess - opis sesji | |
1748 * | |
1749 * 0, -1. | |
1750 */ | |
1751 int gg_ping(struct gg_session *sess) | |
1752 { | |
1753 gg_debug(GG_DEBUG_FUNCTION, "** gg_ping(%p);\n", sess); | |
1754 | |
1755 if (!sess) { | |
1756 errno = EFAULT; | |
1757 return -1; | |
1758 } | |
1759 | |
1760 if (sess->state != GG_STATE_CONNECTED) { | |
1761 errno = ENOTCONN; | |
1762 return -1; | |
1763 } | |
1764 | |
1765 return gg_send_packet(sess, GG_PING, NULL); | |
1766 } | |
1767 | |
1768 /* | |
1769 * gg_notify_ex() | |
1770 * | |
1771 * wysyła serwerowi listę kontaktów (wraz z odpowiadającymi im typami userów), | |
1772 * dzięki czemu wie, czyj stan nas interesuje. | |
1773 * | |
1774 * - sess - opis sesji | |
1775 * - userlist - wskaźnik do tablicy numerów | |
1776 * - types - wskaźnik do tablicy typów użytkowników | |
1777 * - count - ilość numerków | |
1778 * | |
1779 * 0, -1. | |
1780 */ | |
1781 int gg_notify_ex(struct gg_session *sess, uin_t *userlist, char *types, int count) | |
1782 { | |
1783 struct gg_notify *n; | |
1784 uin_t *u; | |
1785 char *t; | |
1786 int i, res = 0; | |
1787 | |
1788 gg_debug(GG_DEBUG_FUNCTION, "** gg_notify_ex(%p, %p, %p, %d);\n", sess, userlist, types, count); | |
1789 | |
1790 if (!sess) { | |
1791 errno = EFAULT; | |
1792 return -1; | |
1793 } | |
1794 | |
1795 if (sess->state != GG_STATE_CONNECTED) { | |
1796 errno = ENOTCONN; | |
1797 return -1; | |
1798 } | |
1799 | |
1800 if (!userlist || !count) | |
1801 return gg_send_packet(sess, GG_LIST_EMPTY, NULL); | |
1802 | |
1803 while (count > 0) { | |
1804 int part_count, packet_type; | |
1805 | |
1806 if (count > 400) { | |
1807 part_count = 400; | |
1808 packet_type = GG_NOTIFY_FIRST; | |
1809 } else { | |
1810 part_count = count; | |
1811 packet_type = GG_NOTIFY_LAST; | |
1812 } | |
1813 | |
1814 if (!(n = (struct gg_notify*) malloc(sizeof(*n) * part_count))) | |
1815 return -1; | |
1816 | |
1817 for (u = userlist, t = types, i = 0; i < part_count; u++, t++, i++) { | |
1818 n[i].uin = gg_fix32(*u); | |
1819 n[i].dunno1 = *t; | |
1820 } | |
1821 | |
1822 if (gg_send_packet(sess, packet_type, n, sizeof(*n) * part_count, NULL) == -1) { | |
1823 free(n); | |
1824 res = -1; | |
1825 break; | |
1826 } | |
1827 | |
1828 count -= part_count; | |
1829 userlist += part_count; | |
1830 types += part_count; | |
1831 | |
1832 free(n); | |
1833 } | |
1834 | |
1835 return res; | |
1836 } | |
1837 | |
1838 /* | |
1839 * gg_notify() | |
1840 * | |
1841 * wysyła serwerowi listę kontaktów, dzięki czemu wie, czyj stan nas | |
1842 * interesuje. | |
1843 * | |
1844 * - sess - opis sesji | |
1845 * - userlist - wskaźnik do tablicy numerów | |
1846 * - count - ilość numerków | |
1847 * | |
1848 * 0, -1. | |
1849 */ | |
1850 int gg_notify(struct gg_session *sess, uin_t *userlist, int count) | |
1851 { | |
1852 struct gg_notify *n; | |
1853 uin_t *u; | |
1854 int i, res = 0; | |
1855 | |
1856 gg_debug(GG_DEBUG_FUNCTION, "** gg_notify(%p, %p, %d);\n", sess, userlist, count); | |
1857 | |
1858 if (!sess) { | |
1859 errno = EFAULT; | |
1860 return -1; | |
1861 } | |
1862 | |
1863 if (sess->state != GG_STATE_CONNECTED) { | |
1864 errno = ENOTCONN; | |
1865 return -1; | |
1866 } | |
1867 | |
1868 if (!userlist || !count) | |
1869 return gg_send_packet(sess, GG_LIST_EMPTY, NULL); | |
1870 | |
1871 while (count > 0) { | |
1872 int part_count, packet_type; | |
1873 | |
1874 if (count > 400) { | |
1875 part_count = 400; | |
1876 packet_type = GG_NOTIFY_FIRST; | |
1877 } else { | |
1878 part_count = count; | |
1879 packet_type = GG_NOTIFY_LAST; | |
1880 } | |
1881 | |
1882 if (!(n = (struct gg_notify*) malloc(sizeof(*n) * part_count))) | |
1883 return -1; | |
1884 | |
1885 for (u = userlist, i = 0; i < part_count; u++, i++) { | |
1886 n[i].uin = gg_fix32(*u); | |
1887 n[i].dunno1 = GG_USER_NORMAL; | |
1888 } | |
1889 | |
1890 if (gg_send_packet(sess, packet_type, n, sizeof(*n) * part_count, NULL) == -1) { | |
1891 res = -1; | |
1892 free(n); | |
1893 break; | |
1894 } | |
1895 | |
1896 free(n); | |
1897 | |
1898 userlist += part_count; | |
1899 count -= part_count; | |
1900 } | |
1901 | |
1902 return res; | |
1903 } | |
1904 | |
1905 /* | |
1906 * gg_add_notify_ex() | |
1907 * | |
1908 * dodaje do listy kontaktów dany numer w trakcie połączenia. | |
1909 * dodawanemu użytkownikowi określamy jego typ (patrz protocol.html) | |
1910 * | |
1911 * - sess - opis sesji | |
1912 * - uin - numer | |
1913 * - type - typ | |
1914 * | |
1915 * 0, -1. | |
1916 */ | |
1917 int gg_add_notify_ex(struct gg_session *sess, uin_t uin, char type) | |
1918 { | |
1919 struct gg_add_remove a; | |
1920 | |
1921 gg_debug(GG_DEBUG_FUNCTION, "** gg_add_notify_ex(%p, %u, %d);\n", sess, uin, type); | |
1922 | |
1923 if (!sess) { | |
1924 errno = EFAULT; | |
1925 return -1; | |
1926 } | |
1927 | |
1928 if (sess->state != GG_STATE_CONNECTED) { | |
1929 errno = ENOTCONN; | |
1930 return -1; | |
1931 } | |
1932 | |
1933 a.uin = gg_fix32(uin); | |
1934 a.dunno1 = type; | |
1935 | |
1936 return gg_send_packet(sess, GG_ADD_NOTIFY, &a, sizeof(a), NULL); | |
1937 } | |
1938 | |
1939 /* | |
1940 * gg_add_notify() | |
1941 * | |
1942 * dodaje do listy kontaktów dany numer w trakcie połączenia. | |
1943 * | |
1944 * - sess - opis sesji | |
1945 * - uin - numer | |
1946 * | |
1947 * 0, -1. | |
1948 */ | |
1949 int gg_add_notify(struct gg_session *sess, uin_t uin) | |
1950 { | |
1951 return gg_add_notify_ex(sess, uin, GG_USER_NORMAL); | |
1952 } | |
1953 | |
1954 /* | |
1955 * gg_remove_notify_ex() | |
1956 * | |
1957 * usuwa z listy kontaktów w trakcie połączenia. | |
1958 * usuwanemu użytkownikowi określamy jego typ (patrz protocol.html) | |
1959 * | |
1960 * - sess - opis sesji | |
1961 * - uin - numer | |
1962 * - type - typ | |
1963 * | |
1964 * 0, -1. | |
1965 */ | |
1966 int gg_remove_notify_ex(struct gg_session *sess, uin_t uin, char type) | |
1967 { | |
1968 struct gg_add_remove a; | |
1969 | |
1970 gg_debug(GG_DEBUG_FUNCTION, "** gg_remove_notify_ex(%p, %u, %d);\n", sess, uin, type); | |
1971 | |
1972 if (!sess) { | |
1973 errno = EFAULT; | |
1974 return -1; | |
1975 } | |
1976 | |
1977 if (sess->state != GG_STATE_CONNECTED) { | |
1978 errno = ENOTCONN; | |
1979 return -1; | |
1980 } | |
1981 | |
1982 a.uin = gg_fix32(uin); | |
1983 a.dunno1 = type; | |
1984 | |
1985 return gg_send_packet(sess, GG_REMOVE_NOTIFY, &a, sizeof(a), NULL); | |
1986 } | |
1987 | |
1988 /* | |
1989 * gg_remove_notify() | |
1990 * | |
1991 * usuwa z listy kontaktów w trakcie połączenia. | |
1992 * | |
1993 * - sess - opis sesji | |
1994 * - uin - numer | |
1995 * | |
1996 * 0, -1. | |
1997 */ | |
1998 int gg_remove_notify(struct gg_session *sess, uin_t uin) | |
1999 { | |
2000 return gg_remove_notify_ex(sess, uin, GG_USER_NORMAL); | |
2001 } | |
2002 | |
2003 /* | |
2004 * gg_userlist_request() | |
2005 * | |
2006 * wysyła żądanie/zapytanie listy kontaktów na serwerze. | |
2007 * | |
2008 * - sess - opis sesji | |
2009 * - type - rodzaj zapytania/żądania | |
2010 * - request - treść zapytania/żądania (może być NULL) | |
2011 * | |
2012 * 0, -1 | |
2013 */ | |
2014 int gg_userlist_request(struct gg_session *sess, char type, const char *request) | |
2015 { | |
2016 int len; | |
2017 | |
2018 if (!sess) { | |
2019 errno = EFAULT; | |
2020 return -1; | |
2021 } | |
2022 | |
2023 if (sess->state != GG_STATE_CONNECTED) { | |
2024 errno = ENOTCONN; | |
2025 return -1; | |
2026 } | |
2027 | |
2028 if (!request) { | |
2029 sess->userlist_blocks = 1; | |
2030 return gg_send_packet(sess, GG_USERLIST_REQUEST, &type, sizeof(type), NULL); | |
2031 } | |
2032 | |
2033 len = strlen(request); | |
2034 | |
2035 sess->userlist_blocks = 0; | |
2036 | |
2037 while (len > 2047) { | |
2038 sess->userlist_blocks++; | |
2039 | |
2040 if (gg_send_packet(sess, GG_USERLIST_REQUEST, &type, sizeof(type), request, 2047, NULL) == -1) | |
2041 return -1; | |
2042 | |
2043 if (type == GG_USERLIST_PUT) | |
2044 type = GG_USERLIST_PUT_MORE; | |
2045 | |
2046 request += 2047; | |
2047 len -= 2047; | |
2048 } | |
2049 | |
2050 sess->userlist_blocks++; | |
2051 | |
2052 return gg_send_packet(sess, GG_USERLIST_REQUEST, &type, sizeof(type), request, len, NULL); | |
2053 } | |
2054 | |
2055 /* | |
2056 * Local variables: | |
2057 * c-indentation-style: k&r | |
2058 * c-basic-offset: 8 | |
2059 * indent-tabs-mode: notnil | |
2060 * End: | |
2061 * | |
2062 * vim: shiftwidth=8: | |
2063 */ |