Statistics
| Revision:

root / libsylph / socket.c @ 2031

History | View | Annotate | Download (34.7 kB)

1 528 hiro
/*
2 578 hiro
 * LibSylph -- E-Mail client library
3 1499 hiro
 * Copyright (C) 1999-2007 Hiroyuki Yamamoto
4 528 hiro
 *
5 578 hiro
 * This library is free software; you can redistribute it and/or
6 578 hiro
 * modify it under the terms of the GNU Lesser General Public
7 578 hiro
 * License as published by the Free Software Foundation; either
8 578 hiro
 * version 2.1 of the License, or (at your option) any later version.
9 528 hiro
 *
10 578 hiro
 * This library is distributed in the hope that it will be useful,
11 528 hiro
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 578 hiro
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13 578 hiro
 * Lesser General Public License for more details.
14 528 hiro
 *
15 578 hiro
 * You should have received a copy of the GNU Lesser General Public
16 578 hiro
 * License along with this library; if not, write to the Free Software
17 578 hiro
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
18 528 hiro
 */
19 528 hiro
20 528 hiro
#ifdef HAVE_CONFIG_H
21 528 hiro
#  include "config.h"
22 528 hiro
#endif
23 528 hiro
24 528 hiro
#include <glib.h>
25 528 hiro
#include <sys/time.h>
26 528 hiro
#include <sys/types.h>
27 528 hiro
#ifdef G_OS_WIN32
28 528 hiro
#  include <winsock2.h>
29 932 hiro
#  include <ws2tcpip.h>
30 528 hiro
#else
31 528 hiro
#  if HAVE_SYS_WAIT_H
32 528 hiro
#    include <sys/wait.h>
33 528 hiro
#  endif
34 528 hiro
#  include <sys/socket.h>
35 528 hiro
#  include <sys/un.h>
36 528 hiro
#  include <netinet/in.h>
37 528 hiro
#  include <arpa/inet.h>
38 1418 hiro
#  include <resolv.h>
39 528 hiro
#  include <netdb.h>
40 1418 hiro
#  include <sys/stat.h>
41 528 hiro
#endif /* G_OS_WIN32 */
42 528 hiro
#include <unistd.h>
43 528 hiro
#include <stdio.h>
44 528 hiro
#include <string.h>
45 528 hiro
#include <stdarg.h>
46 528 hiro
#include <fcntl.h>
47 528 hiro
#include <errno.h>
48 528 hiro
#include <signal.h>
49 528 hiro
#include <setjmp.h>
50 528 hiro
#if HAVE_SYS_SELECT_H
51 528 hiro
#  include <sys/select.h>
52 528 hiro
#endif
53 528 hiro
54 528 hiro
#include "socket.h"
55 528 hiro
#if USE_SSL
56 528 hiro
#  include "ssl.h"
57 528 hiro
#endif
58 528 hiro
59 1456 hiro
#include "utils.h"
60 1456 hiro
61 528 hiro
#define BUFFSIZE        8192
62 528 hiro
63 941 hiro
#ifdef G_OS_WIN32
64 941 hiro
#define SockDesc                SOCKET
65 941 hiro
#define SOCKET_IS_VALID(s)        ((s) != INVALID_SOCKET)
66 941 hiro
#else
67 941 hiro
#define SockDesc                gint
68 941 hiro
#define SOCKET_IS_VALID(s)        ((s) >= 0)
69 941 hiro
#define INVALID_SOCKET                (-1)
70 941 hiro
#endif
71 941 hiro
72 528 hiro
typedef gint (*SockAddrFunc)        (GList                *addr_list,
73 528 hiro
                                 gpointer         data);
74 528 hiro
75 528 hiro
typedef struct _SockConnectData        SockConnectData;
76 528 hiro
typedef struct _SockLookupData        SockLookupData;
77 528 hiro
typedef struct _SockAddrData        SockAddrData;
78 528 hiro
typedef struct _SockSource        SockSource;
79 528 hiro
80 528 hiro
struct _SockConnectData {
81 528 hiro
        gint id;
82 528 hiro
        gchar *hostname;
83 528 hiro
        gushort port;
84 528 hiro
        GList *addr_list;
85 528 hiro
        GList *cur_addr;
86 528 hiro
        SockLookupData *lookup_data;
87 528 hiro
        GIOChannel *channel;
88 528 hiro
        guint io_tag;
89 528 hiro
        SockConnectFunc func;
90 528 hiro
        gpointer data;
91 528 hiro
};
92 528 hiro
93 528 hiro
struct _SockLookupData {
94 528 hiro
        gchar *hostname;
95 528 hiro
        pid_t child_pid;
96 528 hiro
        GIOChannel *channel;
97 528 hiro
        guint io_tag;
98 528 hiro
        SockAddrFunc func;
99 528 hiro
        gpointer data;
100 528 hiro
};
101 528 hiro
102 528 hiro
struct _SockAddrData {
103 528 hiro
        gint family;
104 528 hiro
        gint socktype;
105 528 hiro
        gint protocol;
106 528 hiro
        gint addr_len;
107 528 hiro
        struct sockaddr *addr;
108 528 hiro
};
109 528 hiro
110 528 hiro
struct _SockSource {
111 528 hiro
        GSource parent;
112 528 hiro
        SockInfo *sock;
113 528 hiro
};
114 528 hiro
115 528 hiro
static guint io_timeout = 60;
116 528 hiro
117 528 hiro
static GList *sock_connect_data_list = NULL;
118 1230 hiro
static GList *sock_list = NULL;
119 528 hiro
120 528 hiro
static gboolean sock_prepare                (GSource        *source,
121 528 hiro
                                         gint                *timeout);
122 528 hiro
static gboolean sock_check                (GSource        *source);
123 528 hiro
static gboolean sock_dispatch                (GSource        *source,
124 528 hiro
                                         GSourceFunc         callback,
125 528 hiro
                                         gpointer         user_data);
126 528 hiro
127 528 hiro
GSourceFuncs sock_watch_funcs = {
128 528 hiro
        sock_prepare,
129 528 hiro
        sock_check,
130 528 hiro
        sock_dispatch,
131 528 hiro
        NULL
132 528 hiro
};
133 528 hiro
134 1230 hiro
static SockInfo *sock_find_from_fd        (gint        fd);
135 1230 hiro
136 528 hiro
static gint sock_connect_with_timeout        (gint                         sock,
137 528 hiro
                                         const struct sockaddr        *serv_addr,
138 528 hiro
                                         gint                         addrlen,
139 528 hiro
                                         guint                         timeout_secs);
140 528 hiro
141 528 hiro
#ifndef INET6
142 528 hiro
static gint sock_connect_by_hostname        (gint                 sock,
143 528 hiro
                                         const gchar        *hostname,
144 528 hiro
                                         gushort         port);
145 528 hiro
#else
146 941 hiro
static SockDesc sock_connect_by_getaddrinfo        (const gchar        *hostname,
147 941 hiro
                                                 gushort         port);
148 528 hiro
#endif
149 528 hiro
150 528 hiro
#ifdef G_OS_UNIX
151 528 hiro
static void sock_address_list_free                (GList                *addr_list);
152 528 hiro
153 528 hiro
static gboolean sock_connect_async_cb                (GIOChannel        *source,
154 528 hiro
                                                 GIOCondition         condition,
155 528 hiro
                                                 gpointer         data);
156 528 hiro
static gint sock_connect_async_get_address_info_cb
157 528 hiro
                                                (GList                *addr_list,
158 528 hiro
                                                 gpointer         data);
159 528 hiro
160 528 hiro
static gint sock_connect_address_list_async        (SockConnectData *conn_data);
161 528 hiro
162 528 hiro
static gboolean sock_get_address_info_async_cb        (GIOChannel        *source,
163 528 hiro
                                                 GIOCondition         condition,
164 528 hiro
                                                 gpointer         data);
165 528 hiro
static SockLookupData *sock_get_address_info_async
166 528 hiro
                                                (const gchar        *hostname,
167 528 hiro
                                                 gushort         port,
168 528 hiro
                                                 SockAddrFunc         func,
169 528 hiro
                                                 gpointer         data);
170 528 hiro
static gint sock_get_address_info_async_cancel        (SockLookupData        *lookup_data);
171 528 hiro
#endif /* G_OS_UNIX */
172 528 hiro
173 528 hiro
174 528 hiro
gint sock_init(void)
175 528 hiro
{
176 528 hiro
#ifdef G_OS_WIN32
177 528 hiro
        WSADATA wsadata;
178 528 hiro
        gint result;
179 528 hiro
180 528 hiro
        result = WSAStartup(MAKEWORD(2, 2), &wsadata);
181 528 hiro
        if (result != NO_ERROR) {
182 528 hiro
                g_warning("WSAStartup() failed\n");
183 528 hiro
                return -1;
184 528 hiro
        }
185 528 hiro
#endif
186 528 hiro
        return 0;
187 528 hiro
}
188 528 hiro
189 528 hiro
gint sock_cleanup(void)
190 528 hiro
{
191 528 hiro
#ifdef G_OS_WIN32
192 528 hiro
        WSACleanup();
193 528 hiro
#endif
194 528 hiro
        return 0;
195 528 hiro
}
196 528 hiro
197 528 hiro
gint sock_set_io_timeout(guint sec)
198 528 hiro
{
199 528 hiro
        io_timeout = sec;
200 528 hiro
        return 0;
201 528 hiro
}
202 528 hiro
203 692 hiro
gint fd_connect_inet(gushort port)
204 692 hiro
{
205 941 hiro
        SockDesc sock;
206 692 hiro
        struct sockaddr_in addr;
207 692 hiro
208 941 hiro
        sock = socket(AF_INET, SOCK_STREAM, 0);
209 941 hiro
        if (!SOCKET_IS_VALID(sock)) {
210 692 hiro
#ifdef G_OS_WIN32
211 692 hiro
                g_warning("fd_connect_inet(): socket() failed: %ld\n",
212 692 hiro
                          WSAGetLastError());
213 692 hiro
#else
214 692 hiro
                perror("fd_connect_inet(): socket");
215 692 hiro
#endif
216 692 hiro
                return -1;
217 692 hiro
        }
218 692 hiro
219 692 hiro
        memset(&addr, 0, sizeof(addr));
220 692 hiro
        addr.sin_family = AF_INET;
221 692 hiro
        addr.sin_port = htons(port);
222 692 hiro
        addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
223 692 hiro
224 692 hiro
        if (connect(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
225 692 hiro
                fd_close(sock);
226 692 hiro
                return -1;
227 692 hiro
        }
228 692 hiro
229 692 hiro
        return sock;
230 692 hiro
}
231 692 hiro
232 692 hiro
gint fd_open_inet(gushort port)
233 692 hiro
{
234 941 hiro
        SockDesc sock;
235 692 hiro
        struct sockaddr_in addr;
236 692 hiro
        gint val;
237 692 hiro
238 941 hiro
        sock = socket(AF_INET, SOCK_STREAM, 0);
239 941 hiro
        if (!SOCKET_IS_VALID(sock)) {
240 692 hiro
#ifdef G_OS_WIN32
241 692 hiro
                g_warning("fd_open_inet(): socket() failed: %ld\n",
242 692 hiro
                          WSAGetLastError());
243 692 hiro
#else
244 692 hiro
                perror("fd_open_inet(): socket");
245 692 hiro
#endif
246 692 hiro
                return -1;
247 692 hiro
        }
248 692 hiro
249 692 hiro
        val = 1;
250 1501 hiro
        if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *)&val,
251 1501 hiro
                       sizeof(val)) < 0) {
252 692 hiro
                perror("setsockopt");
253 692 hiro
                fd_close(sock);
254 692 hiro
                return -1;
255 692 hiro
        }
