Mercurial > pidgin
annotate src/protocols/gg/lib/libgadu.c @ 12218:9cbc5967fbfd
[gaim-migrate @ 14520]
Crush some warnings. I ran this by Bartosz Oler and made some corrections at his suggestion. I'll be submitting this upstream and merging any changes they suggest/make-when-accepting.
committer: Tailor Script <tailor@pidgin.im>
author | Richard Laager <rlaager@wiktel.com> |
---|---|
date | Fri, 25 Nov 2005 00:32:45 +0000 |
parents | 8724718d387f |
children | 4661eefa0840 |
rev | line source |
---|---|
12218
9cbc5967fbfd
[gaim-migrate @ 14520]
Richard Laager <rlaager@wiktel.com>
parents:
12007
diff
changeset
|
1 /* $Id: libgadu.c 14520 2005-11-25 00:32:45Z rlaager $ */ |
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 | |
12218
9cbc5967fbfd
[gaim-migrate @ 14520]
Richard Laager <rlaager@wiktel.com>
parents:
12007
diff
changeset
|
84 = "$Id: libgadu.c 14520 2005-11-25 00:32:45Z rlaager $"; |
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; | |
12218
9cbc5967fbfd
[gaim-migrate @ 14520]
Richard Laager <rlaager@wiktel.com>
parents:
12007
diff
changeset
|
702 int ret = 0, offset, size = 0; |
11360 | 703 |
704 gg_debug(GG_DEBUG_FUNCTION, "** gg_recv_packet(%p);\n", sess); | |
705 | |
706 if (!sess) { | |
707 errno = EFAULT; | |
708 return NULL; | |
709 } | |
710 | |
711 if (sess->recv_left < 1) { | |
712 if (sess->header_buf) { | |
713 memcpy(&h, sess->header_buf, sess->header_done); | |
714 gg_debug(GG_DEBUG_MISC, "// gg_recv_packet() header recv: resuming last read (%d bytes left)\n", sizeof(h) - sess->header_done); | |
715 free(sess->header_buf); | |
716 sess->header_buf = NULL; | |
717 } else | |
718 sess->header_done = 0; | |
719 | |
720 while (sess->header_done < sizeof(h)) { | |
721 ret = gg_read(sess, (char*) &h + sess->header_done, sizeof(h) - sess->header_done); | |
722 | |
723 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); | |
724 | |
725 if (!ret) { | |
726 errno = ECONNRESET; | |
727 gg_debug(GG_DEBUG_MISC, "// gg_recv_packet() header recv() failed: connection broken\n"); | |
728 return NULL; | |
729 } | |
730 | |
731 if (ret == -1) { | |
732 if (errno == EINTR) { | |
733 gg_debug(GG_DEBUG_MISC, "// gg_recv_packet() header recv() interrupted system call, resuming\n"); | |
734 continue; | |
735 } | |
736 | |
737 if (errno == EAGAIN) { | |
738 gg_debug(GG_DEBUG_MISC, "// gg_recv_packet() header recv() incomplete header received\n"); | |
739 | |
740 if (!(sess->header_buf = malloc(sess->header_done))) { | |
741 gg_debug(GG_DEBUG_MISC, "// gg_recv_packet() header recv() not enough memory\n"); | |
742 return NULL; | |
743 } | |
744 | |
745 memcpy(sess->header_buf, &h, sess->header_done); | |
746 | |
747 return NULL; | |
748 } | |
749 | |
750 gg_debug(GG_DEBUG_MISC, "// gg_recv_packet() header recv() failed: errno=%d, %s\n", errno, strerror(errno)); | |
751 | |
752 return NULL; | |
753 } | |
754 | |
755 sess->header_done += ret; | |
756 | |
757 } | |
758 | |
759 h.type = gg_fix32(h.type); | |
760 h.length = gg_fix32(h.length); | |
761 } else | |
762 memcpy(&h, sess->recv_buf, sizeof(h)); | |
763 | |
764 /* jakieś sensowne limity na rozmiar pakietu */ | |
765 if (h.length > 65535) { | |
766 gg_debug(GG_DEBUG_MISC, "// gg_recv_packet() invalid packet length (%d)\n", h.length); | |
767 errno = ERANGE; | |
768 return NULL; | |
769 } | |
770 | |
771 if (sess->recv_left > 0) { | |
772 gg_debug(GG_DEBUG_MISC, "// gg_recv_packet() resuming last gg_recv_packet()\n"); | |
773 size = sess->recv_left; | |
774 offset = sess->recv_done; | |
775 buf = sess->recv_buf; | |
776 } else { | |
777 if (!(buf = malloc(sizeof(h) + h.length + 1))) { | |
778 gg_debug(GG_DEBUG_MISC, "// gg_recv_packet() not enough memory for packet data\n"); | |
779 return NULL; | |
780 } | |
781 | |
782 memcpy(buf, &h, sizeof(h)); | |
783 | |
784 offset = 0; | |
785 size = h.length; | |
786 } | |
787 | |
788 while (size > 0) { | |
789 ret = gg_read(sess, buf + sizeof(h) + offset, size); | |
790 gg_debug(GG_DEBUG_MISC, "// gg_recv_packet() body recv(%d,%p,%d) = %d\n", sess->fd, buf + sizeof(h) + offset, size, ret); | |
791 if (!ret) { | |
792 gg_debug(GG_DEBUG_MISC, "// gg_recv_packet() body recv() failed: connection broken\n"); | |
793 errno = ECONNRESET; | |
794 return NULL; | |
795 } | |
796 if (ret > -1 && ret <= size) { | |
797 offset += ret; | |
798 size -= ret; | |
799 } else if (ret == -1) { | |
800 int errno2 = errno; | |
801 | |
802 gg_debug(GG_DEBUG_MISC, "// gg_recv_packet() body recv() failed (errno=%d, %s)\n", errno, strerror(errno)); | |
803 errno = errno2; | |
804 | |
805 if (errno == EAGAIN) { | |
806 gg_debug(GG_DEBUG_MISC, "// gg_recv_packet() %d bytes received, %d left\n", offset, size); | |
807 sess->recv_buf = buf; | |
808 sess->recv_left = size; | |
809 sess->recv_done = offset; | |
810 return NULL; | |
811 } | |
812 if (errno != EINTR) { | |
813 free(buf); | |
814 return NULL; | |
815 } | |
816 } | |
817 } | |
818 | |
819 sess->recv_left = 0; | |
820 | |
821 if ((gg_debug_level & GG_DEBUG_DUMP)) { | |
822 unsigned int i; | |
823 | |
824 gg_debug(GG_DEBUG_DUMP, "// gg_recv_packet(%.2x)", h.type); | |
825 for (i = 0; i < sizeof(h) + h.length; i++) | |
826 gg_debug(GG_DEBUG_DUMP, " %.2x", (unsigned char) buf[i]); | |
827 gg_debug(GG_DEBUG_DUMP, "\n"); | |
828 } | |
829 | |
830 return buf; | |
831 } | |
832 | |
833 /* | |
834 * gg_send_packet() // funkcja wewnętrzna | |
835 * | |
836 * konstruuje pakiet i wysyła go do serwera. | |
837 * | |
838 * - sock - deskryptor gniazda | |
839 * - type - typ pakietu | |
840 * - payload_1 - pierwsza część pakietu | |
841 * - payload_length_1 - długość pierwszej części | |
842 * - payload_2 - druga część pakietu | |
843 * - payload_length_2 - długość drugiej części | |
844 * - ... - kolejne części pakietu i ich długości | |
845 * - NULL - końcowym parametr (konieczny!) | |
846 * | |
847 * jeśli się powiodło, zwraca 0, w przypadku błędu -1. jeśli errno == ENOMEM, | |
848 * zabrakło pamięci. inaczej był błąd przy wysyłaniu pakietu. dla errno == 0 | |
849 * nie wysłano całego pakietu. | |
850 */ | |
851 int gg_send_packet(struct gg_session *sess, int type, ...) | |
852 { | |
853 struct gg_header *h; | |
854 char *tmp; | |
12218
9cbc5967fbfd
[gaim-migrate @ 14520]
Richard Laager <rlaager@wiktel.com>
parents:
12007
diff
changeset
|
855 int tmp_length; |
11360 | 856 void *payload; |
857 unsigned int payload_length; | |
858 va_list ap; | |
859 int res; | |
860 | |
861 gg_debug(GG_DEBUG_FUNCTION, "** gg_send_packet(%p, 0x%.2x, ...)\n", sess, type); | |
862 | |
863 tmp_length = sizeof(struct gg_header); | |
864 | |
865 if (!(tmp = malloc(tmp_length))) { | |
866 gg_debug(GG_DEBUG_MISC, "// gg_send_packet() not enough memory for packet header\n"); | |
867 return -1; | |
868 } | |
869 | |
870 va_start(ap, type); | |
871 | |
872 payload = va_arg(ap, void *); | |
873 | |
874 while (payload) { | |
875 char *tmp2; | |
876 | |
877 payload_length = va_arg(ap, unsigned int); | |
878 | |
879 if (!(tmp2 = realloc(tmp, tmp_length + payload_length))) { | |
880 gg_debug(GG_DEBUG_MISC, "// gg_send_packet() not enough memory for payload\n"); | |
881 free(tmp); | |
882 va_end(ap); | |
883 return -1; | |
884 } | |
885 | |
886 tmp = tmp2; | |
887 | |
888 memcpy(tmp + tmp_length, payload, payload_length); | |
889 tmp_length += payload_length; | |
890 | |
891 payload = va_arg(ap, void *); | |
892 } | |
893 | |
894 va_end(ap); | |
895 | |
896 h = (struct gg_header*) tmp; | |
897 h->type = gg_fix32(type); | |
898 h->length = gg_fix32(tmp_length - sizeof(struct gg_header)); | |
899 | |
900 if ((gg_debug_level & GG_DEBUG_DUMP)) { | |
12218
9cbc5967fbfd
[gaim-migrate @ 14520]
Richard Laager <rlaager@wiktel.com>
parents:
12007
diff
changeset
|
901 int i; |
11360 | 902 |
903 gg_debug(GG_DEBUG_DUMP, "// gg_send_packet(0x%.2x)", gg_fix32(h->type)); | |
904 for (i = 0; i < tmp_length; ++i) | |
905 gg_debug(GG_DEBUG_DUMP, " %.2x", (unsigned char) tmp[i]); | |
906 gg_debug(GG_DEBUG_DUMP, "\n"); | |
907 } | |
908 | |
909 if ((res = gg_write(sess, tmp, tmp_length)) < tmp_length) { | |
910 gg_debug(GG_DEBUG_MISC, "// gg_send_packet() write() failed. res = %d, errno = %d (%s)\n", res, errno, strerror(errno)); | |
911 free(tmp); | |
912 return -1; | |
913 } | |
914 | |
915 free(tmp); | |
916 return 0; | |
917 } | |
918 | |
919 /* | |
920 * gg_session_callback() // funkcja wewnętrzna | |
921 * | |
922 * wywoływany z gg_session->callback, wykonuje gg_watch_fd() i pakuje | |
923 * do gg_session->event jego wynik. | |
924 */ | |
925 static int gg_session_callback(struct gg_session *s) | |
926 { | |
927 if (!s) { | |
928 errno = EFAULT; | |
929 return -1; | |
930 } | |
931 | |
932 return ((s->event = gg_watch_fd(s)) != NULL) ? 0 : -1; | |
933 } | |
934 | |
935 /* | |
936 * gg_login() | |
937 * | |
938 * rozpoczyna procedurę łączenia się z serwerem. resztę obsługuje się przez | |
939 * gg_watch_fd(). | |
940 * | |
941 * UWAGA! program musi obsłużyć SIGCHLD, jeśli łączy się asynchronicznie, | |
942 * żeby poprawnie zamknąć proces resolvera. | |
943 * | |
944 * - p - struktura opisująca początkowy stan. wymagane pola: uin, | |
945 * password | |
946 * | |
947 * w przypadku błędu NULL, jeśli idzie dobrze (async) albo poszło | |
948 * dobrze (sync), zwróci wskaźnik do zaalokowanej struct gg_session. | |
949 */ | |
950 struct gg_session *gg_login(const struct gg_login_params *p) | |
951 { | |
952 struct gg_session *sess = NULL; | |
953 char *hostname; | |
954 int port; | |
955 | |
956 if (!p) { | |
957 gg_debug(GG_DEBUG_FUNCTION, "** gg_login(%p);\n", p); | |
958 errno = EFAULT; | |
959 return NULL; | |
960 } | |
961 | |
962 gg_debug(GG_DEBUG_FUNCTION, "** gg_login(%p: [uin=%u, async=%d, ...]);\n", p, p->uin, p->async); | |
963 | |
964 if (!(sess = malloc(sizeof(struct gg_session)))) { | |
965 gg_debug(GG_DEBUG_MISC, "// gg_login() not enough memory for session data\n"); | |
966 goto fail; | |
967 } | |
968 | |
969 memset(sess, 0, sizeof(struct gg_session)); | |
970 | |
971 if (!p->password || !p->uin) { | |
972 gg_debug(GG_DEBUG_MISC, "// gg_login() invalid arguments. uin and password needed\n"); | |
973 errno = EFAULT; | |
974 goto fail; | |
975 } | |
976 | |
977 if (!(sess->password = strdup(p->password))) { | |
978 gg_debug(GG_DEBUG_MISC, "// gg_login() not enough memory for password\n"); | |
979 goto fail; | |
980 } | |
981 | |
982 if (p->status_descr && !(sess->initial_descr = strdup(p->status_descr))) { | |
983 gg_debug(GG_DEBUG_MISC, "// gg_login() not enough memory for status\n"); | |
984 goto fail; | |
985 } | |
986 | |
987 sess->uin = p->uin; | |
988 sess->state = GG_STATE_RESOLVING; | |
989 sess->check = GG_CHECK_READ; | |
990 sess->timeout = GG_DEFAULT_TIMEOUT; | |
991 sess->async = p->async; | |
992 sess->type = GG_SESSION_GG; | |
993 sess->initial_status = p->status; | |
994 sess->callback = gg_session_callback; | |
995 sess->destroy = gg_free_session; | |
996 sess->port = (p->server_port) ? p->server_port : ((gg_proxy_enabled) ? GG_HTTPS_PORT : GG_DEFAULT_PORT); | |
997 sess->server_addr = p->server_addr; | |
998 sess->external_port = p->external_port; | |
999 sess->external_addr = p->external_addr; | |
1000 sess->protocol_version = (p->protocol_version) ? p->protocol_version : GG_DEFAULT_PROTOCOL_VERSION; | |
1001 if (p->era_omnix) | |
1002 sess->protocol_version |= GG_ERA_OMNIX_MASK; | |
1003 if (p->has_audio) | |
1004 sess->protocol_version |= GG_HAS_AUDIO_MASK; | |
1005 sess->client_version = (p->client_version) ? strdup(p->client_version) : NULL; | |
1006 sess->last_sysmsg = p->last_sysmsg; | |
1007 sess->image_size = p->image_size; | |
1008 sess->pid = -1; | |
1009 | |
1010 if (p->tls == 1) { | |
1011 #ifdef __GG_LIBGADU_HAVE_OPENSSL | |
1012 char buf[1024]; | |
1013 | |
1014 OpenSSL_add_ssl_algorithms(); | |
1015 | |
1016 if (!RAND_status()) { | |
1017 char rdata[1024]; | |
1018 struct { | |
1019 time_t time; | |
1020 void *ptr; | |
1021 } rstruct; | |
1022 | |
1023 time(&rstruct.time); | |
1024 rstruct.ptr = (void *) &rstruct; | |
1025 | |
1026 RAND_seed((void *) rdata, sizeof(rdata)); | |
1027 RAND_seed((void *) &rstruct, sizeof(rstruct)); | |
1028 } | |
1029 | |
1030 sess->ssl_ctx = SSL_CTX_new(TLSv1_client_method()); | |
1031 | |
1032 if (!sess->ssl_ctx) { | |
1033 ERR_error_string_n(ERR_get_error(), buf, sizeof(buf)); | |
1034 gg_debug(GG_DEBUG_MISC, "// gg_login() SSL_CTX_new() failed: %s\n", buf); | |
1035 goto fail; | |
1036 } | |
1037 | |
1038 SSL_CTX_set_verify(sess->ssl_ctx, SSL_VERIFY_NONE, NULL); | |
1039 | |
1040 sess->ssl = SSL_new(sess->ssl_ctx); | |
1041 | |
1042 if (!sess->ssl) { | |
1043 ERR_error_string_n(ERR_get_error(), buf, sizeof(buf)); | |
1044 gg_debug(GG_DEBUG_MISC, "// gg_login() SSL_new() failed: %s\n", buf); | |
1045 goto fail; | |
1046 } | |
1047 #else | |
1048 gg_debug(GG_DEBUG_MISC, "// gg_login() client requested TLS but no support compiled in\n"); | |
1049 #endif | |
1050 } | |
1051 | |
1052 if (gg_proxy_enabled) { | |
1053 hostname = gg_proxy_host; | |
1054 sess->proxy_port = port = gg_proxy_port; | |
1055 } else { | |
1056 hostname = GG_APPMSG_HOST; | |
1057 port = GG_APPMSG_PORT; | |
1058 } | |
1059 | |
1060 if (!p->async) { | |
1061 struct in_addr a; | |
1062 | |
1063 if (!p->server_addr || !p->server_port) { | |
1064 if ((a.s_addr = inet_addr(hostname)) == INADDR_NONE) { | |
1065 struct in_addr *hn; | |
1066 | |
1067 if (!(hn = gg_gethostbyname(hostname))) { | |
1068 gg_debug(GG_DEBUG_MISC, "// gg_login() host \"%s\" not found\n", hostname); | |
1069 goto fail; | |
1070 } else { | |
1071 a.s_addr = hn->s_addr; | |
1072 free(hn); | |
1073 } | |
1074 } | |
1075 } else { | |
1076 a.s_addr = p->server_addr; | |
1077 port = p->server_port; | |
1078 } | |
1079 | |
1080 sess->hub_addr = a.s_addr; | |
1081 | |
1082 if (gg_proxy_enabled) | |
1083 sess->proxy_addr = a.s_addr; | |
1084 | |
1085 if ((sess->fd = gg_connect(&a, port, 0)) == -1) { | |
1086 gg_debug(GG_DEBUG_MISC, "// gg_login() connection failed (errno=%d, %s)\n", errno, strerror(errno)); | |
1087 goto fail; | |
1088 } | |
1089 | |
1090 if (p->server_addr && p->server_port) | |
1091 sess->state = GG_STATE_CONNECTING_GG; | |
1092 else | |
1093 sess->state = GG_STATE_CONNECTING_HUB; | |
1094 | |
1095 while (sess->state != GG_STATE_CONNECTED) { | |
1096 struct gg_event *e; | |
1097 | |
1098 if (!(e = gg_watch_fd(sess))) { | |
1099 gg_debug(GG_DEBUG_MISC, "// gg_login() critical error in gg_watch_fd()\n"); | |
1100 goto fail; | |
1101 } | |
1102 | |
1103 if (e->type == GG_EVENT_CONN_FAILED) { | |
1104 errno = EACCES; | |
1105 gg_debug(GG_DEBUG_MISC, "// gg_login() could not login\n"); | |
1106 gg_event_free(e); | |
1107 goto fail; | |
1108 } | |
1109 | |
1110 gg_event_free(e); | |
1111 } | |
1112 | |
1113 return sess; | |
1114 } | |
1115 | |
1116 if (!sess->server_addr || gg_proxy_enabled) { | |
11546
3c536224f0d0
[gaim-migrate @ 13801]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11360
diff
changeset
|
1117 #ifdef __GG_LIBGADU_HAVE_PTHREAD |
3c536224f0d0
[gaim-migrate @ 13801]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11360
diff
changeset
|
1118 if (gg_resolve_pthread(&sess->fd, &sess->resolver, hostname)) { |
3c536224f0d0
[gaim-migrate @ 13801]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11360
diff
changeset
|
1119 #elif defined _WIN32 |
3c536224f0d0
[gaim-migrate @ 13801]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11360
diff
changeset
|
1120 if (gg_resolve_win32thread(&sess->fd, &sess->resolver, hostname)) { |
3c536224f0d0
[gaim-migrate @ 13801]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11360
diff
changeset
|
1121 #else |
11360 | 1122 if (gg_resolve(&sess->fd, &sess->pid, hostname)) { |
1123 #endif | |
1124 gg_debug(GG_DEBUG_MISC, "// gg_login() resolving failed (errno=%d, %s)\n", errno, strerror(errno)); | |
1125 goto fail; | |
1126 } | |
1127 } else { | |
1128 if ((sess->fd = gg_connect(&sess->server_addr, sess->port, sess->async)) == -1) { | |
1129 gg_debug(GG_DEBUG_MISC, "// gg_login() direct connection failed (errno=%d, %s)\n", errno, strerror(errno)); | |
1130 goto fail; | |
1131 } | |
1132 sess->state = GG_STATE_CONNECTING_GG; | |
1133 sess->check = GG_CHECK_WRITE; | |
1134 } | |
1135 | |
1136 return sess; | |
1137 | |
1138 fail: | |
1139 if (sess) { | |
1140 if (sess->password) | |
1141 free(sess->password); | |
1142 if (sess->initial_descr) | |
1143 free(sess->initial_descr); | |
1144 free(sess); | |
1145 } | |
1146 | |
1147 return NULL; | |
1148 } | |
1149 | |
1150 /* | |
1151 * gg_free_session() | |
1152 * | |
1153 * próbuje zamknąć połączenia i zwalnia pamięć zajmowaną przez sesję. | |
1154 * | |
1155 * - sess - opis sesji | |
1156 */ | |
1157 void gg_free_session(struct gg_session *sess) | |
1158 { | |
1159 if (!sess) | |
1160 return; | |
1161 | |
1162 /* XXX dopisać zwalnianie i zamykanie wszystkiego, co mogło zostać */ | |
1163 | |
1164 if (sess->password) | |
1165 free(sess->password); | |
1166 | |
1167 if (sess->initial_descr) | |
1168 free(sess->initial_descr); | |
1169 | |
1170 if (sess->client_version) | |
1171 free(sess->client_version); | |
1172 | |
1173 if (sess->header_buf) | |
1174 free(sess->header_buf); | |
1175 | |
1176 #ifdef __GG_LIBGADU_HAVE_OPENSSL | |
1177 if (sess->ssl) | |
1178 SSL_free(sess->ssl); | |
1179 | |
1180 if (sess->ssl_ctx) | |
1181 SSL_CTX_free(sess->ssl_ctx); | |
1182 #endif | |
1183 | |
1184 #ifdef __GG_LIBGADU_HAVE_PTHREAD | |
1185 if (sess->resolver) { | |
1186 pthread_cancel(*((pthread_t*) sess->resolver)); | |
1187 free(sess->resolver); | |
1188 sess->resolver = NULL; | |
1189 } | |
11546
3c536224f0d0
[gaim-migrate @ 13801]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11360
diff
changeset
|
1190 #elif defined _WIN32 |
3c536224f0d0
[gaim-migrate @ 13801]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11360
diff
changeset
|
1191 if (sess->resolver) { |
3c536224f0d0
[gaim-migrate @ 13801]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11360
diff
changeset
|
1192 HANDLE h = sess->resolver; |
3c536224f0d0
[gaim-migrate @ 13801]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11360
diff
changeset
|
1193 TerminateThread(h, 0); |
3c536224f0d0
[gaim-migrate @ 13801]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11360
diff
changeset
|
1194 CloseHandle(h); |
3c536224f0d0
[gaim-migrate @ 13801]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11360
diff
changeset
|
1195 sess->resolver = NULL; |
3c536224f0d0
[gaim-migrate @ 13801]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11360
diff
changeset
|
1196 } |
11360 | 1197 #else |
1198 if (sess->pid != -1) | |
1199 waitpid(sess->pid, NULL, WNOHANG); | |
1200 #endif | |
1201 | |
1202 if (sess->fd != -1) | |
1203 close(sess->fd); | |
1204 | |
1205 while (sess->images) | |
1206 gg_image_queue_remove(sess, sess->images, 1); | |
1207 | |
1208 free(sess); | |
1209 } | |
1210 | |
1211 /* | |
1212 * gg_change_status() | |
1213 * | |
1214 * zmienia status użytkownika. przydatne do /away i /busy oraz /quit. | |
1215 * | |
1216 * - sess - opis sesji | |
1217 * - status - nowy status użytkownika | |
1218 * | |
1219 * 0, -1. | |
1220 */ | |
1221 int gg_change_status(struct gg_session *sess, int status) | |
1222 { | |
1223 struct gg_new_status p; | |
1224 | |
1225 gg_debug(GG_DEBUG_FUNCTION, "** gg_change_status(%p, %d);\n", sess, status); | |
1226 | |
1227 if (!sess) { | |
1228 errno = EFAULT; | |
1229 return -1; | |
1230 } | |
1231 | |
1232 if (sess->state != GG_STATE_CONNECTED) { | |
1233 errno = ENOTCONN; | |
1234 return -1; | |
1235 } | |
1236 | |
1237 p.status = gg_fix32(status); | |
1238 | |
1239 sess->status = status; | |
1240 | |
1241 return gg_send_packet(sess, GG_NEW_STATUS, &p, sizeof(p), NULL); | |
1242 } | |
1243 | |
1244 /* | |
1245 * gg_change_status_descr() | |
1246 * | |
1247 * zmienia status użytkownika na opisowy. | |
1248 * | |
1249 * - sess - opis sesji | |
1250 * - status - nowy status użytkownika | |
1251 * - descr - opis statusu | |
1252 * | |
1253 * 0, -1. | |
1254 */ | |
1255 int gg_change_status_descr(struct gg_session *sess, int status, const char *descr) | |
1256 { | |
1257 struct gg_new_status p; | |
1258 | |
1259 gg_debug(GG_DEBUG_FUNCTION, "** gg_change_status_descr(%p, %d, \"%s\");\n", sess, status, descr); | |
1260 | |
1261 if (!sess || !descr) { | |
1262 errno = EFAULT; | |
1263 return -1; | |
1264 } | |
1265 | |
1266 if (sess->state != GG_STATE_CONNECTED) { | |
1267 errno = ENOTCONN; | |
1268 return -1; | |
1269 } | |
1270 | |
1271 p.status = gg_fix32(status); | |
1272 | |
1273 sess->status = status; | |
1274 | |
1275 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); | |
1276 } | |
1277 | |
1278 /* | |
1279 * gg_change_status_descr_time() | |
1280 * | |
1281 * zmienia status użytkownika na opisowy z godziną powrotu. | |
1282 * | |
1283 * - sess - opis sesji | |
1284 * - status - nowy status użytkownika | |
1285 * - descr - opis statusu | |
1286 * - time - czas w formacie uniksowym | |
1287 * | |
1288 * 0, -1. | |
1289 */ | |
1290 int gg_change_status_descr_time(struct gg_session *sess, int status, const char *descr, int time) | |
1291 { | |
1292 struct gg_new_status p; | |
1293 uint32_t newtime; | |
1294 | |
1295 gg_debug(GG_DEBUG_FUNCTION, "** gg_change_status_descr_time(%p, %d, \"%s\", %d);\n", sess, status, descr, time); | |
1296 | |
1297 if (!sess || !descr || !time) { | |
1298 errno = EFAULT; | |
1299 return -1; | |
1300 } | |
1301 | |
1302 if (sess->state != GG_STATE_CONNECTED) { | |
1303 errno = ENOTCONN; | |
1304 return -1; | |
1305 } | |
1306 | |
1307 p.status = gg_fix32(status); | |
1308 | |
1309 sess->status = status; | |
1310 | |
1311 newtime = gg_fix32(time); | |
1312 | |
1313 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); | |
1314 } | |
1315 | |
1316 /* | |
1317 * gg_logoff() | |
1318 * | |
1319 * wylogowuje użytkownika i zamyka połączenie, ale nie zwalnia pamięci. | |
1320 * | |
1321 * - sess - opis sesji | |
1322 */ | |
1323 void gg_logoff(struct gg_session *sess) | |
1324 { | |
1325 if (!sess) | |
1326 return; | |
1327 | |
1328 gg_debug(GG_DEBUG_FUNCTION, "** gg_logoff(%p);\n", sess); | |
1329 | |
1330 if (GG_S_NA(sess->status & ~GG_STATUS_FRIENDS_MASK)) | |
1331 gg_change_status(sess, GG_STATUS_NOT_AVAIL); | |
1332 | |
1333 #ifdef __GG_LIBGADU_HAVE_OPENSSL | |
1334 if (sess->ssl) | |
1335 SSL_shutdown(sess->ssl); | |
1336 #endif | |
1337 | |
1338 #ifdef __GG_LIBGADU_HAVE_PTHREAD | |
1339 if (sess->resolver) { | |
1340 pthread_cancel(*((pthread_t*) sess->resolver)); | |
1341 free(sess->resolver); | |
1342 sess->resolver = NULL; | |
1343 } | |
11546
3c536224f0d0
[gaim-migrate @ 13801]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11360
diff
changeset
|
1344 #elif defined _WIN32 |
3c536224f0d0
[gaim-migrate @ 13801]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11360
diff
changeset
|
1345 if (sess->resolver) { |
3c536224f0d0
[gaim-migrate @ 13801]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11360
diff
changeset
|
1346 HANDLE h = sess->resolver; |
3c536224f0d0
[gaim-migrate @ 13801]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11360
diff
changeset
|
1347 TerminateThread(h, 0); |
3c536224f0d0
[gaim-migrate @ 13801]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11360
diff
changeset
|
1348 CloseHandle(h); |
3c536224f0d0
[gaim-migrate @ 13801]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11360
diff
changeset
|
1349 sess->resolver = NULL; |
3c536224f0d0
[gaim-migrate @ 13801]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11360
diff
changeset
|
1350 } |
11360 | 1351 #else |
1352 if (sess->pid != -1) { | |
1353 waitpid(sess->pid, NULL, WNOHANG); | |
1354 sess->pid = -1; | |
1355 } | |
1356 #endif | |
1357 | |
1358 if (sess->fd != -1) { | |
1359 shutdown(sess->fd, SHUT_RDWR); | |
1360 close(sess->fd); | |
1361 sess->fd = -1; | |
1362 } | |
1363 } | |
1364 | |
1365 /* | |
1366 * gg_image_request() | |
1367 * | |
1368 * wysyła żądanie wysłania obrazka o podanych parametrach. | |
1369 * | |
1370 * - sess - opis sesji | |
1371 * - recipient - numer adresata | |
1372 * - size - rozmiar obrazka | |
1373 * - crc32 - suma kontrolna obrazka | |
1374 * | |
1375 * 0/-1 | |
1376 */ | |
1377 int gg_image_request(struct gg_session *sess, uin_t recipient, int size, uint32_t crc32) | |
1378 { | |
1379 struct gg_send_msg s; | |
1380 struct gg_msg_image_request r; | |
1381 char dummy = 0; | |
1382 int res; | |
1383 | |
1384 gg_debug(GG_DEBUG_FUNCTION, "** gg_image_request(%p, %d, %u, 0x%.4x);\n", sess, recipient, size, crc32); | |
1385 | |
1386 if (!sess) { | |
1387 errno = EFAULT; | |
1388 return -1; | |
1389 } | |
1390 | |
1391 if (sess->state != GG_STATE_CONNECTED) { | |
1392 errno = ENOTCONN; | |
1393 return -1; | |
1394 } | |
1395 | |
1396 if (size < 0) { | |
1397 errno = EINVAL; | |
1398 return -1; | |
1399 } | |
1400 | |
1401 s.recipient = gg_fix32(recipient); | |
1402 s.seq = gg_fix32(0); | |
1403 s.msgclass = gg_fix32(GG_CLASS_MSG); | |
1404 | |
1405 r.flag = 0x04; | |
1406 r.size = gg_fix32(size); | |
1407 r.crc32 = gg_fix32(crc32); | |
1408 | |
1409 res = gg_send_packet(sess, GG_SEND_MSG, &s, sizeof(s), &dummy, 1, &r, sizeof(r), NULL); | |
1410 | |
1411 if (!res) { | |
1412 struct gg_image_queue *q = malloc(sizeof(*q)); | |
1413 char *buf; | |
1414 | |
1415 if (!q) { | |
1416 gg_debug(GG_DEBUG_MISC, "// gg_image_request() not enough memory for image queue\n"); | |
1417 return -1; | |
1418 } | |
1419 | |
1420 buf = malloc(size); | |
1421 if (size && !buf) | |
1422 { | |
1423 gg_debug(GG_DEBUG_MISC, "// gg_image_request() not enough memory for image\n"); | |
1424 free(q); | |
1425 return -1; | |
1426 } | |
1427 | |
1428 memset(q, 0, sizeof(*q)); | |
1429 | |
1430 q->sender = recipient; | |
1431 q->size = size; | |
1432 q->crc32 = crc32; | |
1433 q->image = buf; | |
1434 | |
1435 if (!sess->images) | |
1436 sess->images = q; | |
1437 else { | |
1438 struct gg_image_queue *qq; | |
1439 | |
1440 for (qq = sess->images; qq->next; qq = qq->next) | |
1441 ; | |
1442 | |
1443 qq->next = q; | |
1444 } | |
1445 } | |
1446 | |
1447 return res; | |
1448 } | |
1449 | |
1450 /* | |
1451 * gg_image_reply() | |
1452 * | |
1453 * wysyła żądany obrazek. | |
1454 * | |
1455 * - sess - opis sesji | |
1456 * - recipient - numer adresata | |
1457 * - filename - nazwa pliku | |
1458 * - image - bufor z obrazkiem | |
1459 * - size - rozmiar obrazka | |
1460 * | |
1461 * 0/-1 | |
1462 */ | |
12218
9cbc5967fbfd
[gaim-migrate @ 14520]
Richard Laager <rlaager@wiktel.com>
parents:
12007
diff
changeset
|
1463 int gg_image_reply(struct gg_session *sess, uin_t recipient, const char *filename, const unsigned char *image, int size) |
11360 | 1464 { |
1465 struct gg_msg_image_reply *r; | |
1466 struct gg_send_msg s; | |
1467 const char *tmp; | |
1468 char buf[1910]; | |
1469 int res = -1; | |
1470 | |
1471 gg_debug(GG_DEBUG_FUNCTION, "** gg_image_reply(%p, %d, \"%s\", %p, %d);\n", sess, recipient, filename, image, size); | |
1472 | |
1473 if (!sess || !filename || !image) { | |
1474 errno = EFAULT; | |
1475 return -1; | |
1476 } | |
1477 | |
1478 if (sess->state != GG_STATE_CONNECTED) { | |
1479 errno = ENOTCONN; | |
1480 return -1; | |
1481 } | |
1482 | |
1483 if (size < 0) { | |
1484 errno = EINVAL; | |
1485 return -1; | |
1486 } | |
1487 | |
1488 /* wytnij ścieżki, zostaw tylko nazwę pliku */ | |
1489 while ((tmp = strrchr(filename, '/')) || (tmp = strrchr(filename, '\\'))) | |
1490 filename = tmp + 1; | |
1491 | |
1492 if (strlen(filename) < 1 || strlen(filename) > 1024) { | |
1493 errno = EINVAL; | |
1494 return -1; | |
1495 } | |
1496 | |
1497 s.recipient = gg_fix32(recipient); | |
1498 s.seq = gg_fix32(0); | |
1499 s.msgclass = gg_fix32(GG_CLASS_MSG); | |
1500 | |
1501 buf[0] = 0; | |
1502 r = (void*) &buf[1]; | |
1503 | |
1504 r->flag = 0x05; | |
1505 r->size = gg_fix32(size); | |
1506 r->crc32 = gg_fix32(gg_crc32(0, image, size)); | |
1507 | |
1508 while (size > 0) { | |
12218
9cbc5967fbfd
[gaim-migrate @ 14520]
Richard Laager <rlaager@wiktel.com>
parents:
12007
diff
changeset
|
1509 size_t buflen, chunklen; |
11360 | 1510 |
1511 /* \0 + struct gg_msg_image_reply */ | |
1512 buflen = sizeof(struct gg_msg_image_reply) + 1; | |
1513 | |
1514 /* w pierwszym kawałku jest nazwa pliku */ | |
1515 if (r->flag == 0x05) { | |
1516 strcpy(buf + buflen, filename); | |
1517 buflen += strlen(filename) + 1; | |
1518 } | |
1519 | |
12218
9cbc5967fbfd
[gaim-migrate @ 14520]
Richard Laager <rlaager@wiktel.com>
parents:
12007
diff
changeset
|
1520 chunklen = ((size_t)size >= sizeof(buf) - buflen) ? (sizeof(buf) - buflen) : (size_t)size; |
11360 | 1521 |
1522 memcpy(buf + buflen, image, chunklen); | |
1523 size -= chunklen; | |
1524 image += chunklen; | |
1525 | |
1526 res = gg_send_packet(sess, GG_SEND_MSG, &s, sizeof(s), buf, buflen + chunklen, NULL); | |
1527 | |
1528 if (res == -1) | |
1529 break; | |
1530 | |
1531 r->flag = 0x06; | |
1532 } | |
1533 | |
1534 return res; | |
1535 } | |
1536 | |
1537 /* | |
1538 * gg_send_message_ctcp() | |
1539 * | |
1540 * wysyła wiadomość do innego użytkownika. zwraca losowy numer | |
1541 * sekwencyjny, który można zignorować albo wykorzystać do potwierdzenia. | |
1542 * | |
1543 * - sess - opis sesji | |
1544 * - msgclass - rodzaj wiadomości | |
1545 * - recipient - numer adresata | |
1546 * - message - treść wiadomości | |
1547 * - message_len - długość | |
1548 * | |
1549 * numer sekwencyjny wiadomości lub -1 w przypadku błędu. | |
1550 */ | |
1551 int gg_send_message_ctcp(struct gg_session *sess, int msgclass, uin_t recipient, const unsigned char *message, int message_len) | |
1552 { | |
1553 struct gg_send_msg s; | |
1554 | |
1555 gg_debug(GG_DEBUG_FUNCTION, "** gg_send_message_ctcp(%p, %d, %u, ...);\n", sess, msgclass, recipient); | |
1556 | |
1557 if (!sess) { | |
1558 errno = EFAULT; | |
1559 return -1; | |
1560 } | |
1561 | |
1562 if (sess->state != GG_STATE_CONNECTED) { | |
1563 errno = ENOTCONN; | |
1564 return -1; | |
1565 } | |
1566 | |
1567 s.recipient = gg_fix32(recipient); | |
1568 s.seq = gg_fix32(0); | |
1569 s.msgclass = gg_fix32(msgclass); | |
1570 | |
1571 return gg_send_packet(sess, GG_SEND_MSG, &s, sizeof(s), message, message_len, NULL); | |
1572 } | |
1573 | |
1574 /* | |
1575 * gg_send_message() | |
1576 * | |
1577 * wysyła wiadomość do innego użytkownika. zwraca losowy numer | |
1578 * sekwencyjny, który można zignorować albo wykorzystać do potwierdzenia. | |
1579 * | |
1580 * - sess - opis sesji | |
1581 * - msgclass - rodzaj wiadomości | |
1582 * - recipient - numer adresata | |
1583 * - message - treść wiadomości | |
1584 * | |
1585 * numer sekwencyjny wiadomości lub -1 w przypadku błędu. | |
1586 */ | |
1587 int gg_send_message(struct gg_session *sess, int msgclass, uin_t recipient, const unsigned char *message) | |
1588 { | |
1589 gg_debug(GG_DEBUG_FUNCTION, "** gg_send_message(%p, %d, %u, %p)\n", sess, msgclass, recipient, message); | |
1590 | |
1591 return gg_send_message_richtext(sess, msgclass, recipient, message, NULL, 0); | |
1592 } | |
1593 | |
1594 /* | |
1595 * gg_send_message_richtext() | |
1596 * | |
1597 * wysyła kolorową wiadomość do innego użytkownika. zwraca losowy numer | |
1598 * sekwencyjny, który można zignorować albo wykorzystać do potwierdzenia. | |
1599 * | |
1600 * - sess - opis sesji | |
1601 * - msgclass - rodzaj wiadomości | |
1602 * - recipient - numer adresata | |
1603 * - message - treść wiadomości | |
1604 * - format - informacje o formatowaniu | |
1605 * - formatlen - długość informacji o formatowaniu | |
1606 * | |
1607 * numer sekwencyjny wiadomości lub -1 w przypadku błędu. | |
1608 */ | |
1609 int gg_send_message_richtext(struct gg_session *sess, int msgclass, uin_t recipient, const unsigned char *message, const unsigned char *format, int formatlen) | |
1610 { | |
1611 struct gg_send_msg s; | |
1612 | |
1613 gg_debug(GG_DEBUG_FUNCTION, "** gg_send_message_richtext(%p, %d, %u, %p, %p, %d);\n", sess, msgclass, recipient, message, format, formatlen); | |
1614 | |
1615 if (!sess) { | |
1616 errno = EFAULT; | |
1617 return -1; | |
1618 } | |
1619 | |
1620 if (sess->state != GG_STATE_CONNECTED) { | |
1621 errno = ENOTCONN; | |
1622 return -1; | |
1623 } | |
1624 | |
1625 if (!message) { | |
1626 errno = EFAULT; | |
1627 return -1; | |
1628 } | |
1629 | |
1630 s.recipient = gg_fix32(recipient); | |
1631 if (!sess->seq) | |
1632 sess->seq = 0x01740000 | (rand() & 0xffff); | |
1633 s.seq = gg_fix32(sess->seq); | |
1634 s.msgclass = gg_fix32(msgclass); | |
1635 sess->seq += (rand() % 0x300) + 0x300; | |
1636 | |
12218
9cbc5967fbfd
[gaim-migrate @ 14520]
Richard Laager <rlaager@wiktel.com>
parents:
12007
diff
changeset
|
1637 if (gg_send_packet(sess, GG_SEND_MSG, &s, sizeof(s), message, strlen((const char *)message) + 1, format, formatlen, NULL) == -1) |
11360 | 1638 return -1; |
1639 | |
1640 return gg_fix32(s.seq); | |
1641 } | |
1642 | |
1643 /* | |
1644 * gg_send_message_confer() | |
1645 * | |
1646 * wysyła wiadomość do kilku użytkownikow (konferencja). zwraca losowy numer | |
1647 * sekwencyjny, który można zignorować albo wykorzystać do potwierdzenia. | |
1648 * | |
1649 * - sess - opis sesji | |
1650 * - msgclass - rodzaj wiadomości | |
1651 * - recipients_count - ilość adresatów | |
1652 * - recipients - numerki adresatów | |
1653 * - message - treść wiadomości | |
1654 * | |
1655 * numer sekwencyjny wiadomości lub -1 w przypadku błędu. | |
1656 */ | |
1657 int gg_send_message_confer(struct gg_session *sess, int msgclass, int recipients_count, uin_t *recipients, const unsigned char *message) | |
1658 { | |
1659 gg_debug(GG_DEBUG_FUNCTION, "** gg_send_message_confer(%p, %d, %d, %p, %p);\n", sess, msgclass, recipients_count, recipients, message); | |
1660 | |
1661 return gg_send_message_confer_richtext(sess, msgclass, recipients_count, recipients, message, NULL, 0); | |
1662 } | |
1663 | |
1664 /* | |
1665 * gg_send_message_confer_richtext() | |
1666 * | |
1667 * wysyła kolorową wiadomość do kilku użytkownikow (konferencja). zwraca | |
1668 * losowy numer sekwencyjny, który można zignorować albo wykorzystać do | |
1669 * potwierdzenia. | |
1670 * | |
1671 * - sess - opis sesji | |
1672 * - msgclass - rodzaj wiadomości | |
1673 * - recipients_count - ilość adresatów | |
1674 * - recipients - numerki adresatów | |
1675 * - message - treść wiadomości | |
1676 * - format - informacje o formatowaniu | |
1677 * - formatlen - długość informacji o formatowaniu | |
1678 * | |
1679 * numer sekwencyjny wiadomości lub -1 w przypadku błędu. | |
1680 */ | |
1681 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) | |
1682 { | |
1683 struct gg_send_msg s; | |
1684 struct gg_msg_recipients r; | |
1685 int i, j, k; | |
1686 uin_t *recps; | |
1687 | |
1688 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); | |
1689 | |
1690 if (!sess) { | |
1691 errno = EFAULT; | |
1692 return -1; | |
1693 } | |
1694 | |
1695 if (sess->state != GG_STATE_CONNECTED) { | |
1696 errno = ENOTCONN; | |
1697 return -1; | |
1698 } | |
1699 | |
1700 if (!message || recipients_count <= 0 || recipients_count > 0xffff || !recipients) { | |
1701 errno = EINVAL; | |
1702 return -1; | |
1703 } | |
1704 | |
1705 r.flag = 0x01; | |
1706 r.count = gg_fix32(recipients_count - 1); | |
1707 | |
1708 if (!sess->seq) | |
1709 sess->seq = 0x01740000 | (rand() & 0xffff); | |
1710 s.seq = gg_fix32(sess->seq); | |
1711 s.msgclass = gg_fix32(msgclass); | |
1712 | |
1713 recps = malloc(sizeof(uin_t) * recipients_count); | |
1714 if (!recps) | |
1715 return -1; | |
1716 | |
1717 for (i = 0; i < recipients_count; i++) { | |
1718 | |
1719 s.recipient = gg_fix32(recipients[i]); | |
1720 | |
1721 for (j = 0, k = 0; j < recipients_count; j++) | |
1722 if (recipients[j] != recipients[i]) { | |
1723 recps[k] = gg_fix32(recipients[j]); | |
1724 k++; | |
1725 } | |
1726 | |
1727 if (!i) | |
1728 sess->seq += (rand() % 0x300) + 0x300; | |
1729 | |
12218
9cbc5967fbfd
[gaim-migrate @ 14520]
Richard Laager <rlaager@wiktel.com>
parents:
12007
diff
changeset
|
1730 if (gg_send_packet(sess, GG_SEND_MSG, &s, sizeof(s), message, strlen((const char *)message) + 1, &r, sizeof(r), recps, (recipients_count - 1) * sizeof(uin_t), format, formatlen, NULL) == -1) { |
11360 | 1731 free(recps); |
1732 return -1; | |
1733 } | |
1734 } | |
1735 | |
1736 free(recps); | |
1737 | |
1738 return gg_fix32(s.seq); | |
1739 } | |
1740 | |
1741 /* | |
1742 * gg_ping() | |
1743 * | |
1744 * wysyła do serwera pakiet ping. | |
1745 * | |
1746 * - sess - opis sesji | |
1747 * | |
1748 * 0, -1. | |
1749 */ | |
1750 int gg_ping(struct gg_session *sess) | |
1751 { | |
1752 gg_debug(GG_DEBUG_FUNCTION, "** gg_ping(%p);\n", sess); | |
1753 | |
1754 if (!sess) { | |
1755 errno = EFAULT; | |
1756 return -1; | |
1757 } | |
1758 | |
1759 if (sess->state != GG_STATE_CONNECTED) { | |
1760 errno = ENOTCONN; | |
1761 return -1; | |
1762 } | |
1763 | |
1764 return gg_send_packet(sess, GG_PING, NULL); | |
1765 } | |
1766 | |
1767 /* | |
1768 * gg_notify_ex() | |
1769 * | |
1770 * wysyła serwerowi listę kontaktów (wraz z odpowiadającymi im typami userów), | |
1771 * dzięki czemu wie, czyj stan nas interesuje. | |
1772 * | |
1773 * - sess - opis sesji | |
1774 * - userlist - wskaźnik do tablicy numerów | |
1775 * - types - wskaźnik do tablicy typów użytkowników | |
1776 * - count - ilość numerków | |
1777 * | |
1778 * 0, -1. | |
1779 */ | |
1780 int gg_notify_ex(struct gg_session *sess, uin_t *userlist, char *types, int count) | |
1781 { | |
1782 struct gg_notify *n; | |
1783 uin_t *u; | |
1784 char *t; | |
1785 int i, res = 0; | |
1786 | |
1787 gg_debug(GG_DEBUG_FUNCTION, "** gg_notify_ex(%p, %p, %p, %d);\n", sess, userlist, types, count); | |
1788 | |
1789 if (!sess) { | |
1790 errno = EFAULT; | |
1791 return -1; | |
1792 } | |
1793 | |
1794 if (sess->state != GG_STATE_CONNECTED) { | |
1795 errno = ENOTCONN; | |
1796 return -1; | |
1797 } | |
1798 | |
1799 if (!userlist || !count) | |
1800 return gg_send_packet(sess, GG_LIST_EMPTY, NULL); | |
1801 | |
1802 while (count > 0) { | |
1803 int part_count, packet_type; | |
1804 | |
1805 if (count > 400) { | |
1806 part_count = 400; | |
1807 packet_type = GG_NOTIFY_FIRST; | |
1808 } else { | |
1809 part_count = count; | |
1810 packet_type = GG_NOTIFY_LAST; | |
1811 } | |
1812 | |
1813 if (!(n = (struct gg_notify*) malloc(sizeof(*n) * part_count))) | |
1814 return -1; | |
1815 | |
1816 for (u = userlist, t = types, i = 0; i < part_count; u++, t++, i++) { | |
1817 n[i].uin = gg_fix32(*u); | |
1818 n[i].dunno1 = *t; | |
1819 } | |
1820 | |
1821 if (gg_send_packet(sess, packet_type, n, sizeof(*n) * part_count, NULL) == -1) { | |
1822 free(n); | |
1823 res = -1; | |
1824 break; | |
1825 } | |
1826 | |
1827 count -= part_count; | |
1828 userlist += part_count; | |
1829 types += part_count; | |
1830 | |
1831 free(n); | |
1832 } | |
1833 | |
1834 return res; | |
1835 } | |
1836 | |
1837 /* | |
1838 * gg_notify() | |
1839 * | |
1840 * wysyła serwerowi listę kontaktów, dzięki czemu wie, czyj stan nas | |
1841 * interesuje. | |
1842 * | |
1843 * - sess - opis sesji | |
1844 * - userlist - wskaźnik do tablicy numerów | |
1845 * - count - ilość numerków | |
1846 * | |
1847 * 0, -1. | |
1848 */ | |
1849 int gg_notify(struct gg_session *sess, uin_t *userlist, int count) | |
1850 { | |
1851 struct gg_notify *n; | |
1852 uin_t *u; | |
1853 int i, res = 0; | |
1854 | |
1855 gg_debug(GG_DEBUG_FUNCTION, "** gg_notify(%p, %p, %d);\n", sess, userlist, count); | |
1856 | |
1857 if (!sess) { | |
1858 errno = EFAULT; | |
1859 return -1; | |
1860 } | |
1861 | |
1862 if (sess->state != GG_STATE_CONNECTED) { | |
1863 errno = ENOTCONN; | |
1864 return -1; | |
1865 } | |
1866 | |
1867 if (!userlist || !count) | |
1868 return gg_send_packet(sess, GG_LIST_EMPTY, NULL); | |
1869 | |
1870 while (count > 0) { | |
1871 int part_count, packet_type; | |
1872 | |
1873 if (count > 400) { | |
1874 part_count = 400; | |
1875 packet_type = GG_NOTIFY_FIRST; | |
1876 } else { | |
1877 part_count = count; | |
1878 packet_type = GG_NOTIFY_LAST; | |
1879 } | |
1880 | |
1881 if (!(n = (struct gg_notify*) malloc(sizeof(*n) * part_count))) | |
1882 return -1; | |
1883 | |
1884 for (u = userlist, i = 0; i < part_count; u++, i++) { | |
1885 n[i].uin = gg_fix32(*u); | |
1886 n[i].dunno1 = GG_USER_NORMAL; | |
1887 } | |
1888 | |
1889 if (gg_send_packet(sess, packet_type, n, sizeof(*n) * part_count, NULL) == -1) { | |
1890 res = -1; | |
1891 free(n); | |
1892 break; | |
1893 } | |
1894 | |
1895 free(n); | |
1896 | |
1897 userlist += part_count; | |
1898 count -= part_count; | |
1899 } | |
1900 | |
1901 return res; | |
1902 } | |
1903 | |
1904 /* | |
1905 * gg_add_notify_ex() | |
1906 * | |
1907 * dodaje do listy kontaktów dany numer w trakcie połączenia. | |
1908 * dodawanemu użytkownikowi określamy jego typ (patrz protocol.html) | |
1909 * | |
1910 * - sess - opis sesji | |
1911 * - uin - numer | |
1912 * - type - typ | |
1913 * | |
1914 * 0, -1. | |
1915 */ | |
1916 int gg_add_notify_ex(struct gg_session *sess, uin_t uin, char type) | |
1917 { | |
1918 struct gg_add_remove a; | |
1919 | |
1920 gg_debug(GG_DEBUG_FUNCTION, "** gg_add_notify_ex(%p, %u, %d);\n", sess, uin, type); | |
1921 | |
1922 if (!sess) { | |
1923 errno = EFAULT; | |
1924 return -1; | |
1925 } | |
1926 | |
1927 if (sess->state != GG_STATE_CONNECTED) { | |
1928 errno = ENOTCONN; | |
1929 return -1; | |
1930 } | |
1931 | |
1932 a.uin = gg_fix32(uin); | |
1933 a.dunno1 = type; | |
1934 | |
1935 return gg_send_packet(sess, GG_ADD_NOTIFY, &a, sizeof(a), NULL); | |
1936 } | |
1937 | |
1938 /* | |
1939 * gg_add_notify() | |
1940 * | |
1941 * dodaje do listy kontaktów dany numer w trakcie połączenia. | |
1942 * | |
1943 * - sess - opis sesji | |
1944 * - uin - numer | |
1945 * | |
1946 * 0, -1. | |
1947 */ | |
1948 int gg_add_notify(struct gg_session *sess, uin_t uin) | |
1949 { | |
1950 return gg_add_notify_ex(sess, uin, GG_USER_NORMAL); | |
1951 } | |
1952 | |
1953 /* | |
1954 * gg_remove_notify_ex() | |
1955 * | |
1956 * usuwa z listy kontaktów w trakcie połączenia. | |
1957 * usuwanemu użytkownikowi określamy jego typ (patrz protocol.html) | |
1958 * | |
1959 * - sess - opis sesji | |
1960 * - uin - numer | |
1961 * - type - typ | |
1962 * | |
1963 * 0, -1. | |
1964 */ | |
1965 int gg_remove_notify_ex(struct gg_session *sess, uin_t uin, char type) | |
1966 { | |
1967 struct gg_add_remove a; | |
1968 | |
1969 gg_debug(GG_DEBUG_FUNCTION, "** gg_remove_notify_ex(%p, %u, %d);\n", sess, uin, type); | |
1970 | |
1971 if (!sess) { | |
1972 errno = EFAULT; | |
1973 return -1; | |
1974 } | |
1975 | |
1976 if (sess->state != GG_STATE_CONNECTED) { | |
1977 errno = ENOTCONN; | |
1978 return -1; | |
1979 } | |
1980 | |
1981 a.uin = gg_fix32(uin); | |
1982 a.dunno1 = type; | |
1983 | |
1984 return gg_send_packet(sess, GG_REMOVE_NOTIFY, &a, sizeof(a), NULL); | |
1985 } | |
1986 | |
1987 /* | |
1988 * gg_remove_notify() | |
1989 * | |
1990 * usuwa z listy kontaktów w trakcie połączenia. | |
1991 * | |
1992 * - sess - opis sesji | |
1993 * - uin - numer | |
1994 * | |
1995 * 0, -1. | |
1996 */ | |
1997 int gg_remove_notify(struct gg_session *sess, uin_t uin) | |
1998 { | |
1999 return gg_remove_notify_ex(sess, uin, GG_USER_NORMAL); | |
2000 } | |
2001 | |
2002 /* | |
2003 * gg_userlist_request() | |
2004 * | |
2005 * wysyła żądanie/zapytanie listy kontaktów na serwerze. | |
2006 * | |
2007 * - sess - opis sesji | |
2008 * - type - rodzaj zapytania/żądania | |
2009 * - request - treść zapytania/żądania (może być NULL) | |
2010 * | |
2011 * 0, -1 | |
2012 */ | |
2013 int gg_userlist_request(struct gg_session *sess, char type, const char *request) | |
2014 { | |
2015 int len; | |
2016 | |
2017 if (!sess) { | |
2018 errno = EFAULT; | |
2019 return -1; | |
2020 } | |
2021 | |
2022 if (sess->state != GG_STATE_CONNECTED) { | |
2023 errno = ENOTCONN; | |
2024 return -1; | |
2025 } | |
2026 | |
2027 if (!request) { | |
2028 sess->userlist_blocks = 1; | |
2029 return gg_send_packet(sess, GG_USERLIST_REQUEST, &type, sizeof(type), NULL); | |
2030 } | |
2031 | |
2032 len = strlen(request); | |
2033 | |
2034 sess->userlist_blocks = 0; | |
2035 | |
2036 while (len > 2047) { | |
2037 sess->userlist_blocks++; | |
2038 | |
2039 if (gg_send_packet(sess, GG_USERLIST_REQUEST, &type, sizeof(type), request, 2047, NULL) == -1) | |
2040 return -1; | |
2041 | |
2042 if (type == GG_USERLIST_PUT) | |
2043 type = GG_USERLIST_PUT_MORE; | |
2044 | |
2045 request += 2047; | |
2046 len -= 2047; | |
2047 } | |
2048 | |
2049 sess->userlist_blocks++; | |
2050 | |
2051 return gg_send_packet(sess, GG_USERLIST_REQUEST, &type, sizeof(type), request, len, NULL); | |
2052 } | |
2053 | |
2054 /* | |
2055 * Local variables: | |
2056 * c-indentation-style: k&r | |
2057 * c-basic-offset: 8 | |
2058 * indent-tabs-mode: notnil | |
2059 * End: | |
2060 * | |
2061 * vim: shiftwidth=8: | |
2062 */ |