256 692 hiro
257 692 hiro
        memset(&addr, 0, sizeof(addr));
258 692 hiro
        addr.sin_family = AF_INET;
259 692 hiro
        addr.sin_port = htons(port);
260 692 hiro
        addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
261 692 hiro
262 692 hiro
        if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
263 692 hiro
                perror("bind");
264 692 hiro
                fd_close(sock);
265 692 hiro
                return -1;
266 692 hiro
        }
267 692 hiro
268 692 hiro
        if (listen(sock, 1) < 0) {
269 692 hiro
                perror("listen");
270 692 hiro
                fd_close(sock);
271 692 hiro
                return -1;
272 692 hiro
        }
273 692 hiro
274 692 hiro
        return sock;
275 692 hiro
}
276 692 hiro
277 528 hiro
gint fd_connect_unix(const gchar *path)
278 528 hiro
{
279 528 hiro
#ifdef G_OS_UNIX
280 528 hiro
        gint sock;
281 528 hiro
        struct sockaddr_un addr;
282 528 hiro
283 528 hiro
        sock = socket(PF_UNIX, SOCK_STREAM, 0);
284 528 hiro
        if (sock < 0) {
285 692 hiro
                perror("fd_connect_unix(): socket");
286 528 hiro
                return -1;
287 528 hiro
        }
288 528 hiro
289 528 hiro
        memset(&addr, 0, sizeof(addr));
290 528 hiro
        addr.sun_family = AF_UNIX;
291 528 hiro
        strncpy(addr.sun_path, path, sizeof(addr.sun_path) - 1);
292 528 hiro
293 528 hiro
        if (connect(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
294 528 hiro
                fd_close(sock);
295 528 hiro
                return -1;
296 528 hiro
        }
297 528 hiro
298 528 hiro
        return sock;
299 528 hiro
#else
300 528 hiro
        return -1;
301 528 hiro
#endif
302 528 hiro
}
303 528 hiro
304 528 hiro
gint fd_open_unix(const gchar *path)
305 528 hiro
{
306 528 hiro
#ifdef G_OS_UNIX
307 528 hiro
        gint sock;
308 528 hiro
        struct sockaddr_un addr;
309 692 hiro
        gint val;
310 528 hiro
311 528 hiro
        sock = socket(PF_UNIX, SOCK_STREAM, 0);
312 528 hiro
313 528 hiro
        if (sock < 0) {
314 528 hiro
                perror("sock_open_unix(): socket");
315 528 hiro
                return -1;
316 528 hiro
        }
317 528 hiro
318 692 hiro
        val = 1;
319 692 hiro
        if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)) < 0) {
320 692 hiro
                perror("setsockopt");
321 692 hiro
                fd_close(sock);
322 692 hiro
                return -1;
323 692 hiro
        }
324 692 hiro
325 528 hiro
        memset(&addr, 0, sizeof(addr));
326 528 hiro
        addr.sun_family = AF_UNIX;
327 528 hiro
        strncpy(addr.sun_path, path, sizeof(addr.sun_path) - 1);
328 528 hiro
329 528 hiro
        if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
330 528 hiro
                perror("bind");
331 528 hiro
                fd_close(sock);
332 528 hiro
                return -1;
333 528 hiro
        }
334 528 hiro
335 528 hiro
        if (listen(sock, 1) < 0) {
336 528 hiro
                perror("listen");
337 528 hiro
                fd_close(sock);
338 528 hiro
                return -1;
339 528 hiro
        }
340 528 hiro
341 528 hiro
        return sock;
342 528 hiro
#else
343 528 hiro
        return -1;
344 528 hiro
#endif
345 528 hiro
}
346 528 hiro
347 528 hiro
gint fd_accept(gint sock)
348 528 hiro
{
349 528 hiro
        struct sockaddr_in caddr;
350 528 hiro
        guint caddr_len;
351 528 hiro
352 528 hiro
        caddr_len = sizeof(caddr);
353 528 hiro
        return accept(sock, (struct sockaddr *)&caddr, &caddr_len);
354 528 hiro
}
355 528 hiro
356 1230 hiro
357 1230 hiro
static SockInfo *sock_find_from_fd(gint fd)
358 1230 hiro
{
359 1230 hiro
        GList *cur;
360 1230 hiro
361 1230 hiro
        for (cur = sock_list; cur != NULL; cur = cur->next) {
362 1230 hiro
                if (((SockInfo *)cur->data)->sock == fd)
363 1230 hiro
                        return (SockInfo *)cur->data;
364 1230 hiro
        }
365 1230 hiro
366 1230 hiro
        return NULL;
367 1230 hiro
}
368 1230 hiro
369 528 hiro
static gint set_nonblocking_mode(gint fd, gboolean nonblock)
370 528 hiro
{
371 1211 hiro
#ifdef G_OS_WIN32
372 1211 hiro
        gulong val = nonblock ? 1 : 0;
373 1230 hiro
        SockInfo *sock;
374 1211 hiro
375 1211 hiro
        if (!nonblock)
376 1211 hiro
                WSAEventSelect(fd, NULL, 0);
377 1211 hiro
        if (ioctlsocket(fd, FIONBIO, &val) == SOCKET_ERROR) {
378 1230 hiro
                g_warning("set_nonblocking_mode(): ioctlsocket() failed: %ld\n",
379 1230 hiro
                          WSAGetLastError());
380 1211 hiro
                return -1;
381 1211 hiro
        }
382 1230 hiro
383 1230 hiro
        sock = sock_find_from_fd(fd);
384 1500 hiro
        if (sock) {
385 1500 hiro
                if (nonblock) {
386 1500 hiro
                        SOCK_SET_FLAGS(sock->flags, SOCK_NONBLOCK);
387 1500 hiro
                } else {
388 1500 hiro
                        SOCK_UNSET_FLAGS(sock->flags, SOCK_NONBLOCK);
389 1500 hiro
                }
390 1500 hiro
        }
391 1211 hiro
        debug_print("set nonblocking mode to %d\n", nonblock);
392 1211 hiro
393 1211 hiro
        return 0;
394 1211 hiro
#else
395 528 hiro
        gint flags;
396 528 hiro
397 528 hiro
        flags = fcntl(fd, F_GETFL, 0);
398 528 hiro
        if (flags < 0) {
399 528 hiro
                perror("fcntl");
400 528 hiro
                return -1;
401 528 hiro
        }
402 528 hiro
403 528 hiro
        if (nonblock)
404 528 hiro
                flags |= O_NONBLOCK;
405 528 hiro
        else
406 528 hiro
                flags &= ~O_NONBLOCK;
407 528 hiro
408 528 hiro
        return fcntl(fd, F_SETFL, flags);
409 528 hiro
#endif
410 528 hiro
}
411 528 hiro
412 528 hiro
gint sock_set_nonblocking_mode(SockInfo *sock, gboolean nonblock)
413 528 hiro
{
414 1211 hiro
        gint ret;
415 1211 hiro
416 528 hiro
        g_return_val_if_fail(sock != NULL, -1);
417 528 hiro
418 1211 hiro
        ret = set_nonblocking_mode(sock->sock, nonblock);
419 1500 hiro
        if (ret == 0) {
420 1500 hiro
                if (nonblock) {
421 1500 hiro
                        SOCK_SET_FLAGS(sock->flags, SOCK_NONBLOCK);
422 1500 hiro
                } else {
423 1500 hiro
                        SOCK_UNSET_FLAGS(sock->flags, SOCK_NONBLOCK);
424 1500 hiro
                }
425 1500 hiro
        }
426 1211 hiro
427 1211 hiro
        return ret;
428 528 hiro
}
429 528 hiro
430 528 hiro
static gboolean is_nonblocking_mode(gint fd)
431 528 hiro
{
432 1230 hiro
#ifdef G_OS_WIN32
433 1230 hiro
        SockInfo *sock;
434 1230 hiro
435 1230 hiro
        sock = sock_find_from_fd(fd);
436 1500 hiro
        if (sock) {
437 1500 hiro
                return SOCK_IS_NONBLOCK(sock->flags);
438 1500 hiro
        }
439 1230 hiro
440 1230 hiro
        return FALSE;
441 1230 hiro
#else
442 528 hiro
        gint flags;
443 528 hiro
444 528 hiro
        flags = fcntl(fd, F_GETFL, 0);
445 528 hiro
        if (flags < 0) {
446 528 hiro
                perror("fcntl");
447 528 hiro
                return FALSE;
448 528 hiro
        }
449 528 hiro
450 528 hiro
        return ((flags & O_NONBLOCK) != 0);
451 528 hiro
#endif
452 528 hiro
}
453 528 hiro
454 528 hiro
gboolean sock_is_nonblocking_mode(SockInfo *sock)
455 528 hiro
{
456 528 hiro
        g_return_val_if_fail(sock != NULL, FALSE);
457 528 hiro
458 1211 hiro
#ifdef G_OS_WIN32
459 1500 hiro
        return SOCK_IS_NONBLOCK(sock->flags);
460 1211 hiro
#else
461 528 hiro
        return is_nonblocking_mode(sock->sock);
462 1211 hiro
#endif
463 528 hiro
}
464 528 hiro
465 1001 hiro
gboolean sock_has_read_data(SockInfo *sock)
466 1001 hiro
{
467 1001 hiro
#ifdef G_OS_WIN32
468 1001 hiro
        gulong val;
469 528 hiro
470 1001 hiro
#if USE_SSL
471 1001 hiro
        if (sock->ssl)
472 1001 hiro
                return TRUE;
473 1001 hiro
#endif
474 1230 hiro
        if (ioctlsocket(sock->sock, FIONREAD, &val) < 0) {
475 1230 hiro
                g_warning("sock_has_read_data(): ioctlsocket() failed: %ld\n",
476 1230 hiro
                          WSAGetLastError());
477 1001 hiro
                return TRUE;
478 1230 hiro
        }
479 1001 hiro
480 1001 hiro
        if (val == 0)
481 1001 hiro
                return FALSE;
482 1001 hiro
        else
483 1001 hiro
                return TRUE;
484 1001 hiro
#else
485 1001 hiro
        return TRUE;
486 1001 hiro
#endif
487 1001 hiro
}
488 1001 hiro
489 1001 hiro
490 528 hiro
static gboolean sock_prepare(GSource *source, gint *timeout)
491 528 hiro
{
492 528 hiro
        *timeout = 1;
493 528 hiro
        return FALSE;
494 528 hiro
}
495 528 hiro
496 528 hiro
static gboolean sock_check(GSource *source)
497 528 hiro
{
498 528 hiro
        SockInfo *sock = ((SockSource *)source)->sock;
499 528 hiro
        struct timeval timeout = {0, 0};
500 528 hiro
        fd_set fds;
501 528 hiro
        GIOCondition condition = sock->condition;
502 528 hiro
503 528 hiro
#if USE_SSL
504 528 hiro
        if (sock->ssl) {
505 528 hiro
                if (condition & G_IO_IN) {
506 528 hiro
                        if (SSL_pending(sock->ssl) > 0)
507 528 hiro
                                return TRUE;
508 528 hiro
                        if (SSL_want_write(sock->ssl))
509 528 hiro
                                condition |= G_IO_OUT;
510 528 hiro
                }
511 528 hiro
512 528 hiro
                if (condition & G_IO_OUT) {
513 528 hiro
                        if (SSL_want_read(sock->ssl))
514 528 hiro
                                condition |= G_IO_IN;
515 528 hiro
                }
516 528 hiro
        }
517 528 hiro
#endif
518 528 hiro
519 528 hiro
        FD_ZERO(&fds);
520 528 hiro
        FD_SET(sock->sock, &fds);
521 528 hiro
522 528 hiro
        select(sock->sock + 1,
523 528 hiro
               (condition & G_IO_IN)  ? &fds : NULL,
524 528 hiro
               (condition & G_IO_OUT) ? &fds : NULL,
525 528 hiro
               NULL, &timeout);
526 528 hiro
527 528 hiro
        return FD_ISSET(sock->sock, &fds) != 0;
528 528 hiro
}
529 528 hiro
530 528 hiro
static gboolean sock_dispatch(GSource *source, GSourceFunc callback,
531 528 hiro
                              gpointer user_data)
532 528 hiro
{
533 528 hiro
        SockInfo *sock = ((SockSource *)source)->sock;
534 528 hiro
535 528 hiro
        return sock->callback(sock, sock->condition, sock->data);
536 528 hiro
}
537 528 hiro
538 528 hiro
static gboolean sock_watch_cb(GIOChannel *source, GIOCondition condition,
539 528 hiro
                              gpointer data)
540 528 hiro
{
541 528 hiro
        SockInfo *sock = (SockInfo *)data;
542 528 hiro
543 528 hiro
        if ((condition & sock->condition) == 0)
544 528 hiro
                return TRUE;
545 528 hiro
546 528 hiro
        return sock->callback(sock, sock->condition, sock->data);
547 528 hiro
}
548 528 hiro
549 528 hiro
guint sock_add_watch(SockInfo *sock, GIOCondition condition, SockFunc func,
550 528 hiro
                     gpointer data)
551 528 hiro
{
552 528 hiro
        sock->callback = func;
553 528 hiro
        sock->condition = condition;
554 528 hiro
        sock->data = data;
555 528 hiro
556 528 hiro
#if USE_SSL
557 528 hiro
        if (sock->ssl) {
558 528 hiro
                GSource *source;
559 528 hiro
560 528 hiro
                source = g_source_new(&sock_watch_funcs, sizeof(SockSource));
561 528 hiro
                ((SockSource *)source)->sock = sock;
562 528 hiro
                g_source_set_priority(source, G_PRIORITY_DEFAULT);
563 528 hiro
                g_source_set_can_recurse(source, FALSE);
564 528 hiro
                return g_source_attach(source, NULL);
565 528 hiro
        }
566 528 hiro
#endif
567 528 hiro
568 528 hiro
        return g_io_add_watch(sock->sock_ch, condition, sock_watch_cb, sock);
569 528 hiro
}
570 528 hiro
571 1757 hiro
guint sock_add_watch_poll(SockInfo *sock, GIOCondition condition, SockFunc func,
572 1757 hiro
                          gpointer data)
573 1757 hiro
{
574 1757 hiro
        GSource *source;
575 1757 hiro
576 1757 hiro
        sock->callback = func;
577 1757 hiro
        sock->condition = condition;
578 1757 hiro
        sock->data = data;
579 1757 hiro
580 1757 hiro
        source = g_source_new(&sock_watch_funcs, sizeof(SockSource));
581 1757 hiro
        ((SockSource *)source)->sock = sock;
582 1757 hiro
        g_source_set_priority(source, G_PRIORITY_DEFAULT);
583 1757 hiro
        g_source_set_can_recurse(source, FALSE);
584 1757 hiro
585 1757 hiro
        return g_source_attach(source, NULL);
586 1757 hiro
}
587 1757 hiro
588 528 hiro
static gint fd_check_io(gint fd, GIOCondition cond)
589 528 hiro
{
590 528 hiro
        struct timeval timeout;
591 528 hiro
        fd_set fds;
592 1500 hiro
        SockInfo *sock;
593 528 hiro
594 1500 hiro
        sock = sock_find_from_fd(fd);
595 1500 hiro
        if (sock && !SOCK_IS_CHECK_IO(sock->flags))
596 528 hiro
                return 0;
597 528 hiro
598 528 hiro
        timeout.tv_sec  = io_timeout;
599 528 hiro
        timeout.tv_usec = 0;
600 528 hiro
601 528 hiro
        FD_ZERO(&fds);
602 528 hiro
        FD_SET(fd, &fds);
603 528 hiro
604 528 hiro
        if (cond == G_IO_IN) {
605 528 hiro
                select(fd + 1, &fds, NULL, NULL,
606 528 hiro
                       io_timeout > 0 ? &timeout : NULL);
607 528 hiro
        } else {
608 528 hiro
                select(fd + 1, NULL, &fds, NULL,
609 528 hiro
                       io_timeout > 0 ? &timeout : NULL);
610 528 hiro
        }
611 528 hiro
612 528 hiro
        if (FD_ISSET(fd, &fds)) {
613 528 hiro
                return 0;
614 528 hiro
        } else {
615 528 hiro
                g_warning("Socket IO timeout\n");
616 528 hiro
                return -1;
617 528 hiro
        }
618 528 hiro
}
619 528 hiro
620 528 hiro
#ifdef G_OS_UNIX
621 528 hiro
static sigjmp_buf jmpenv;
622 528 hiro
623 528 hiro
static void timeout_handler(gint sig)
624 528 hiro
{
625 528 hiro
        siglongjmp(jmpenv, 1);
626 528 hiro
}
627 528 hiro
#endif
628 528 hiro
629 528 hiro
static gint sock_connect_with_timeout(gint sock,
630 528 hiro
                                      const struct sockaddr *serv_addr,
631 528 hiro
                                      gint addrlen,
632 528 hiro
                                      guint timeout_secs)
633 528 hiro
{
634 528 hiro
        gint ret;
635 528 hiro
#ifdef G_OS_UNIX
636 528 hiro
        void (*prev_handler)(gint);
637 528 hiro
638 528 hiro
        alarm(0);
639 528 hiro
        prev_handler = signal(SIGALRM, timeout_handler);
640 528 hiro
        if (sigsetjmp(jmpenv, 1)) {
641 528 hiro
                alarm(0);
642 528 hiro
                signal(SIGALRM, prev_handler);
643 528 hiro
                errno = ETIMEDOUT;
644 528 hiro
                return -1;
645 528 hiro
        }
646 528 hiro
        alarm(timeout_secs);
647 528 hiro
#endif
648 528 hiro
649 528 hiro
        ret = connect(sock, serv_addr, addrlen);
650 528 hiro
651 528 hiro
#ifdef G_OS_UNIX
652 528 hiro
        alarm(0);
653 528 hiro
        signal(SIGALRM, prev_handler);
654 528 hiro
#endif
655 528 hiro
656 528 hiro
        return ret;
657 528 hiro
}
658 528 hiro
659 1418 hiro
static void resolver_init(void)
660 1418 hiro
{
661 1418 hiro
#ifdef G_OS_UNIX
662 1418 hiro
        static time_t resolv_conf_mtime = 0;
663 1418 hiro
        struct stat s;
664 1418 hiro
665 1418 hiro
        if (g_stat("/etc/resolv.conf", &s) == 0 &&
666 1418 hiro
            s.st_mtime != resolv_conf_mtime) {
667 1418 hiro
                debug_print("Reloading /etc/resolv.conf\n");
668 1418 hiro
                resolv_conf_mtime = s.st_mtime;
669 1418 hiro
                res_init();
670 1418 hiro
        }
671 1418 hiro
#endif
672 1418 hiro
}
673 1418 hiro
674 528 hiro
struct hostent *my_gethostbyname(const gchar *hostname)
675 528 hiro
{
676 528 hiro
        struct hostent *hp;
677 528 hiro
#ifdef G_OS_UNIX
678 528 hiro
        void (*prev_handler)(gint);
679 528 hiro
680 528 hiro
        alarm(0);
681 528 hiro
        prev_handler = signal(SIGALRM, timeout_handler);
682 528 hiro
        if (sigsetjmp(jmpenv, 1)) {
683 528 hiro
                alarm(0);
684 528 hiro
                signal(SIGALRM, prev_handler);
685 528 hiro
                fprintf(stderr, "%s: host lookup timed out.\n", hostname);
686 528 hiro
                errno = 0;
687 528 hiro
                return NULL;
688 528 hiro
        }
689 528 hiro
        alarm(io_timeout);
690 528 hiro
#endif
691 528 hiro
692 528 hiro
        if ((hp = gethostbyname(hostname)) == NULL) {
693 528 hiro
#ifdef G_OS_UNIX
694 528 hiro
                alarm(0);
695 528 hiro
                signal(SIGALRM, prev_handler);
696 528 hiro
#endif
697 528 hiro
                fprintf(stderr, "%s: unknown host.\n", hostname);
698 528 hiro
                errno = 0;
699 528 hiro
                return NULL;
700 528 hiro
        }
701 528 hiro
702 528 hiro
#ifdef G_OS_UNIX
703 528 hiro
        alarm(0);
704 528 hiro
        signal(SIGALRM, prev_handler);
705 528 hiro
#endif
706 528 hiro
707 528 hiro
        return hp;
708 528 hiro
}
709 528 hiro
710 1499 hiro
static void sock_set_buffer_size(gint sock)
711 1499 hiro
{
712 1499 hiro
#ifdef G_OS_WIN32
713 1500 hiro
        gint val;
714 1499 hiro
        guint len = sizeof(val);
715 1499 hiro
716 1500 hiro
#define SOCK_BUFFSIZE        32768
717 1500 hiro
718 1499 hiro
        getsockopt(sock, SOL_SOCKET, SO_SNDBUF, (char *)&val, &len);
719 1500 hiro
        if (val < SOCK_BUFFSIZE) {
720 1500 hiro
                val = SOCK_BUFFSIZE;
721 1500 hiro
                setsockopt(sock, SOL_SOCKET, SO_SNDBUF, (char *)&val, len);
722 1500 hiro
        }
723 1500 hiro
        getsockopt(sock, SOL_SOCKET, SO_RCVBUF, (char *)&val, &len);
724 1500 hiro
        if (val < SOCK_BUFFSIZE) {
725 1500 hiro
                val = SOCK_BUFFSIZE;
726 1500 hiro
                setsockopt(sock, SOL_SOCKET, SO_RCVBUF, (char *)&val, len);
727 1500 hiro
        }
728 1500 hiro
        getsockopt(sock, SOL_SOCKET, SO_SNDBUF, (char *)&val, &len);
729 1499 hiro
        debug_print("SO_SNDBUF = %d\n", val);
730 1499 hiro
        getsockopt(sock, SOL_SOCKET, SO_RCVBUF, (char *)&val, &len);
731 1499 hiro
        debug_print("SO_RCVBUF = %d\n", val);
732 1500 hiro
733 1500 hiro
#undef SOCK_BUFFSIZE
734 1499 hiro
#endif
735 1499 hiro
}
736 1499 hiro
737 528 hiro
#ifndef INET6
738 528 hiro
static gint my_inet_aton(const gchar *hostname, struct in_addr *inp)
739 528 hiro
{
740 528 hiro
#if HAVE_INET_ATON
741 528 hiro
        return inet_aton(hostname, inp);
742 528 hiro
#else
743 528 hiro
#if HAVE_INET_ADDR
744 528 hiro
        guint32 inaddr;
745 528 hiro
746 528 hiro
        inaddr = inet_addr(hostname);
747 528 hiro
        if (inaddr != -1) {
748 528 hiro
                memcpy(inp, &inaddr, sizeof(inaddr));
749 528 hiro
                return 1;
750 528 hiro
        } else
751 528 hiro
                return 0;
752 528 hiro
#else
753 528 hiro
        return 0;
754 528 hiro
#endif
755 528 hiro
#endif /* HAVE_INET_ATON */
756 528 hiro
}
757 528 hiro
758 528 hiro
static gint sock_connect_by_hostname(gint sock, const gchar *hostname,
759 528 hiro
                                     gushort port)
760 528 hiro
{
761 528 hiro
        struct hostent *hp;
762 528 hiro
        struct sockaddr_in ad;
763 528 hiro
764 1418 hiro
        resolver_init();
765 1418 hiro
766 528 hiro
        memset(&ad, 0, sizeof(ad));
767 528 hiro
        ad.sin_family = AF_INET;
768 528 hiro
        ad.sin_port = htons(port);
769 528 hiro
770 528 hiro
        if (!my_inet_aton(hostname, &ad.sin_addr)) {
771 528 hiro
                if ((hp = my_gethostbyname(hostname)) == NULL) {
772 528 hiro
                        fprintf(stderr, "%s: unknown host.\n", hostname);
773 528 hiro
                        errno = 0;
774 528 hiro
                        return -1;
775 528 hiro
                }
776 528 hiro
777 528 hiro
                if (hp->h_length != 4 && hp->h_length != 8) {
778 528 hiro
                        fprintf(stderr, "illegal address length received for host %s\n", hostname);
779 528 hiro
                        errno = 0;
780 528 hiro
                        return -1;
781 528 hiro
                }
782 528 hiro
783 528 hiro
                memcpy(&ad.sin_addr, hp->h_addr, hp->h_length);
784 528 hiro
        }
785 528 hiro
786 528 hiro
        return sock_connect_with_timeout(sock, (struct sockaddr *)&ad,
787 528 hiro
                                         sizeof(ad), io_timeout);
788 528 hiro
}
789 528 hiro
790 528 hiro
#else /* INET6 */
791 932 hiro
792 932 hiro
#ifdef G_OS_WIN32
793 932 hiro
/* MinGW defines gai_strerror() in ws2tcpip.h, but it is not implemented. */
794 932 hiro
#undef gai_strerror
795 932 hiro
const gchar *gai_strerror(gint errcode)
796 932 hiro
{
797 932 hiro
        static gchar str[32];
798 932 hiro
799 932 hiro
        g_snprintf(str, sizeof(str), "gai errcode: (%d)", errcode);
800 932 hiro
        return str;
801 932 hiro
}
802 932 hiro
#endif
803 932 hiro
804 941 hiro
static SockDesc sock_connect_by_getaddrinfo(const gchar *hostname, gushort port)
805 528 hiro
{
806 941 hiro
        SockDesc sock = INVALID_SOCKET;
807 932 hiro
        gint gai_error;
808 528 hiro
        struct addrinfo hints, *res, *ai;
809 528 hiro
        gchar port_str[6];
810 528 hiro
811 1418 hiro
        resolver_init();
812 1418 hiro
813 528 hiro
        memset(&hints, 0, sizeof(hints));
814 528 hiro
        /* hints.ai_flags = AI_CANONNAME; */
815 528 hiro
        hints.ai_family = AF_UNSPEC;
816 528 hiro
        hints.ai_socktype = SOCK_STREAM;
817 528 hiro
        hints.ai_protocol = IPPROTO_TCP;
818 528 hiro
819 528 hiro
        /* convert port from integer to string. */
820 528 hiro
        g_snprintf(port_str, sizeof(port_str), "%d", port);
821 528 hiro
822 528 hiro
        if ((gai_error = getaddrinfo(hostname, port_str, &hints, &res)) != 0) {
823 528 hiro
                fprintf(stderr, "getaddrinfo for %s:%s failed: %s\n",
824 528 hiro
                        hostname, port_str, gai_strerror(gai_error));
825 941 hiro
                return INVALID_SOCKET;
826 528 hiro
        }
827 528 hiro
828 528 hiro
        for (ai = res; ai != NULL; ai = ai->ai_next) {
829 528 hiro
                sock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
830 941 hiro
                if (!SOCKET_IS_VALID(sock))
831 528 hiro
                        continue;
832 1499 hiro
                sock_set_buffer_size(sock);
833 528 hiro
834 528 hiro
                if (sock_connect_with_timeout
835 528 hiro
                        (sock, ai->ai_addr, ai->ai_addrlen, io_timeout) == 0)
836 528 hiro
                        break;
837 528 hiro
838 528 hiro
                fd_close(sock);
839 528 hiro
        }
840 528 hiro
841 528 hiro
        if (res != NULL)
842 528 hiro
                freeaddrinfo(res);
843 528 hiro
844 528 hiro
        if (ai == NULL)
845 941 hiro
                return INVALID_SOCKET;
846 528 hiro
847 528 hiro
        return sock;
848 528 hiro
}
849 528 hiro
#endif /* !INET6 */
850 528 hiro
851 528 hiro
SockInfo *sock_connect(const gchar *hostname, gushort port)
852 528 hiro
{
853 941 hiro
        SockDesc sock;
854 528 hiro
        SockInfo *sockinfo;
855 528 hiro
856 528 hiro
#ifdef INET6
857 941 hiro
        sock = sock_connect_by_getaddrinfo(hostname, port);
858 941 hiro
        if (!SOCKET_IS_VALID(sock))
859 528 hiro
                return NULL;
860 528 hiro
#else
861 941 hiro
        sock = socket(AF_INET, SOCK_STREAM, 0);
862 941 hiro
        if (!SOCKET_IS_VALID(sock)) {
863 528 hiro
#ifdef G_OS_WIN32
864 528 hiro
                g_warning("socket() failed: %ld\n", WSAGetLastError());
865 528 hiro
#else
866 528 hiro
                perror("socket");
867 528 hiro
#endif /* G_OS_WIN32 */
868 528 hiro
                return NULL;
869 528 hiro
        }
870 1499 hiro
        sock_set_buffer_size(sock);
871 528 hiro
872 528 hiro
        if (sock_connect_by_hostname(sock, hostname, port) < 0) {
873 528 hiro
                if (errno != 0) perror("connect");
874 528 hiro
                fd_close(sock);
875 528 hiro
                return NULL;
876 528 hiro
        }
877 528 hiro
#endif /* INET6 */
878 528 hiro
879 528 hiro
        sockinfo = g_new0(SockInfo, 1);
880 528 hiro
        sockinfo->sock = sock;
881 528 hiro
        sockinfo->sock_ch = g_io_channel_unix_new(sock);
882 528 hiro
        sockinfo->hostname = g_strdup(hostname);
883 528 hiro
        sockinfo->port = port;
884 528 hiro
        sockinfo->state = CONN_ESTABLISHED;
885 1500 hiro
        sockinfo->flags = SOCK_CHECK_IO;
886 528 hiro
887 1230 hiro
        sock_list = g_list_prepend(sock_list, sockinfo);
888 1230 hiro
889 528 hiro
        g_usleep(100000);
890 528 hiro
891 528 hiro
        return sockinfo;
892 528 hiro
}
893 528 hiro
894 528 hiro
#ifdef G_OS_UNIX
895 528 hiro
static void sock_address_list_free(GList *addr_list)
896 528 hiro
{
897 528 hiro
        GList *cur;
898 528 hiro
899 528 hiro
        for (cur = addr_list; cur != NULL; cur = cur->next) {
900 528 hiro
                SockAddrData *addr_data = (SockAddrData *)cur->data;
901 528 hiro
                g_free(addr_data->addr);
902 528 hiro
                g_free(addr_data);
903 528 hiro
        }
904 528 hiro
905 528 hiro
        g_list_free(addr_list);
906 528 hiro
}
907 528 hiro
908 528 hiro
/* asynchronous TCP connection */
909 528 hiro
910 528 hiro
static gboolean sock_connect_async_cb(GIOChannel *source,
911 528 hiro
                                      GIOCondition condition, gpointer data)
912 528 hiro
{
913 528 hiro
        SockConnectData *conn_data = (SockConnectData *)data;
914 528 hiro
        gint fd;
915 528 hiro
        gint val;
916 528 hiro
        guint len;
917 528 hiro
        SockInfo *sockinfo;
918 528 hiro
919 528 hiro
        fd = g_io_channel_unix_get_fd(source);
920 528 hiro
921 528 hiro
        conn_data->io_tag = 0;
922 528 hiro
        conn_data->channel = NULL;
923 528 hiro
        g_io_channel_unref(source);
924 528 hiro
925 1953 hiro
        if (condition & (G_IO_ERR | G_IO_HUP)) {
926 1953 hiro
                debug_print("sock_connect_async_cb: condition = %d\n",
927 1953 hiro
                            condition);
928 1953 hiro
                fd_close(fd);
929 1953 hiro
                sock_connect_address_list_async(conn_data);
930 1953 hiro
                return FALSE;
931 1953 hiro
        }
932 1953 hiro
933 528 hiro
        len = sizeof(val);
934 528 hiro
        if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &val, &len) < 0) {
935 528 hiro
                perror("getsockopt");
936 528 hiro
                fd_close(fd);
937 528 hiro
                sock_connect_address_list_async(conn_data);
938 528 hiro
                return FALSE;
939 528 hiro
        }
940 528 hiro
941 528 hiro
        if (val != 0) {
942 528 hiro
                fd_close(fd);
943 528 hiro
                sock_connect_address_list_async(conn_data);
944 528 hiro
                return FALSE;
945 528 hiro
        }
946 528 hiro
947 528 hiro
        sockinfo = g_new0(SockInfo, 1);
948 528 hiro
        sockinfo->sock = fd;
949 528 hiro
        sockinfo->sock_ch = g_io_channel_unix_new(fd);
950 528 hiro
        sockinfo->hostname = g_strdup(conn_data->hostname);
951 528 hiro
        sockinfo->port = conn_data->port;
952 528 hiro
        sockinfo->state = CONN_ESTABLISHED;
953 1500 hiro
        sockinfo->flags = SOCK_NONBLOCK;
954 528 hiro
955 1230 hiro
        sock_list = g_list_prepend(sock_list, sockinfo);
956 1230 hiro
957 528 hiro
        conn_data->func(sockinfo, conn_data->data);
958 528 hiro
959 528 hiro
        sock_connect_async_cancel(conn_data->id);
960 528 hiro
961 528 hiro
        return FALSE;
962 528 hiro
}
963 528 hiro
964 528 hiro
static gint sock_connect_async_get_address_info_cb(GList *addr_list,
965 528 hiro
                                                   gpointer data)
966 528 hiro
{
967 528 hiro
        SockConnectData *conn_data = (SockConnectData *)data;
968 528 hiro
969 528 hiro
        conn_data->addr_list = addr_list;
970 528 hiro
        conn_data->cur_addr = addr_list;
971 528 hiro
        conn_data->lookup_data = NULL;
972 528 hiro
973 528 hiro
        return sock_connect_address_list_async(conn_data);
974 528 hiro
}
975 528 hiro
976 528 hiro
gint sock_connect_async(const gchar *hostname, gushort port,
977 528 hiro
                        SockConnectFunc func, gpointer data)
978 528 hiro
{
979 528 hiro
        static gint id = 1;
980 528 hiro
        SockConnectData *conn_data;
981 528 hiro
982 528 hiro
        conn_data = g_new0(SockConnectData, 1);
983 528 hiro
        conn_data->id = id++;
984 528 hiro
        conn_data->hostname = g_strdup(hostname);
985 528 hiro
        conn_data->port = port;
986 528 hiro
        conn_data->addr_list = NULL;
987 528 hiro
        conn_data->cur_addr = NULL;
988 528 hiro
        conn_data->io_tag = 0;
989 528 hiro
        conn_data->func = func;
990 528 hiro
        conn_data->data = data;
991 528 hiro
992 528 hiro
        conn_data->lookup_data = sock_get_address_info_async
993 528 hiro
                (hostname, port, sock_connect_async_get_address_info_cb,
994 528 hiro
                 conn_data);
995 528 hiro
996 528 hiro
        if (conn_data->lookup_data == NULL) {
997 528 hiro
                g_free(conn_data->hostname);
998 528 hiro
                g_free(conn_data);
999 528 hiro
                return -1;
1000 528 hiro
        }
1001 528 hiro
1002 528 hiro
        sock_connect_data_list = g_list_append(sock_connect_data_list,
1003 528 hiro
                                               conn_data);
1004 528 hiro
1005 528 hiro
        return conn_data->id;
1006 528 hiro
}
1007 528 hiro
1008 528 hiro
gint sock_connect_async_cancel(gint id)
1009 528 hiro
{
1010 528 hiro
        SockConnectData *conn_data = NULL;
1011 528 hiro
        GList *cur;
1012 528 hiro
1013 528 hiro
        for (cur = sock_connect_data_list; cur != NULL; cur = cur->next) {
1014 528 hiro
                if (((SockConnectData *)cur->data)->id == id) {
1015 528 hiro
                        conn_data = (SockConnectData *)cur->data;
1016 528 hiro
                        break;
1017 528 hiro
                }
1018 528 hiro
        }
1019 528 hiro
1020 528 hiro
        if (conn_data) {
1021 528 hiro
                sock_connect_data_list = g_list_remove(sock_connect_data_list,
1022 528 hiro
                                                       conn_data);
1023 528 hiro
1024 528 hiro
                if (conn_data->lookup_data)
1025 528 hiro
                        sock_get_address_info_async_cancel
1026 528 hiro
                                (conn_data->lookup_data);
1027 528 hiro
1028 528 hiro
                if (conn_data->io_tag > 0)
1029 528 hiro
                        g_source_remove(conn_data->io_tag);
1030 528 hiro
                if (conn_data->channel) {
1031 528 hiro
                        g_io_channel_shutdown(conn_data->channel, FALSE, NULL);
1032 528 hiro
                        g_io_channel_unref(conn_data->channel);
1033 528 hiro
                }
1034 528 hiro
1035 528 hiro
                sock_address_list_free(conn_data->addr_list);
1036 528 hiro
                g_free(conn_data->hostname);
1037 528 hiro
                g_free(conn_data);
1038 528 hiro
        } else {
1039 528 hiro
                g_warning("sock_connect_async_cancel: id %d not found.\n", id);
1040 528 hiro
                return -1;
1041 528 hiro
        }
1042 528 hiro
1043 528 hiro
        return 0;
1044 528 hiro
}
1045 528 hiro
1046 528 hiro
static gint sock_connect_address_list_async(SockConnectData *conn_data)
1047 528 hiro
{
1048 528 hiro
        SockAddrData *addr_data;
1049 528 hiro
        gint sock = -1;
1050 528 hiro
1051 528 hiro
        for (; conn_data->cur_addr != NULL;
1052 528 hiro
             conn_data->cur_addr = conn_data->cur_addr->next) {
1053 528 hiro
                addr_data = (SockAddrData *)conn_data->cur_addr->data;
1054 528 hiro
1055 528 hiro
                if ((sock = socket(addr_data->family, addr_data->socktype,
1056 528 hiro
                                   addr_data->protocol)) < 0) {
1057 528 hiro
                        perror("socket");
1058 528 hiro
                        continue;
1059 528 hiro
                }
1060 528 hiro
1061 1499 hiro
                sock_set_buffer_size(sock);
1062 528 hiro
                set_nonblocking_mode(sock, TRUE);
1063 528 hiro
1064 528 hiro
                if (connect(sock, addr_data->addr, addr_data->addr_len) < 0) {
1065 528 hiro
                        if (EINPROGRESS == errno) {
1066 528 hiro
                                break;
1067 528 hiro
                        } else {
1068 528 hiro
                                perror("connect");
1069 528 hiro
                                fd_close(sock);
1070 528 hiro
                        }
1071 528 hiro
                } else
1072 528 hiro
                        break;
1073 528 hiro
        }
1074 528 hiro
1075 528 hiro
        if (conn_data->cur_addr == NULL) {
1076 528 hiro
                g_warning("sock_connect_address_list_async: "
1077 528 hiro
                          "connection to %s:%d failed\n",
1078 528 hiro
                          conn_data->hostname, conn_data->port);
1079 528 hiro
                conn_data->func(NULL, conn_data->data);
1080 528 hiro
                sock_connect_async_cancel(conn_data->id);
1081 528 hiro
                return -1;
1082 528 hiro
        }
1083 528 hiro
1084 1953 hiro
        debug_print("sock_connect_address_list_async: waiting for connect\n");
1085 1953 hiro
1086 528 hiro
        conn_data->cur_addr = conn_data->cur_addr->next;
1087 528 hiro
1088 528 hiro
        conn_data->channel = g_io_channel_unix_new(sock);
1089 1953 hiro
        conn_data->io_tag = g_io_add_watch(conn_data->channel,
1090 1953 hiro
                                           G_IO_OUT | G_IO_ERR | G_IO_HUP,
1091 528 hiro
                                           sock_connect_async_cb, conn_data);
1092 528 hiro
1093 528 hiro
        return 0;
1094 528 hiro
}
1095 528 hiro
1096 1143 hiro
static gint sock_kill_process(pid_t pid)
1097 1143 hiro
{
1098 1143 hiro
        pid_t ret = (pid_t)-1;
1099 1143 hiro
1100 1143 hiro
        kill(pid, SIGKILL);
1101 1143 hiro
1102 1143 hiro
        while (ret == (pid_t)-1) {
1103 1143 hiro
                if ((ret = waitpid(pid, NULL, 0)) != pid) {
1104 1143 hiro
                        perror("sock_kill_process(): waitpid");
1105 1143 hiro
                        if (ret == (pid_t)-1 && errno != EINTR)
1106 1143 hiro
                                break;
1107 1143 hiro
                }
1108 1143 hiro
        }
1109 1143 hiro
1110 1143 hiro
        return (gint)pid;
1111 1143 hiro
}
1112 1143 hiro
1113 528 hiro
/* asynchronous DNS lookup */
1114 528 hiro
1115 528 hiro
static gboolean sock_get_address_info_async_cb(GIOChannel *source,
1116 528 hiro
                                               GIOCondition condition,
1117 528 hiro
                                               gpointer data)
1118 528 hiro
{
1119 528 hiro
        SockLookupData *lookup_data = (SockLookupData *)data;
1120 528 hiro
        GList *addr_list = NULL;
1121 528 hiro
        SockAddrData *addr_data;
1122 528 hiro
        gsize bytes_read;
1123 528 hiro
        gint ai_member[4];
1124 528 hiro
        struct sockaddr *addr;
1125 528 hiro
1126 528 hiro
        for (;;) {
1127 528 hiro
                if (g_io_channel_read(source, (gchar *)ai_member,
1128 528 hiro
                                      sizeof(ai_member), &bytes_read)
1129 528 hiro
                    != G_IO_ERROR_NONE) {
1130 528 hiro
                        g_warning("sock_get_address_info_async_cb: "
1131 528 hiro
                                  "address length read error\n");
1132 528 hiro
                        break;
1133 528 hiro
                }
1134 528 hiro
1135 528 hiro
                if (bytes_read == 0 || bytes_read != sizeof(ai_member))
1136 528 hiro
                        break;
1137 528 hiro
1138 528 hiro
                if (ai_member[0] == AF_UNSPEC) {
1139 528 hiro
                        g_warning("DNS lookup failed\n");
1140 528 hiro
                        break;
1141 528 hiro
                }
1142 528 hiro
1143 528 hiro
                addr = g_malloc(ai_member[3]);
1144 528 hiro
                if (g_io_channel_read(source, (gchar *)addr, ai_member[3],
1145 528 hiro
                                      &bytes_read)
1146 528 hiro
                    != G_IO_ERROR_NONE) {
1147 528 hiro
                        g_warning("sock_get_address_info_async_cb: "
1148 528 hiro
                                  "address data read error\n");
1149 528 hiro
                        g_free(addr);
1150 528 hiro
                        break;
1151 528 hiro
                }
1152 528 hiro
1153 528 hiro
                if (bytes_read != ai_member[3]) {
1154 528 hiro
                        g_warning("sock_get_address_info_async_cb: "
1155 528 hiro
                                  "incomplete address data\n");
1156 528 hiro
                        g_free(addr);
1157 528 hiro
                        break;
1158 528 hiro
                }
1159 528 hiro
1160 528 hiro
                addr_data = g_new0(SockAddrData, 1);
1161 528 hiro
                addr_data->family = ai_member[0];
1162 528 hiro
                addr_data->socktype = ai_member[1];
1163 528 hiro
                addr_data->protocol = ai_member[2];
1164 528 hiro
                addr_data->addr_len = ai_member[3];
1165 528 hiro
                addr_data->addr = addr;
1166 528 hiro
1167 528 hiro
                addr_list = g_list_append(addr_list, addr_data);
1168 528 hiro
        }
1169 528 hiro
1170 528 hiro
        g_io_channel_shutdown(source, FALSE, NULL);
1171 528 hiro
        g_io_channel_unref(source);
1172 528 hiro
1173 1143 hiro
        sock_kill_process(lookup_data->child_pid);
1174 528 hiro
1175 528 hiro
        lookup_data->func(addr_list, lookup_data->data);
1176 528 hiro
1177 528 hiro
        g_free(lookup_data->hostname);
1178 528 hiro
        g_free(lookup_data);
1179 528 hiro
1180 528 hiro
        return FALSE;
1181 528 hiro
}
1182 528 hiro
1183 528 hiro
static SockLookupData *sock_get_address_info_async(const gchar *hostname,
1184 528 hiro
                                                   gushort port,
1185 528 hiro
                                                   SockAddrFunc func,
1186 528 hiro
                                                   gpointer data)
1187 528 hiro
{
1188 528 hiro
        SockLookupData *lookup_data = NULL;
1189 528 hiro
        gint pipe_fds[2];
1190 528 hiro
        pid_t pid;
1191 528 hiro
1192 1418 hiro
        resolver_init();
1193 1418 hiro
1194 528 hiro
        if (pipe(pipe_fds) < 0) {
1195 528 hiro
                perror("pipe");
1196 528 hiro
                func(NULL, data);
1197 528 hiro
                return NULL;
1198 528 hiro
        }
1199 528 hiro
1200 528 hiro
        if ((pid = fork()) < 0) {
1201 528 hiro
                perror("fork");
1202 528 hiro
                func(NULL, data);
1203 528 hiro
                return NULL;
1204 528 hiro
        }
1205 528 hiro
1206 528 hiro
        /* child process */
1207 528 hiro
        if (pid == 0) {
1208 528 hiro
#ifdef INET6
1209 528 hiro
                gint gai_err;
1210 528 hiro
                struct addrinfo hints, *res, *ai;
1211 528 hiro
                gchar port_str[6];
1212 528 hiro
#else /* !INET6 */
1213 528 hiro
                struct hostent *hp;
1214 528 hiro
                gchar **addr_list_p;
1215 528 hiro
                struct sockaddr_in ad;
1216 528 hiro
#endif /* INET6 */
1217 528 hiro
                gint ai_member[4] = {AF_UNSPEC, 0, 0, 0};
1218 528 hiro
1219 528 hiro
                close(pipe_fds[0]);
1220 528 hiro
1221 528 hiro
#ifdef INET6
1222 528 hiro
                memset(&hints, 0, sizeof(hints));
1223 528 hiro
                /* hints.ai_flags = AI_CANONNAME; */
1224 528 hiro
                hints.ai_family = AF_UNSPEC;
1225 528 hiro
                hints.ai_socktype = SOCK_STREAM;
1226 528 hiro
                hints.ai_protocol = IPPROTO_TCP;
1227 528 hiro
1228 528 hiro
                g_snprintf(port_str, sizeof(port_str), "%d", port);
1229 528 hiro
1230 528 hiro
                gai_err = getaddrinfo(hostname, port_str, &hints, &res);
1231 528 hiro
                if (gai_err != 0) {
1232 528 hiro
                        g_warning("getaddrinfo for %s:%s failed: %s\n",
1233 528 hiro
                                  hostname, port_str, gai_strerror(gai_err));
1234 528 hiro
                        fd_write_all(pipe_fds[1], (gchar *)ai_member,
1235 528 hiro
                                     sizeof(ai_member));
1236 528 hiro
                        close(pipe_fds[1]);
1237 528 hiro
                        _exit(1);
1238 528 hiro
                }
1239 528 hiro
1240 528 hiro
                for (ai = res; ai != NULL; ai = ai->ai_next) {
1241 528 hiro
                        ai_member[0] = ai->ai_family;
1242 528 hiro
                        ai_member[1] = ai->ai_socktype;
1243 528 hiro
                        ai_member[2] = ai->ai_protocol;
1244 528 hiro
                        ai_member[3] = ai->ai_addrlen;
1245 528 hiro
1246 528 hiro
                        fd_write_all(pipe_fds[1], (gchar *)ai_member,
1247 528 hiro
                                     sizeof(ai_member));
1248 528 hiro
                        fd_write_all(pipe_fds[1], (gchar *)ai->ai_addr,
1249 528 hiro
                                     ai->ai_addrlen);
1250 528 hiro
                }
1251 528 hiro
1252 528 hiro
                if (res != NULL)
1253 528 hiro
                        freeaddrinfo(res);
1254 528 hiro
#else /* !INET6 */
1255 528 hiro
                hp = my_gethostbyname(hostname);
1256 528 hiro
                if (hp == NULL || hp->h_addrtype != AF_INET) {
1257 528 hiro
                        fd_write_all(pipe_fds[1], (gchar *)ai_member,
1258 528 hiro
                                     sizeof(ai_member));
1259 528 hiro
                        close(pipe_fds[1]);
1260 528 hiro
                        _exit(1);
1261 528 hiro
                }
1262 528 hiro
1263 528 hiro
                ai_member[0] = AF_INET;
1264 528 hiro
                ai_member[1] = SOCK_STREAM;
1265 528 hiro
                ai_member[2] = IPPROTO_TCP;
1266 528 hiro
                ai_member[3] = sizeof(ad);
1267 528 hiro
1268 528 hiro
                memset(&ad, 0, sizeof(ad));
1269 528 hiro
                ad.sin_family = AF_INET;
1270 528 hiro
                ad.sin_port = htons(port);
1271 528 hiro
1272 528 hiro
                for (addr_list_p = hp->h_addr_list; *addr_list_p != NULL;
1273 528 hiro
                     addr_list_p++) {
1274 528 hiro
                        memcpy(&ad.sin_addr, *addr_list_p, hp->h_length);
1275 528 hiro
                        fd_write_all(pipe_fds[1], (gchar *)ai_member,
1276 528 hiro
                                     sizeof(ai_member));
1277 528 hiro
                        fd_write_all(pipe_fds[1], (gchar *)&ad, sizeof(ad));
1278 528 hiro
                }
1279 528 hiro
#endif /* INET6 */
1280 528 hiro
1281 528 hiro
                close(pipe_fds[1]);
1282 528 hiro
1283 528 hiro
                _exit(0);
1284 528 hiro
        } else {
1285 528 hiro
                close(pipe_fds[1]);
1286 528 hiro
1287 528 hiro
                lookup_data = g_new0(SockLookupData, 1);
1288 528 hiro
                lookup_data->hostname = g_strdup(hostname);
1289 528 hiro
                lookup_data->child_pid = pid;
1290 528 hiro
                lookup_data->func = func;
1291 528 hiro
                lookup_data->data = data;
1292 528 hiro
1293 528 hiro
                lookup_data->channel = g_io_channel_unix_new(pipe_fds[0]);
1294 528 hiro
                lookup_data->io_tag = g_io_add_watch
1295 528 hiro
                        (lookup_data->channel, G_IO_IN,
1296 528 hiro
                         sock_get_address_info_async_cb, lookup_data);
1297 528 hiro
        }
1298 528 hiro
1299 528 hiro
        return lookup_data;
1300 528 hiro
}
1301 528 hiro
1302 528 hiro
static gint sock_get_address_info_async_cancel(SockLookupData *lookup_data)
1303 528 hiro
{
1304 528 hiro
        if (lookup_data->io_tag > 0)
1305 528 hiro
                g_source_remove(lookup_data->io_tag);
1306 528 hiro
        if (lookup_data->channel) {
1307 528 hiro
                g_io_channel_shutdown(lookup_data->channel, FALSE, NULL);
1308 528 hiro
                g_io_channel_unref(lookup_data->channel);
1309 528 hiro
        }
1310 528 hiro
1311 1143 hiro
        if (lookup_data->child_pid > 0)
1312 1143 hiro
                sock_kill_process(lookup_data->child_pid);
1313 528 hiro
1314 528 hiro
        g_free(lookup_data->hostname);
1315 528 hiro
        g_free(lookup_data);
1316 528 hiro
1317 528 hiro
        return 0;
1318 528 hiro
}
1319 528 hiro
#endif /* G_OS_UNIX */
1320 528 hiro
1321 528 hiro
1322 528 hiro
gint sock_printf(SockInfo *sock, const gchar *format, ...)
1323 528 hiro
{
1324 528 hiro
        va_list args;
1325 528 hiro
        gchar buf[BUFFSIZE];
1326 528 hiro
1327 528 hiro
        va_start(args, format);
1328 528 hiro
        g_vsnprintf(buf, sizeof(buf), format, args);
1329 528 hiro
        va_end(args);
1330 528 hiro
1331 528 hiro
        return sock_write_all(sock, buf, strlen(buf));
1332 528 hiro
}
1333 528 hiro
1334 1207 hiro
#ifdef G_OS_WIN32
1335 1230 hiro
static void sock_set_errno_from_last_error(gint error)
1336 1207 hiro
{
1337 1230 hiro
        switch (error) {
1338 1207 hiro
        case WSAEWOULDBLOCK:
1339 1207 hiro
                errno = EAGAIN;
1340 1207 hiro
                break;
1341 1207 hiro
        default:
1342 1230 hiro
                debug_print("last error = %d\n", error);
1343 1230 hiro
                errno = 0;
1344 1207 hiro
                break;
1345 1207 hiro
        }
1346 1207 hiro
}
1347 1207 hiro
#endif
1348 1207 hiro
1349 528 hiro
gint sock_read(SockInfo *sock, gchar *buf, gint len)
1350 528 hiro
{
1351 528 hiro
        g_return_val_if_fail(sock != NULL, -1);
1352 528 hiro
1353 528 hiro
#if USE_SSL
1354 528 hiro
        if (sock->ssl)
1355 528 hiro
                return ssl_read(sock->ssl, buf, len);
1356 528 hiro
#endif
1357 528 hiro
        return fd_read(sock->sock, buf, len);
1358 528 hiro
}
1359 528 hiro
1360 528 hiro
gint fd_read(gint fd, gchar *buf, gint len)
1361 528 hiro
{
1362 1207 hiro
#ifdef G_OS_WIN32
1363 1207 hiro
        return fd_recv(fd, buf, len, 0);
1364 1207 hiro
#else
1365 528 hiro
        if (fd_check_io(fd, G_IO_IN) < 0)
1366 528 hiro
                return -1;
1367 528 hiro
1368 528 hiro
        return read(fd, buf, len);
1369 528 hiro
#endif
1370 528 hiro
}
1371 528 hiro
1372 528 hiro
#if USE_SSL
1373 528 hiro
gint ssl_read(SSL *ssl, gchar *buf, gint len)
1374 528 hiro
{
1375 528 hiro
        gint err, ret;
1376 528 hiro
1377 1873 hiro
        errno = 0;
1378 1873 hiro
1379 528 hiro
        if (SSL_pending(ssl) == 0) {
1380 528 hiro
                if (fd_check_io(SSL_get_rfd(ssl), G_IO_IN) < 0)
1381 528 hiro
                        return -1;
1382 528 hiro
        }
1383 528 hiro
1384 528 hiro
        ret = SSL_read(ssl, buf, len);
1385 528 hiro
1386 528 hiro
        switch ((err = SSL_get_error(ssl, ret))) {
1387 528 hiro
        case SSL_ERROR_NONE:
1388 528 hiro
                return ret;
1389 528 hiro
        case SSL_ERROR_WANT_READ:
1390 528 hiro
        case SSL_ERROR_WANT_WRITE:
1391 528 hiro
                errno = EAGAIN;
1392 528 hiro
                return -1;
1393 528 hiro
        case SSL_ERROR_ZERO_RETURN:
1394 528 hiro
                return 0;
1395 528 hiro
        default:
1396 528 hiro
                g_warning("SSL_read() returned error %d, ret = %d\n", err, ret);
1397 528 hiro
                if (ret == 0)
1398 528 hiro
                        return 0;
1399 1873 hiro
#ifdef G_OS_WIN32
1400 1873 hiro
                errno = EIO;
1401 1873 hiro
#endif
1402 528 hiro
                return -1;
1403 528 hiro
        }
1404 528 hiro
}
1405 528 hiro
#endif
1406 528 hiro
1407 528 hiro
gint sock_write(SockInfo *sock, const gchar *buf, gint len)
1408 528 hiro
{
1409 528 hiro
        g_return_val_if_fail(sock != NULL, -1);
1410 528 hiro
1411 528 hiro
#if USE_SSL
1412 528 hiro
        if (sock->ssl)
1413 528 hiro
                return ssl_write(sock->ssl, buf, len);
1414 528 hiro
#endif
1415 528 hiro
        return fd_write(sock->sock, buf, len);
1416 528 hiro
}
1417 528 hiro
1418 528 hiro
gint fd_write(gint fd, const gchar *buf, gint len)
1419 528 hiro
{
1420 1207 hiro
#ifdef G_OS_WIN32
1421 1207 hiro
        gint ret;
1422 1207 hiro
#endif
1423 528 hiro
        if (fd_check_io(fd, G_IO_OUT) < 0)
1424 528 hiro
                return -1;
1425 528 hiro
1426 528 hiro
#ifdef G_OS_WIN32
1427 1207 hiro
        ret = send(fd, buf, len, 0);
1428 1207 hiro
        if (ret == SOCKET_ERROR) {
1429 1230 hiro
                gint err;
1430 1230 hiro
                err = WSAGetLastError();
1431 1230 hiro
                sock_set_errno_from_last_error(err);
1432 1230 hiro
                if (err != WSAEWOULDBLOCK)
1433 1230 hiro
                        g_warning("fd_write() failed with %d (errno = %d)\n",
1434 1230 hiro
                                  err, errno);
1435 1207 hiro
        }
1436 1207 hiro
        return ret;
1437 528 hiro
#else
1438 528 hiro
        return write(fd, buf, len);
1439 528 hiro
#endif
1440 528 hiro
}
1441 528 hiro
1442 528 hiro
#if USE_SSL
1443 528 hiro
gint ssl_write(SSL *ssl, const gchar *buf, gint len)
1444 528 hiro
{
1445 528 hiro
        gint ret;
1446 528 hiro
1447 528 hiro
        ret = SSL_write(ssl, buf, len);
1448 528 hiro
1449 528 hiro
        switch (SSL_get_error(ssl, ret)) {
1450 528 hiro
        case SSL_ERROR_NONE:
1451 528 hiro
                return ret;
1452 528 hiro
        case SSL_ERROR_WANT_READ:
1453 528 hiro
        case SSL_ERROR_WANT_WRITE:
1454 528 hiro
                errno = EAGAIN;
1455 528 hiro
                return -1;
1456 528 hiro
        default:
1457 528 hiro
                return -1;
1458 528 hiro
        }
1459 528 hiro
}
1460 528 hiro
#endif
1461 528 hiro
1462 528 hiro
gint sock_write_all(SockInfo *sock, const gchar *buf, gint len)
1463 528 hiro
{
1464 528 hiro
        g_return_val_if_fail(sock != NULL, -1);
1465 528 hiro
1466 528 hiro
#if USE_SSL
1467 528 hiro
        if (sock->ssl)
1468 528 hiro
                return ssl_write_all(sock->ssl, buf, len);
1469 528 hiro
#endif
1470 528 hiro
        return fd_write_all(sock->sock, buf, len);
1471 528 hiro
}
1472 528 hiro
1473 528 hiro
gint fd_write_all(gint fd, const gchar *buf, gint len)
1474 528 hiro
{
1475 528 hiro
        gint n, wrlen = 0;
1476 528 hiro
1477 528 hiro
        while (len) {
1478 528 hiro
                n = fd_write(fd, buf, len);
1479 528 hiro
                if (n <= 0)
1480 528 hiro
                        return -1;
1481 528 hiro
                len -= n;
1482 528 hiro
                wrlen += n;
1483 528 hiro
                buf += n;
1484 528 hiro
        }
1485 528 hiro
1486 528 hiro
        return wrlen;
1487 528 hiro
}
1488 528 hiro
1489 528 hiro
#if USE_SSL
1490 528 hiro
gint ssl_write_all(SSL *ssl, const gchar *buf, gint len)
1491 528 hiro
{
1492 528 hiro
        gint n, wrlen = 0;
1493 528 hiro
1494 528 hiro
        while (len) {
1495 528 hiro
                n = ssl_write(ssl, buf, len);
1496 528 hiro
                if (n <= 0)
1497 528 hiro
                        return -1;
1498 528 hiro
                len -= n;
1499 528 hiro
                wrlen += n;
1500 528 hiro
                buf += n;
1501 528 hiro
        }
1502 528 hiro
1503 528 hiro
        return wrlen;
1504 528 hiro
}
1505 528 hiro
#endif
1506 528 hiro
1507 528 hiro
gint fd_recv(gint fd, gchar *buf, gint len, gint flags)
1508 528 hiro
{
1509 1207 hiro
#ifdef G_OS_WIN32
1510 1207 hiro
        gint ret;
1511 1207 hiro
#endif
1512 528 hiro
        if (fd_check_io(fd, G_IO_IN) < 0)
1513 528 hiro
                return -1;
1514 528 hiro
1515 1207 hiro
#ifdef G_OS_WIN32
1516 1207 hiro
        ret = recv(fd, buf, len, flags);
1517 1207 hiro
        if (ret == SOCKET_ERROR) {
1518 1230 hiro
                gint err;
1519 1230 hiro
                err = WSAGetLastError();
1520 1230 hiro
                sock_set_errno_from_last_error(err);
1521 1230 hiro
                if (err != WSAEWOULDBLOCK)
1522 1230 hiro
                        g_warning("fd_recv(): failed with %d (errno = %d)\n",
1523 1230 hiro
                                  err, errno);
1524 1207 hiro
        }
1525 1207 hiro
        return ret;
1526 1207 hiro
#else
1527 528 hiro
        return recv(fd, buf, len, flags);
1528 1207 hiro
#endif
1529 528 hiro
}
1530 528 hiro
1531 528 hiro
gint fd_gets(gint fd, gchar *buf, gint len)
1532 528 hiro
{
1533 528 hiro
        gchar *newline, *bp = buf;
1534 528 hiro
        gint n;
1535 528 hiro
1536 528 hiro
        if (--len < 1)
1537 528 hiro
                return -1;
1538 528 hiro
        do {
1539 528 hiro
                if ((n = fd_recv(fd, bp, len, MSG_PEEK)) <= 0)
1540 528 hiro
                        return -1;
1541 528 hiro
                if ((newline = memchr(bp, '\n', n)) != NULL)
1542 528 hiro
                        n = newline - bp + 1;
1543 528 hiro
                if ((n = fd_read(fd, bp, n)) < 0)
1544 528 hiro
                        return -1;
1545 528 hiro
                bp += n;
1546 528 hiro
                len -= n;
1547 528 hiro
        } while (!newline && len);
1548 528 hiro
1549 528 hiro
        *bp = '\0';
1550 528 hiro
        return bp - buf;
1551 528 hiro
}
1552 528 hiro
1553 528 hiro
#if USE_SSL
1554 528 hiro
gint ssl_gets(SSL *ssl, gchar *buf, gint len)
1555 528 hiro
{
1556 528 hiro
        gchar *newline, *bp = buf;
1557 528 hiro
        gint n;
1558 528 hiro
1559 528 hiro
        if (--len < 1)
1560 528 hiro
                return -1;
1561 528 hiro
        do {
1562 528 hiro
                if ((n = ssl_peek(ssl, bp, len)) <= 0)
1563 528 hiro
                        return -1;
1564 528 hiro
                if ((newline = memchr(bp, '\n', n)) != NULL)
1565 528 hiro
                        n = newline - bp + 1;
1566 528 hiro
                if ((n = ssl_read(ssl, bp, n)) < 0)
1567 528 hiro
                        return -1;
1568 528 hiro
                bp += n;
1569 528 hiro
                len -= n;
1570 528 hiro
        } while (!newline && len);
1571 528 hiro
1572 528 hiro
        *bp = '\0';
1573 528 hiro
        return bp - buf;
1574 528 hiro
}
1575 528 hiro
#endif
1576 528 hiro
1577 528 hiro
gint sock_gets(SockInfo *sock, gchar *buf, gint len)
1578 528 hiro
{
1579 528 hiro
        g_return_val_if_fail(sock != NULL, -1);
1580 528 hiro
1581 528 hiro
#if USE_SSL
1582 528 hiro
        if (sock->ssl)
1583 528 hiro
                return ssl_gets(sock->ssl, buf, len);
1584 528 hiro
#endif
1585 528 hiro
        return fd_gets(sock->sock, buf, len);
1586 528 hiro
}
1587 528 hiro
1588 528 hiro
gint fd_getline(gint fd, gchar **line)
1589 528 hiro
{
1590 528 hiro
        gchar buf[BUFFSIZE];
1591 528 hiro
        gchar *str = NULL;
1592 528 hiro
        gint len;
1593 528 hiro
        gulong size = 0;
1594 528 hiro
        gulong cur_offset = 0;
1595 528 hiro
1596 528 hiro
        while ((len = fd_gets(fd, buf, sizeof(buf))) > 0) {
1597 528 hiro
                size += len;
1598 528 hiro
                str = g_realloc(str, size + 1);
1599 528 hiro
                memcpy(str + cur_offset, buf, len + 1);
1600 528 hiro
                cur_offset += len;
1601 528 hiro
                if (buf[len - 1] == '\n')
1602 528 hiro
                        break;
1603 528 hiro
        }
1604 528 hiro
1605 528 hiro
        *line = str;
1606 528 hiro
1607 528 hiro
        if (!str)
1608 528 hiro
                return -1;
1609 528 hiro
        else
1610 528 hiro
                return (gint)size;
1611 528 hiro
}
1612 528 hiro
1613 528 hiro
#if USE_SSL
1614 528 hiro
gint ssl_getline(SSL *ssl, gchar **line)
1615 528 hiro
{
1616 528 hiro
        gchar buf[BUFFSIZE];
1617 528 hiro
        gchar *str = NULL;
1618 528 hiro
        gint len;
1619 528 hiro
        gulong size = 0;
1620 528 hiro
        gulong cur_offset = 0;
1621 528 hiro
1622 528 hiro
        while ((len = ssl_gets(ssl, buf, sizeof(buf))) > 0) {
1623 528 hiro
                size += len;
1624 528 hiro
                str = g_realloc(str, size + 1);
1625 528 hiro
                memcpy(str + cur_offset, buf, len + 1);
1626 528 hiro
                cur_offset += len;
1627 528 hiro
                if (buf[len - 1] == '\n')
1628 528 hiro
                        break;
1629 528 hiro
        }
1630 528 hiro
1631 528 hiro
        *line = str;
1632 528 hiro
1633 528 hiro
        if (!str)
1634 528 hiro
                return -1;
1635 528 hiro
        else
1636 528 hiro
                return (gint)size;
1637 528 hiro
}
1638 528 hiro
#endif
1639 528 hiro
1640 528 hiro
gint sock_getline(SockInfo *sock, gchar **line)
1641 528 hiro
{
1642 528 hiro
        g_return_val_if_fail(sock != NULL, -1);
1643 528 hiro
        g_return_val_if_fail(line != NULL, -1);
1644 528 hiro
1645 528 hiro
#if USE_SSL
1646 528 hiro
        if (sock->ssl)
1647 528 hiro
                return ssl_getline(sock->ssl, line);
1648 528 hiro
#endif
1649 528 hiro
        return fd_getline(sock->sock, line);
1650 528 hiro
}
1651 528 hiro
1652 528 hiro
gint sock_puts(SockInfo *sock, const gchar *buf)
1653 528 hiro
{
1654 528 hiro
        gint ret;
1655 528 hiro
1656 528 hiro
        if ((ret = sock_write_all(sock, buf, strlen(buf))) < 0)
1657 528 hiro
                return ret;
1658 528 hiro
        return sock_write_all(sock, "\r\n", 2);
1659 528 hiro
}
1660 528 hiro
1661 528 hiro
/* peek at the socket data without actually reading it */
1662 528 hiro
#if USE_SSL
1663 528 hiro
gint ssl_peek(SSL *ssl, gchar *buf, gint len)
1664 528 hiro
{
1665 528 hiro
        gint err, ret;
1666 528 hiro
1667 528 hiro
        if (SSL_pending(ssl) == 0) {
1668 528 hiro
                if (fd_check_io(SSL_get_rfd(ssl), G_IO_IN) < 0)
1669 528 hiro
                        return -1;
1670 528 hiro
        }
1671 528 hiro
1672 528 hiro
        ret = SSL_peek(ssl, buf, len);
1673 528 hiro
1674 528 hiro
        switch ((err = SSL_get_error(ssl, ret))) {
1675 528 hiro
        case SSL_ERROR_NONE:
1676 528 hiro
                return ret;
1677 528 hiro
        case SSL_ERROR_WANT_READ:
1678 528 hiro
        case SSL_ERROR_WANT_WRITE:
1679 528 hiro
                errno = EAGAIN;
1680 528 hiro
                return -1;
1681 528 hiro
        case SSL_ERROR_ZERO_RETURN:
1682 528 hiro
                return 0;
1683 528 hiro
        default:
1684 528 hiro
                g_warning("SSL_peek() returned error %d, ret = %d\n", err, ret);
1685 528 hiro
                if (ret == 0)
1686 528 hiro
                        return 0;
1687 528 hiro
                return -1;
1688 528 hiro
        }
1689 528 hiro
}
1690 528 hiro
#endif
1691 528 hiro
1692 528 hiro
gint sock_peek(SockInfo *sock, gchar *buf, gint len)
1693 528 hiro
{
1694 528 hiro
        g_return_val_if_fail(sock != NULL, -1);
1695 528 hiro
1696 528 hiro
#if USE_SSL
1697 528 hiro
        if (sock->ssl)
1698 528 hiro
                return ssl_peek(sock->ssl, buf, len);
1699 528 hiro
#endif
1700 528 hiro
        return fd_recv(sock->sock, buf, len, MSG_PEEK);
1701 528 hiro
}
1702 528 hiro
1703 528 hiro
gint sock_close(SockInfo *sock)
1704 528 hiro
{
1705 1230 hiro
        GList *cur;
1706 1230 hiro
1707 528 hiro
        if (!sock)
1708 528 hiro
                return 0;
1709 528 hiro
1710 528 hiro
#if USE_SSL
1711 528 hiro
        if (sock->ssl)
1712 528 hiro
                ssl_done_socket(sock);
1713 528 hiro
#endif
1714 528 hiro
1715 528 hiro
        if (sock->sock_ch) {
1716 528 hiro
                g_io_channel_shutdown(sock->sock_ch, FALSE, NULL);
1717 528 hiro
                g_io_channel_unref(sock->sock_ch);
1718 528 hiro
        }
1719 528 hiro
1720 1230 hiro
        for (cur = sock_list; cur != NULL; cur = cur->next) {
1721 1230 hiro
                if ((SockInfo *)cur->data == sock) {
1722 1230 hiro
                        sock_list = g_list_remove(sock_list, sock);
1723 1230 hiro
                        break;
1724 1230 hiro
                }
1725 1230 hiro
        }
1726 1230 hiro
1727 528 hiro
        g_free(sock->hostname);
1728 528 hiro
        g_free(sock);
1729 528 hiro
1730 528 hiro
        return 0;
1731 528 hiro
}
1732 528 hiro
1733 528 hiro
gint fd_close(gint fd)
1734 528 hiro
{
1735 528 hiro
#ifdef G_OS_WIN32
1736 528 hiro
        return closesocket(fd);
1737 528 hiro
#else
1738 528 hiro
        return close(fd);
1739 528 hiro
#endif
1740 528 hiro
}