]> git.saurik.com Git - wxWidgets.git/blame - src/unix/gsocket.c
applied SF patch #846738 mousewheel support
[wxWidgets.git] / src / unix / gsocket.c
CommitLineData
a324a7bc
GL
1/* -------------------------------------------------------------------------
2 * Project: GSocket (Generic Socket) for WX
3 * Name: gsocket.c
9bf10d6b
GRG
4 * Authors: Guilhem Lavaux,
5 * Guillermo Rodriguez Garcia <guille@iies.es> (maintainer)
a324a7bc 6 * Purpose: GSocket main Unix file
84969af7 7 * Licence: The wxWindows licence
a324a7bc 8 * CVSID: $Id$
a324a7bc
GL
9 * -------------------------------------------------------------------------
10 */
11
9bf10d6b
GRG
12/*
13 * PLEASE don't put C++ comments here - this is a C source file.
14 */
15
16#ifndef __GSOCKET_STANDALONE__
813c20a6 17#include "wx/setup.h"
9bf10d6b 18#endif
813c20a6 19
9bf10d6b 20#if wxUSE_SOCKETS || defined(__GSOCKET_STANDALONE__)
813c20a6 21
a324a7bc 22#include <assert.h>
efee48a0 23#include <sys/types.h>
6a2e7225
VZ
24#include <netdb.h>
25#include <sys/ioctl.h>
9bf10d6b 26
af9d1662 27#ifdef __VMS__
a324a7bc 28#include <socket.h>
5c9eff30
GRG
29struct sockaddr_un
30{
9bf10d6b
GRG
31 u_char sun_len; /* sockaddr len including null */
32 u_char sun_family; /* AF_UNIX */
33 char sun_path[108]; /* path name (gag) */
af9d1662 34};
a324a7bc
GL
35#else
36#include <sys/socket.h>
a324a7bc 37#include <sys/un.h>
af9d1662 38#endif
9bf10d6b 39
a324a7bc
GL
40#include <sys/time.h>
41#include <netinet/in.h>
42#include <arpa/inet.h>
9592b687 43#include <errno.h>
a324a7bc
GL
44#include <string.h>
45#include <unistd.h>
46#include <stdio.h>
47#include <stdlib.h>
552e8bf8 48#include <stddef.h>
9b61f868 49#include <ctype.h>
a324a7bc 50#ifdef sun
9bf10d6b 51# include <sys/filio.h>
a324a7bc 52#endif
a324a7bc 53#ifdef sgi
9bf10d6b 54# include <bstring.h>
a324a7bc 55#endif
a324a7bc 56#include <signal.h>
5a96d2f4 57
efee48a0 58#ifndef SOCKLEN_T
5a96d2f4 59
85806dc2
GRG
60#ifdef VMS
61# define SOCKLEN_T unsigned int
5a96d2f4 62#else
85806dc2
GRG
63# ifdef __GLIBC__
64# if __GLIBC__ == 2
aac67d4c 65# define SOCKLEN_T socklen_t
85806dc2
GRG
66# endif
67# else
68# define SOCKLEN_T int
69# endif
5a96d2f4
GL
70#endif
71
ddb56b38 72#endif /* SOCKLEN_T */
efee48a0 73
aac67d4c
GRG
74/*
75 * MSW defines this, Unices don't.
76 */
77#ifndef INVALID_SOCKET
78#define INVALID_SOCKET -1
79#endif
9bf10d6b 80
a5e3c24d
VZ
81/* UnixWare reportedly needs this for FIONBIO definition */
82#ifdef __UNIXWARE__
83#include <sys/filio.h>
84#endif
85
9bf10d6b
GRG
86/*
87 * INADDR_BROADCAST is identical to INADDR_NONE which is not defined
aac67d4c 88 * on all systems. INADDR_BROADCAST should be fine to indicate an error.
9bf10d6b
GRG
89 */
90#ifndef INADDR_NONE
91#define INADDR_NONE INADDR_BROADCAST
92#endif
93
483249fc
GRG
94#define MASK_SIGNAL() \
95{ \
96 void (*old_handler)(int); \
97 \
aa6d9706
GL
98 old_handler = signal(SIGPIPE, SIG_IGN);
99
483249fc
GRG
100#define UNMASK_SIGNAL() \
101 signal(SIGPIPE, old_handler); \
aa6d9706
GL
102}
103
54e575f9 104
9bf10d6b 105#ifndef __GSOCKET_STANDALONE__
8e907a13
VZ
106# include "wx/unix/gsockunx.h"
107# include "wx/gsocket.h"
9bf10d6b 108#else
8e907a13
VZ
109# include "gsockunx.h"
110# include "gsocket.h"
9bf10d6b
GRG
111#endif /* __GSOCKET_STANDALONE__ */
112
8e907a13
VZ
113/* debugging helpers */
114#ifdef __GSOCKET_DEBUG__
032d5581 115# define GSocket_Debug(args) printf args
8e907a13 116#else
032d5581
GRG
117# define GSocket_Debug(args)
118#endif /* __GSOCKET_DEBUG__ */
8e907a13 119
38bb138f
VS
120/* Table of GUI-related functions. We must call them indirectly because
121 * of wxBase and GUI separation: */
122
123static struct GSocketGUIFunctionsTable *gs_gui_functions;
124
125#define USE_GUI() (gs_gui_functions != NULL)
126
127/* Define macros to simplify indirection: */
128#define _GSocket_GUI_Init() \
129 if (gs_gui_functions) gs_gui_functions->GUI_Init()
130#define _GSocket_GUI_Cleanup() \
131 if (gs_gui_functions) gs_gui_functions->GUI_Cleanup()
132#define _GSocket_GUI_Init_Socket(socket) \
133 (gs_gui_functions ? gs_gui_functions->GUI_Init_Socket(socket) : 1)
134#define _GSocket_GUI_Destroy_Socket(socket) \
135 if (gs_gui_functions) gs_gui_functions->GUI_Destroy_Socket(socket)
136#define _GSocket_Enable_Events(socket) \
137 if (gs_gui_functions) gs_gui_functions->Enable_Events(socket)
138#define _GSocket_Disable_Events(socket) \
139 if (gs_gui_functions) gs_gui_functions->Disable_Events(socket)
140#define _GSocket_Install_Callback(socket, event) \
141 if (gs_gui_functions) gs_gui_functions->Install_Callback(socket, event)
142#define _GSocket_Uninstall_Callback(socket, event) \
143 if (gs_gui_functions) gs_gui_functions->Uninstall_Callback(socket, event)
144
145static struct GSocketBaseFunctionsTable gs_base_functions =
146{
147 _GSocket_Detected_Read,
148 _GSocket_Detected_Write
149};
150
a58d5df4
GL
151/* Global initialisers */
152
38bb138f
VS
153void GSocket_SetGUIFunctions(struct GSocketGUIFunctionsTable *guifunc)
154{
155 gs_gui_functions = guifunc;
156}
157
5c9eff30 158int GSocket_Init(void)
a58d5df4 159{
38bb138f
VS
160 if (gs_gui_functions)
161 {
162 if ( !gs_gui_functions->GUI_Init() )
163 return 0;
164 }
5c9eff30 165 return 1;
a58d5df4
GL
166}
167
da051b23 168void GSocket_Cleanup(void)
a58d5df4 169{
38bb138f
VS
170 if (gs_gui_functions)
171 {
172 gs_gui_functions->GUI_Cleanup();
173 }
a58d5df4
GL
174}
175
9bf10d6b 176/* Constructors / Destructors for GSocket */
a324a7bc 177
da051b23 178GSocket *GSocket_new(void)
a324a7bc 179{
8e907a13 180 int i, success;
a324a7bc
GL
181 GSocket *socket;
182
183 socket = (GSocket *)malloc(sizeof(GSocket));
184
e00f35bb
GL
185 if (socket == NULL)
186 return NULL;
187
aac67d4c 188 socket->m_fd = INVALID_SOCKET;
483249fc
GRG
189 for (i=0;i<GSOCK_MAX_EVENT;i++)
190 {
98781fa3 191 socket->m_cbacks[i] = NULL;
a324a7bc 192 }
483249fc 193 socket->m_detected = 0;
a324a7bc
GL
194 socket->m_local = NULL;
195 socket->m_peer = NULL;
196 socket->m_error = GSOCK_NOERROR;
ef25e638
GRG
197 socket->m_server = FALSE;
198 socket->m_stream = TRUE;
199 socket->m_gui_dependent = NULL;
200 socket->m_non_blocking = FALSE;
39b91eca 201 socket->m_timeout = 10*60*1000;
ef25e638 202 /* 10 minutes * 60 sec * 1000 millisec */
aa6d9706 203 socket->m_establishing = FALSE;
a324a7bc 204
38bb138f
VS
205 socket->m_functions = &gs_base_functions;
206
da051b23 207 /* Per-socket GUI-specific initialization */
38bb138f 208 success = _GSocket_GUI_Init_Socket(socket);
8e907a13 209 if (!success)
da051b23
GRG
210 {
211 free(socket);
212 return NULL;
213 }
a324a7bc
GL
214
215 return socket;
216}
217
007c77ab
RL
218void GSocket_close(GSocket *socket)
219{
220 _GSocket_Disable_Events(socket);
221 close(socket->m_fd);
222 socket->m_fd = INVALID_SOCKET;
223}
224
a324a7bc
GL
225void GSocket_destroy(GSocket *socket)
226{
227 assert(socket != NULL);
228
9bf10d6b 229 /* Check that the socket is really shutdowned */
aac67d4c 230 if (socket->m_fd != INVALID_SOCKET)
a324a7bc
GL
231 GSocket_Shutdown(socket);
232
f6f13cd4 233 /* Per-socket GUI-specific cleanup */
38bb138f 234 _GSocket_GUI_Destroy_Socket(socket);
f6f13cd4 235
9bf10d6b 236 /* Destroy private addresses */
a324a7bc
GL
237 if (socket->m_local)
238 GAddress_destroy(socket->m_local);
239
240 if (socket->m_peer)
241 GAddress_destroy(socket->m_peer);
242
9bf10d6b 243 /* Destroy the socket itself */
a324a7bc
GL
244 free(socket);
245}
246
9bf10d6b
GRG
247/* GSocket_Shutdown:
248 * Disallow further read/write operations on this socket, close
249 * the fd and disable all callbacks.
250 */
a324a7bc
GL
251void GSocket_Shutdown(GSocket *socket)
252{
253 int evt;
254
255 assert(socket != NULL);
256
9bf10d6b 257 /* If socket has been created, shutdown it */
aac67d4c 258 if (socket->m_fd != INVALID_SOCKET)
483249fc 259 {
533c7161 260 shutdown(socket->m_fd, 2);
007c77ab 261 GSocket_close(socket);
a324a7bc
GL
262 }
263
9bf10d6b 264 /* Disable GUI callbacks */
483249fc
GRG
265 for (evt = 0; evt < GSOCK_MAX_EVENT; evt++)
266 socket->m_cbacks[evt] = NULL;
267
557e7011 268 socket->m_detected = GSOCK_LOST_FLAG;
a324a7bc
GL
269}
270
271/* Address handling */
272
9bf10d6b
GRG
273/* GSocket_SetLocal:
274 * GSocket_GetLocal:
275 * GSocket_SetPeer:
276 * GSocket_GetPeer:
277 * Set or get the local or peer address for this socket. The 'set'
278 * functions return GSOCK_NOERROR on success, an error code otherwise.
279 * The 'get' functions return a pointer to a GAddress object on success,
280 * or NULL otherwise, in which case they set the error code of the
281 * corresponding GSocket.
282 *
283 * Error codes:
284 * GSOCK_INVSOCK - the socket is not valid.
285 * GSOCK_INVADDR - the address is not valid.
286 */
a324a7bc
GL
287GSocketError GSocket_SetLocal(GSocket *socket, GAddress *address)
288{
5a96d2f4
GL
289 assert(socket != NULL);
290
9bf10d6b 291 /* the socket must be initialized, or it must be a server */
aac67d4c 292 if ((socket->m_fd != INVALID_SOCKET && !socket->m_server))
9bf10d6b 293 {
31989b0b 294 socket->m_error = GSOCK_INVSOCK;
a324a7bc 295 return GSOCK_INVSOCK;
31989b0b 296 }
a324a7bc 297
9bf10d6b
GRG
298 /* check address */
299 if (address == NULL || address->m_family == GSOCK_NOFAMILY)
300 {
31989b0b 301 socket->m_error = GSOCK_INVADDR;
a324a7bc 302 return GSOCK_INVADDR;
31989b0b 303 }
a324a7bc
GL
304
305 if (socket->m_local)
306 GAddress_destroy(socket->m_local);
307
308 socket->m_local = GAddress_copy(address);
309
310 return GSOCK_NOERROR;
311}
312
313GSocketError GSocket_SetPeer(GSocket *socket, GAddress *address)
314{
5a96d2f4 315 assert(socket != NULL);
a324a7bc 316
9bf10d6b
GRG
317 /* check address */
318 if (address == NULL || address->m_family == GSOCK_NOFAMILY)
319 {
a324a7bc
GL
320 socket->m_error = GSOCK_INVADDR;
321 return GSOCK_INVADDR;
322 }
323
324 if (socket->m_peer)
325 GAddress_destroy(socket->m_peer);
326
327 socket->m_peer = GAddress_copy(address);
328
329 return GSOCK_NOERROR;
330}
331
332GAddress *GSocket_GetLocal(GSocket *socket)
333{
334 GAddress *address;
335 struct sockaddr addr;
85806dc2 336 SOCKLEN_T size = sizeof(addr);
aa6d9706 337 GSocketError err;
a324a7bc
GL
338
339 assert(socket != NULL);
340
9bf10d6b 341 /* try to get it from the m_local var first */
a324a7bc
GL
342 if (socket->m_local)
343 return GAddress_copy(socket->m_local);
344
9bf10d6b 345 /* else, if the socket is initialized, try getsockname */
aac67d4c 346 if (socket->m_fd == INVALID_SOCKET)
9bf10d6b 347 {
a324a7bc
GL
348 socket->m_error = GSOCK_INVSOCK;
349 return NULL;
350 }
351
9bf10d6b
GRG
352 if (getsockname(socket->m_fd, &addr, (SOCKLEN_T *) &size) < 0)
353 {
a324a7bc
GL
354 socket->m_error = GSOCK_IOERR;
355 return NULL;
356 }
357
9bf10d6b 358 /* got a valid address from getsockname, create a GAddress object */
a324a7bc 359 address = GAddress_new();
9bf10d6b
GRG
360 if (address == NULL)
361 {
e00f35bb
GL
362 socket->m_error = GSOCK_MEMERR;
363 return NULL;
364 }
9bf10d6b
GRG
365
366 err = _GAddress_translate_from(address, &addr, size);
367 if (err != GSOCK_NOERROR)
368 {
e00f35bb 369 GAddress_destroy(address);
85806dc2 370 socket->m_error = err;
e00f35bb
GL
371 return NULL;
372 }
a324a7bc
GL
373
374 return address;
375}
376
377GAddress *GSocket_GetPeer(GSocket *socket)
378{
379 assert(socket != NULL);
380
9bf10d6b 381 /* try to get it from the m_peer var */
a324a7bc
GL
382 if (socket->m_peer)
383 return GAddress_copy(socket->m_peer);
384
385 return NULL;
386}
387
388/* Server specific parts */
389
2f7c2af5 390/* GSocket_SetServer:
9bf10d6b
GRG
391 * Sets up this socket as a server. The local address must have been
392 * set with GSocket_SetLocal() before GSocket_SetServer() is called.
393 * Returns GSOCK_NOERROR on success, one of the following otherwise:
394 *
395 * Error codes:
396 * GSOCK_INVSOCK - the socket is in use.
397 * GSOCK_INVADDR - the local address has not been set.
398 * GSOCK_IOERR - low-level error.
2f7c2af5 399 */
a324a7bc
GL
400GSocketError GSocket_SetServer(GSocket *sck)
401{
483249fc 402 int arg = 1;
a324a7bc
GL
403
404 assert(sck != NULL);
405
9bf10d6b 406 /* must not be in use */
aac67d4c 407 if (sck->m_fd != INVALID_SOCKET)
9bf10d6b 408 {
a324a7bc
GL
409 sck->m_error = GSOCK_INVSOCK;
410 return GSOCK_INVSOCK;
411 }
412
9bf10d6b
GRG
413 /* the local addr must have been set */
414 if (!sck->m_local)
415 {
a324a7bc
GL
416 sck->m_error = GSOCK_INVADDR;
417 return GSOCK_INVADDR;
418 }
419
9bf10d6b
GRG
420 /* Initialize all fields */
421 sck->m_stream = TRUE;
422 sck->m_server = TRUE;
423 sck->m_oriented = TRUE;
a324a7bc 424
f61815af
GL
425 /* Create the socket */
426 sck->m_fd = socket(sck->m_local->m_realfamily, SOCK_STREAM, 0);
a324a7bc 427
aac67d4c 428 if (sck->m_fd == INVALID_SOCKET)
9bf10d6b 429 {
a324a7bc
GL
430 sck->m_error = GSOCK_IOERR;
431 return GSOCK_IOERR;
432 }
433
483249fc
GRG
434 ioctl(sck->m_fd, FIONBIO, &arg);
435 _GSocket_Enable_Events(sck);
436
9bf10d6b
GRG
437 /* Bind to the local address,
438 * retrieve the actual address bound,
439 * and listen up to 5 connections.
440 */
441 if ((bind(sck->m_fd, sck->m_local->m_addr, sck->m_local->m_len) != 0) ||
442 (getsockname(sck->m_fd,
443 sck->m_local->m_addr,
444 (SOCKLEN_T *) &sck->m_local->m_len) != 0) ||
445 (listen(sck->m_fd, 5) != 0))
446 {
007c77ab 447 GSocket_close(sck);
a324a7bc
GL
448 sck->m_error = GSOCK_IOERR;
449 return GSOCK_IOERR;
450 }
451
a324a7bc 452 return GSOCK_NOERROR;
a324a7bc
GL
453}
454
2f7c2af5 455/* GSocket_WaitConnection:
9bf10d6b
GRG
456 * Waits for an incoming client connection. Returns a pointer to
457 * a GSocket object, or NULL if there was an error, in which case
458 * the last error field will be updated for the calling GSocket.
459 *
460 * Error codes (set in the calling GSocket)
461 * GSOCK_INVSOCK - the socket is not valid or not a server.
462 * GSOCK_TIMEDOUT - timeout, no incoming connections.
463 * GSOCK_WOULDBLOCK - the call would block and the socket is nonblocking.
464 * GSOCK_MEMERR - couldn't allocate memory.
465 * GSOCK_IOERR - low-level error.
2f7c2af5 466 */
a324a7bc
GL
467GSocket *GSocket_WaitConnection(GSocket *socket)
468{
85806dc2
GRG
469 struct sockaddr from;
470 SOCKLEN_T fromlen = sizeof(from);
a324a7bc 471 GSocket *connection;
bd046d42 472 GSocketError err;
483249fc 473 int arg = 1;
a324a7bc
GL
474
475 assert(socket != NULL);
476
483249fc
GRG
477 /* Reenable CONNECTION events */
478 _GSocket_Enable(socket, GSOCK_CONNECTION);
479
f61815af 480 /* If the socket has already been created, we exit immediately */
aac67d4c 481 if (socket->m_fd == INVALID_SOCKET || !socket->m_server)
483249fc 482 {
a324a7bc
GL
483 socket->m_error = GSOCK_INVSOCK;
484 return NULL;
485 }
486
f61815af 487 /* Create a GSocket object for the new connection */
a324a7bc 488 connection = GSocket_new();
9bf10d6b 489
483249fc
GRG
490 if (!connection)
491 {
85806dc2 492 socket->m_error = GSOCK_MEMERR;
aa6d9706
GL
493 return NULL;
494 }
a324a7bc 495
9bf10d6b 496 /* Wait for a connection (with timeout) */
483249fc
GRG
497 if (_GSocket_Input_Timeout(socket) == GSOCK_TIMEDOUT)
498 {
499 GSocket_destroy(connection);
500 /* socket->m_error set by _GSocket_Input_Timeout */
501 return NULL;
502 }
503
85806dc2 504 connection->m_fd = accept(socket->m_fd, &from, (SOCKLEN_T *) &fromlen);
483249fc 505
aac67d4c 506 if (connection->m_fd == INVALID_SOCKET)
483249fc
GRG
507 {
508 if (errno == EWOULDBLOCK)
509 socket->m_error = GSOCK_WOULDBLOCK;
510 else
511 socket->m_error = GSOCK_IOERR;
512
a324a7bc 513 GSocket_destroy(connection);
a324a7bc
GL
514 return NULL;
515 }
516
f61815af 517 /* Initialize all fields */
a324a7bc 518 connection->m_server = FALSE;
483249fc 519 connection->m_stream = TRUE;
a324a7bc
GL
520 connection->m_oriented = TRUE;
521
9bf10d6b 522 /* Setup the peer address field */
85806dc2
GRG
523 connection->m_peer = GAddress_new();
524 if (!connection->m_peer)
525 {
526 GSocket_destroy(connection);
527 socket->m_error = GSOCK_MEMERR;
528 return NULL;
529 }
530 err = _GAddress_translate_from(connection->m_peer, &from, fromlen);
531 if (err != GSOCK_NOERROR)
532 {
533 GAddress_destroy(connection->m_peer);
534 GSocket_destroy(connection);
535 socket->m_error = err;
536 return NULL;
537 }
538
483249fc
GRG
539 ioctl(connection->m_fd, FIONBIO, &arg);
540 _GSocket_Enable_Events(connection);
2f7c2af5 541
a324a7bc
GL
542 return connection;
543}
544
a324a7bc
GL
545/* Client specific parts */
546
2f7c2af5 547/* GSocket_Connect:
9bf10d6b
GRG
548 * For stream (connection oriented) sockets, GSocket_Connect() tries
549 * to establish a client connection to a server using the peer address
550 * as established with GSocket_SetPeer(). Returns GSOCK_NOERROR if the
551 * connection has been succesfully established, or one of the error
552 * codes listed below. Note that for nonblocking sockets, a return
553 * value of GSOCK_WOULDBLOCK doesn't mean a failure. The connection
554 * request can be completed later; you should use GSocket_Select()
555 * to poll for GSOCK_CONNECTION | GSOCK_LOST, or wait for the
556 * corresponding asynchronous events.
557 *
558 * For datagram (non connection oriented) sockets, GSocket_Connect()
559 * just sets the peer address established with GSocket_SetPeer() as
560 * default destination.
561 *
562 * Error codes:
563 * GSOCK_INVSOCK - the socket is in use or not valid.
564 * GSOCK_INVADDR - the peer address has not been established.
565 * GSOCK_TIMEDOUT - timeout, the connection failed.
566 * GSOCK_WOULDBLOCK - connection in progress (nonblocking sockets only)
567 * GSOCK_MEMERR - couldn't allocate memory.
568 * GSOCK_IOERR - low-level error.
2f7c2af5 569 */
a324a7bc
GL
570GSocketError GSocket_Connect(GSocket *sck, GSocketStream stream)
571{
9bf10d6b 572 int err, ret;
483249fc 573 int arg = 1;
a324a7bc
GL
574
575 assert(sck != NULL);
576
483249fc
GRG
577 /* Enable CONNECTION events (needed for nonblocking connections) */
578 _GSocket_Enable(sck, GSOCK_CONNECTION);
579
aac67d4c 580 if (sck->m_fd != INVALID_SOCKET)
483249fc 581 {
a324a7bc
GL
582 sck->m_error = GSOCK_INVSOCK;
583 return GSOCK_INVSOCK;
584 }
585
483249fc
GRG
586 if (!sck->m_peer)
587 {
a324a7bc
GL
588 sck->m_error = GSOCK_INVADDR;
589 return GSOCK_INVADDR;
590 }
591
9bf10d6b 592 /* Streamed or dgram socket? */
483249fc 593 sck->m_stream = (stream == GSOCK_STREAMED);
a324a7bc 594 sck->m_oriented = TRUE;
483249fc
GRG
595 sck->m_server = FALSE;
596 sck->m_establishing = FALSE;
a324a7bc 597
f61815af 598 /* Create the socket */
9bf10d6b
GRG
599 sck->m_fd = socket(sck->m_peer->m_realfamily,
600 sck->m_stream? SOCK_STREAM : SOCK_DGRAM, 0);
a324a7bc 601
aac67d4c 602 if (sck->m_fd == INVALID_SOCKET)
9bf10d6b 603 {
a324a7bc
GL
604 sck->m_error = GSOCK_IOERR;
605 return GSOCK_IOERR;
606 }
607
483249fc
GRG
608 ioctl(sck->m_fd, FIONBIO, &arg);
609 _GSocket_Enable_Events(sck);
aa6d9706 610
9bf10d6b 611 /* Connect it to the peer address, with a timeout (see below) */
483249fc
GRG
612 ret = connect(sck->m_fd, sck->m_peer->m_addr, sck->m_peer->m_len);
613
614 if (ret == -1)
615 {
616 err = errno;
617
618 /* If connect failed with EINPROGRESS and the GSocket object
619 * is in blocking mode, we select() for the specified timeout
620 * checking for writability to see if the connection request
621 * completes.
622 */
623 if ((err == EINPROGRESS) && (!sck->m_non_blocking))
624 {
625 if (_GSocket_Output_Timeout(sck) == GSOCK_TIMEDOUT)
626 {
007c77ab 627 GSocket_close(sck);
483249fc 628 /* sck->m_error is set in _GSocket_Output_Timeout */
483249fc
GRG
629 return GSOCK_TIMEDOUT;
630 }
631 else
632 {
9bf10d6b
GRG
633 int error;
634 SOCKLEN_T len = sizeof(error);
635
636 getsockopt(sck->m_fd, SOL_SOCKET, SO_ERROR, (void*) &error, &len);
637
638 if (!error)
639 return GSOCK_NOERROR;
483249fc
GRG
640 }
641 }
642
643 /* If connect failed with EINPROGRESS and the GSocket object
644 * is set to nonblocking, we set m_error to GSOCK_WOULDBLOCK
645 * (and return GSOCK_WOULDBLOCK) but we don't close the socket;
646 * this way if the connection completes, a GSOCK_CONNECTION
647 * event will be generated, if enabled.
648 */
649 if ((err == EINPROGRESS) && (sck->m_non_blocking))
650 {
483249fc 651 sck->m_establishing = TRUE;
9bf10d6b 652 sck->m_error = GSOCK_WOULDBLOCK;
483249fc
GRG
653 return GSOCK_WOULDBLOCK;
654 }
aa6d9706 655
483249fc
GRG
656 /* If connect failed with an error other than EINPROGRESS,
657 * then the call to GSocket_Connect has failed.
658 */
007c77ab 659 GSocket_close(sck);
aac67d4c
GRG
660 sck->m_error = GSOCK_IOERR;
661 return GSOCK_IOERR;
662 }
663
664 return GSOCK_NOERROR;
665}
666
667/* Datagram sockets */
668
669/* GSocket_SetNonOriented:
670 * Sets up this socket as a non-connection oriented (datagram) socket.
671 * Before using this function, the local address must have been set
672 * with GSocket_SetLocal(), or the call will fail. Returns GSOCK_NOERROR
673 * on success, or one of the following otherwise.
674 *
675 * Error codes:
676 * GSOCK_INVSOCK - the socket is in use.
677 * GSOCK_INVADDR - the local address has not been set.
678 * GSOCK_IOERR - low-level error.
679 */
680GSocketError GSocket_SetNonOriented(GSocket *sck)
681{
682 int arg = 1;
683
684 assert(sck != NULL);
685
686 if (sck->m_fd != INVALID_SOCKET)
687 {
688 sck->m_error = GSOCK_INVSOCK;
689 return GSOCK_INVSOCK;
690 }
691
692 if (!sck->m_local)
693 {
694 sck->m_error = GSOCK_INVADDR;
695 return GSOCK_INVADDR;
696 }
697
698 /* Initialize all fields */
699 sck->m_stream = FALSE;
700 sck->m_server = FALSE;
701 sck->m_oriented = FALSE;
702
703 /* Create the socket */
704 sck->m_fd = socket(sck->m_local->m_realfamily, SOCK_DGRAM, 0);
705
706 if (sck->m_fd == INVALID_SOCKET)
707 {
708 sck->m_error = GSOCK_IOERR;
709 return GSOCK_IOERR;
710 }
711
712 ioctl(sck->m_fd, FIONBIO, &arg);
713 _GSocket_Enable_Events(sck);
714
715 /* Bind to the local address,
716 * and retrieve the actual address bound.
717 */
718 if ((bind(sck->m_fd, sck->m_local->m_addr, sck->m_local->m_len) != 0) ||
719 (getsockname(sck->m_fd,
720 sck->m_local->m_addr,
721 (SOCKLEN_T *) &sck->m_local->m_len) != 0))
722 {
007c77ab 723 GSocket_close(sck);
483249fc 724 sck->m_error = GSOCK_IOERR;
a324a7bc
GL
725 return GSOCK_IOERR;
726 }
39b91eca 727
483249fc 728 return GSOCK_NOERROR;
a324a7bc
GL
729}
730
731/* Generic IO */
732
733/* Like recv(), send(), ... */
734int GSocket_Read(GSocket *socket, char *buffer, int size)
735{
483249fc
GRG
736 int ret;
737
a324a7bc
GL
738 assert(socket != NULL);
739
483249fc
GRG
740 /* Reenable INPUT events */
741 _GSocket_Enable(socket, GSOCK_INPUT);
742
aac67d4c 743 if (socket->m_fd == INVALID_SOCKET || socket->m_server)
483249fc 744 {
a324a7bc
GL
745 socket->m_error = GSOCK_INVSOCK;
746 return -1;
747 }
748
9bf10d6b 749 /* If the socket is blocking, wait for data (with a timeout) */
483249fc
GRG
750 if (_GSocket_Input_Timeout(socket) == GSOCK_TIMEDOUT)
751 return -1;
a324a7bc 752
9bf10d6b 753 /* Read the data */
f61815af 754 if (socket->m_stream)
483249fc 755 ret = _GSocket_Recv_Stream(socket, buffer, size);
a324a7bc 756 else
483249fc
GRG
757 ret = _GSocket_Recv_Dgram(socket, buffer, size);
758
759 if (ret == -1)
760 {
761 if (errno == EWOULDBLOCK)
762 socket->m_error = GSOCK_WOULDBLOCK;
763 else
764 socket->m_error = GSOCK_IOERR;
765 }
766
767 return ret;
a324a7bc
GL
768}
769
9bf10d6b
GRG
770int GSocket_Write(GSocket *socket, const char *buffer, int size)
771{
483249fc
GRG
772 int ret;
773
a324a7bc 774 assert(socket != NULL);
856bc99a 775
8e907a13 776 GSocket_Debug(( "GSocket_Write #1, size %d\n", size ));
a324a7bc 777
aac67d4c 778 if (socket->m_fd == INVALID_SOCKET || socket->m_server)
483249fc 779 {
a324a7bc
GL
780 socket->m_error = GSOCK_INVSOCK;
781 return -1;
782 }
783
8e907a13 784 GSocket_Debug(( "GSocket_Write #2, size %d\n", size ));
856bc99a 785
9bf10d6b 786 /* If the socket is blocking, wait for writability (with a timeout) */
483249fc
GRG
787 if (_GSocket_Output_Timeout(socket) == GSOCK_TIMEDOUT)
788 return -1;
a324a7bc 789
8e907a13 790 GSocket_Debug(( "GSocket_Write #3, size %d\n", size ));
856bc99a 791
9bf10d6b 792 /* Write the data */
f61815af 793 if (socket->m_stream)
483249fc 794 ret = _GSocket_Send_Stream(socket, buffer, size);
a324a7bc 795 else
483249fc
GRG
796 ret = _GSocket_Send_Dgram(socket, buffer, size);
797
8e907a13 798 GSocket_Debug(( "GSocket_Write #4, size %d\n", size ));
856bc99a 799
483249fc
GRG
800 if (ret == -1)
801 {
802 if (errno == EWOULDBLOCK)
d5ab387d 803 {
483249fc 804 socket->m_error = GSOCK_WOULDBLOCK;
8e907a13 805 GSocket_Debug(( "GSocket_Write error WOULDBLOCK\n" ));
d5ab387d 806 }
483249fc 807 else
d5ab387d 808 {
483249fc 809 socket->m_error = GSOCK_IOERR;
8e907a13 810 GSocket_Debug(( "GSocket_Write error IOERR\n" ));
d5ab387d 811 }
483249fc
GRG
812
813 /* Only reenable OUTPUT events after an error (just like WSAAsyncSelect
814 * in MSW). Once the first OUTPUT event is received, users can assume
815 * that the socket is writable until a read operation fails. Only then
816 * will further OUTPUT events be posted.
817 */
818 _GSocket_Enable(socket, GSOCK_OUTPUT);
9bf10d6b 819 return -1;
483249fc
GRG
820 }
821
8e907a13 822 GSocket_Debug(( "GSocket_Write #5, size %d ret %d\n", size, ret ));
856bc99a 823
483249fc 824 return ret;
a324a7bc
GL
825}
826
ef25e638
GRG
827/* GSocket_Select:
828 * Polls the socket to determine its status. This function will
829 * check for the events specified in the 'flags' parameter, and
830 * it will return a mask indicating which operations can be
831 * performed. This function won't block, regardless of the
9bf10d6b 832 * mode (blocking | nonblocking) of the socket.
ef25e638
GRG
833 */
834GSocketEventFlags GSocket_Select(GSocket *socket, GSocketEventFlags flags)
a324a7bc 835{
38bb138f
VS
836 if (!USE_GUI())
837 {
8e907a13 838
38bb138f
VS
839 GSocketEventFlags result = 0;
840 fd_set readfds;
841 fd_set writefds;
842 fd_set exceptfds;
843 struct timeval tv;
a324a7bc 844
38bb138f
VS
845 /* Do not use a static struct, Linux can garble it */
846 tv.tv_sec = 0;
847 tv.tv_usec = 0;
8e907a13 848
38bb138f 849 assert(socket != NULL);
aa6ca3dc 850
38bb138f
VS
851 FD_ZERO(&readfds);
852 FD_ZERO(&writefds);
853 FD_ZERO(&exceptfds);
854 FD_SET(socket->m_fd, &readfds);
855 FD_SET(socket->m_fd, &writefds);
856 FD_SET(socket->m_fd, &exceptfds);
aa6ca3dc 857
38bb138f
VS
858 /* Check 'sticky' CONNECTION flag first */
859 result |= (GSOCK_CONNECTION_FLAG & socket->m_detected);
8e907a13 860
38bb138f
VS
861 /* If we have already detected a LOST event, then don't try
862 * to do any further processing.
863 */
864 if ((socket->m_detected & GSOCK_LOST_FLAG) != 0)
865 {
866 socket->m_establishing = FALSE;
8e907a13 867
38bb138f
VS
868 return (GSOCK_LOST_FLAG & flags);
869 }
8e907a13 870
38bb138f
VS
871 /* Try select now */
872 if (select(socket->m_fd + 1, &readfds, &writefds, &exceptfds, &tv) <= 0)
8e907a13 873 {
38bb138f
VS
874 /* What to do here? */
875 return (result & flags);
8e907a13 876 }
38bb138f
VS
877
878 /* Check for readability */
879 if (FD_ISSET(socket->m_fd, &readfds))
8e907a13 880 {
38bb138f
VS
881 char c;
882
883 if (recv(socket->m_fd, &c, 1, MSG_PEEK) > 0)
8e907a13 884 {
38bb138f 885 result |= GSOCK_INPUT_FLAG;
8e907a13
VZ
886 }
887 else
888 {
38bb138f
VS
889 if (socket->m_server && socket->m_stream)
890 {
891 result |= GSOCK_CONNECTION_FLAG;
892 socket->m_detected |= GSOCK_CONNECTION_FLAG;
893 }
894 else
895 {
896 socket->m_detected = GSOCK_LOST_FLAG;
897 socket->m_establishing = FALSE;
898
899 /* LOST event: Abort any further processing */
900 return (GSOCK_LOST_FLAG & flags);
901 }
8e907a13
VZ
902 }
903 }
8e907a13 904
38bb138f
VS
905 /* Check for writability */
906 if (FD_ISSET(socket->m_fd, &writefds))
8e907a13 907 {
38bb138f
VS
908 if (socket->m_establishing && !socket->m_server)
909 {
910 int error;
911 SOCKLEN_T len = sizeof(error);
8e907a13 912
38bb138f 913 socket->m_establishing = FALSE;
8e907a13 914
38bb138f 915 getsockopt(socket->m_fd, SOL_SOCKET, SO_ERROR, (void*)&error, &len);
8e907a13 916
38bb138f
VS
917 if (error)
918 {
919 socket->m_detected = GSOCK_LOST_FLAG;
aa6ca3dc 920
38bb138f
VS
921 /* LOST event: Abort any further processing */
922 return (GSOCK_LOST_FLAG & flags);
923 }
924 else
925 {
926 result |= GSOCK_CONNECTION_FLAG;
927 socket->m_detected |= GSOCK_CONNECTION_FLAG;
928 }
8e907a13
VZ
929 }
930 else
931 {
38bb138f 932 result |= GSOCK_OUTPUT_FLAG;
8e907a13
VZ
933 }
934 }
38bb138f
VS
935
936 /* Check for exceptions and errors (is this useful in Unices?) */
937 if (FD_ISSET(socket->m_fd, &exceptfds))
8e907a13 938 {
38bb138f
VS
939 socket->m_establishing = FALSE;
940 socket->m_detected = GSOCK_LOST_FLAG;
941
942 /* LOST event: Abort any further processing */
943 return (GSOCK_LOST_FLAG & flags);
8e907a13 944 }
8e907a13 945
38bb138f 946 return (result & flags);
aa6ca3dc 947
8e907a13 948 }
38bb138f
VS
949 else
950 {
8e907a13 951
38bb138f
VS
952 assert(socket != NULL);
953 return flags & socket->m_detected;
8e907a13 954
38bb138f 955 }
a324a7bc
GL
956}
957
958/* Flags */
959
2f7c2af5 960/* GSocket_SetNonBlocking:
9bf10d6b
GRG
961 * Sets the socket to non-blocking mode. All IO calls will return
962 * immediately.
2f7c2af5 963 */
5c9eff30 964void GSocket_SetNonBlocking(GSocket *socket, int non_block)
a324a7bc
GL
965{
966 assert(socket != NULL);
967
609c60af
GRG
968 GSocket_Debug( ("GSocket_SetNonBlocking: %d\n", (int)non_block) );
969
dc26b37a 970 socket->m_non_blocking = non_block;
a324a7bc
GL
971}
972
2f7c2af5 973/* GSocket_SetTimeout:
9bf10d6b
GRG
974 * Sets the timeout for blocking calls. Time is expressed in
975 * milliseconds.
39b91eca
GL
976 */
977void GSocket_SetTimeout(GSocket *socket, unsigned long millisec)
978{
979 assert(socket != NULL);
980
54e575f9 981 socket->m_timeout = millisec;
39b91eca
GL
982}
983
2f7c2af5 984/* GSocket_GetError:
9bf10d6b
GRG
985 * Returns the last error occured for this socket. Note that successful
986 * operations do not clear this back to GSOCK_NOERROR, so use it only
987 * after an error.
2f7c2af5 988 */
a324a7bc
GL
989GSocketError GSocket_GetError(GSocket *socket)
990{
991 assert(socket != NULL);
992
993 return socket->m_error;
994}
995
996/* Callbacks */
997
9bf10d6b
GRG
998/* GSOCK_INPUT:
999 * There is data to be read in the input buffer. If, after a read
1000 * operation, there is still data available, the callback function will
1001 * be called again.
1002 * GSOCK_OUTPUT:
1003 * The socket is available for writing. That is, the next write call
1004 * won't block. This event is generated only once, when the connection is
1005 * first established, and then only if a call failed with GSOCK_WOULDBLOCK,
1006 * when the output buffer empties again. This means that the app should
1007 * assume that it can write since the first OUTPUT event, and no more
1008 * OUTPUT events will be generated unless an error occurs.
1009 * GSOCK_CONNECTION:
1010 * Connection succesfully established, for client sockets, or incoming
1011 * client connection, for server sockets. Wait for this event (also watch
1012 * out for GSOCK_LOST) after you issue a nonblocking GSocket_Connect() call.
1013 * GSOCK_LOST:
1014 * The connection is lost (or a connection request failed); this could
1015 * be due to a failure, or due to the peer closing it gracefully.
2f7c2af5
GRG
1016 */
1017
1018/* GSocket_SetCallback:
1019 * Enables the callbacks specified by 'flags'. Note that 'flags'
1020 * may be a combination of flags OR'ed toghether, so the same
1021 * callback function can be made to accept different events.
1022 * The callback function must have the following prototype:
1023 *
1024 * void function(GSocket *socket, GSocketEvent event, char *cdata)
1025 */
ef25e638 1026void GSocket_SetCallback(GSocket *socket, GSocketEventFlags flags,
9bf10d6b 1027 GSocketCallback callback, char *cdata)
a324a7bc
GL
1028{
1029 int count;
1030
483249fc 1031 assert(socket != NULL);
a324a7bc 1032
483249fc
GRG
1033 for (count = 0; count < GSOCK_MAX_EVENT; count++)
1034 {
1035 if ((flags & (1 << count)) != 0)
1036 {
98781fa3 1037 socket->m_cbacks[count] = callback;
a324a7bc 1038 socket->m_data[count] = cdata;
a324a7bc
GL
1039 }
1040 }
1041}
1042
2f7c2af5
GRG
1043/* GSocket_UnsetCallback:
1044 * Disables all callbacks specified by 'flags', which may be a
1045 * combination of flags OR'ed toghether.
1046 */
ef25e638 1047void GSocket_UnsetCallback(GSocket *socket, GSocketEventFlags flags)
a324a7bc 1048{
2f7c2af5 1049 int count;
a324a7bc
GL
1050
1051 assert(socket != NULL);
1052
483249fc
GRG
1053 for (count = 0; count < GSOCK_MAX_EVENT; count++)
1054 {
1055 if ((flags & (1 << count)) != 0)
1056 {
98781fa3 1057 socket->m_cbacks[count] = NULL;
483249fc 1058 socket->m_data[count] = NULL;
a324a7bc
GL
1059 }
1060 }
1061}
1062
9bf10d6b 1063
483249fc
GRG
1064#define CALL_CALLBACK(socket, event) { \
1065 _GSocket_Disable(socket, event); \
1066 if (socket->m_cbacks[event]) \
1067 socket->m_cbacks[event](socket, event, socket->m_data[event]); \
a324a7bc
GL
1068}
1069
483249fc 1070
a324a7bc
GL
1071void _GSocket_Enable(GSocket *socket, GSocketEvent event)
1072{
483249fc
GRG
1073 socket->m_detected &= ~(1 << event);
1074 _GSocket_Install_Callback(socket, event);
a324a7bc
GL
1075}
1076
1077void _GSocket_Disable(GSocket *socket, GSocketEvent event)
1078{
483249fc
GRG
1079 socket->m_detected |= (1 << event);
1080 _GSocket_Uninstall_Callback(socket, event);
a324a7bc
GL
1081}
1082
483249fc
GRG
1083/* _GSocket_Input_Timeout:
1084 * For blocking sockets, wait until data is available or
1085 * until timeout ellapses.
1086 */
1087GSocketError _GSocket_Input_Timeout(GSocket *socket)
2f7c2af5 1088{
483249fc
GRG
1089 struct timeval tv;
1090 fd_set readfds;
a8a0b892 1091 int ret;
483249fc
GRG
1092
1093 /* Linux select() will overwrite the struct on return */
1094 tv.tv_sec = (socket->m_timeout / 1000);
1095 tv.tv_usec = (socket->m_timeout % 1000) * 1000;
1096
1097 if (!socket->m_non_blocking)
1098 {
1099 FD_ZERO(&readfds);
1100 FD_SET(socket->m_fd, &readfds);
a8a0b892
RR
1101 ret = select(socket->m_fd + 1, &readfds, NULL, NULL, &tv);
1102 if (ret == 0)
1103 {
8e907a13 1104 GSocket_Debug(( "GSocket_Input_Timeout, select returned 0\n" ));
a8a0b892
RR
1105 socket->m_error = GSOCK_TIMEDOUT;
1106 return GSOCK_TIMEDOUT;
1107 }
1108 if (ret == -1)
483249fc 1109 {
8e907a13 1110 GSocket_Debug(( "GSocket_Input_Timeout, select returned -1\n" ));
d84afea9
GD
1111 if (errno == EBADF) { GSocket_Debug(( "Invalid file descriptor\n" )); }
1112 if (errno == EINTR) { GSocket_Debug(( "A non blocked signal was caught\n" )); }
1113 if (errno == EINVAL) { GSocket_Debug(( "The highest number descriptor is negative\n" )); }
1114 if (errno == ENOMEM) { GSocket_Debug(( "Not enough memory\n" )); }
483249fc
GRG
1115 socket->m_error = GSOCK_TIMEDOUT;
1116 return GSOCK_TIMEDOUT;
1117 }
1118 }
1119 return GSOCK_NOERROR;
1120}
1121
1122/* _GSocket_Output_Timeout:
1123 * For blocking sockets, wait until data can be sent without
1124 * blocking or until timeout ellapses.
1125 */
1126GSocketError _GSocket_Output_Timeout(GSocket *socket)
1127{
1128 struct timeval tv;
1129 fd_set writefds;
a8a0b892 1130 int ret;
483249fc
GRG
1131
1132 /* Linux select() will overwrite the struct on return */
1133 tv.tv_sec = (socket->m_timeout / 1000);
1134 tv.tv_usec = (socket->m_timeout % 1000) * 1000;
1135
609c60af
GRG
1136 GSocket_Debug( ("m_non_blocking has: %d\n", (int)socket->m_non_blocking) );
1137
483249fc
GRG
1138 if (!socket->m_non_blocking)
1139 {
1140 FD_ZERO(&writefds);
1141 FD_SET(socket->m_fd, &writefds);
a8a0b892
RR
1142 ret = select(socket->m_fd + 1, NULL, &writefds, NULL, &tv);
1143 if (ret == 0)
1144 {
8e907a13 1145 GSocket_Debug(( "GSocket_Output_Timeout, select returned 0\n" ));
a8a0b892
RR
1146 socket->m_error = GSOCK_TIMEDOUT;
1147 return GSOCK_TIMEDOUT;
1148 }
1149 if (ret == -1)
483249fc 1150 {
8e907a13 1151 GSocket_Debug(( "GSocket_Output_Timeout, select returned -1\n" ));
d84afea9
GD
1152 if (errno == EBADF) { GSocket_Debug(( "Invalid file descriptor\n" )); }
1153 if (errno == EINTR) { GSocket_Debug(( "A non blocked signal was caught\n" )); }
1154 if (errno == EINVAL) { GSocket_Debug(( "The highest number descriptor is negative\n" )); }
1155 if (errno == ENOMEM) { GSocket_Debug(( "Not enough memory\n" )); }
483249fc
GRG
1156 socket->m_error = GSOCK_TIMEDOUT;
1157 return GSOCK_TIMEDOUT;
2f7c2af5 1158 }
d84afea9
GD
1159 if ( ! FD_ISSET(socket->m_fd, &writefds) ) {
1160 GSocket_Debug(( "GSocket_Output_Timeout is buggy!\n" ));
1161 }
1162 else {
1163 GSocket_Debug(( "GSocket_Output_Timeout seems correct\n" ));
1164 }
2f7c2af5 1165 }
aac67d4c
GRG
1166 else
1167 {
8e3aec85 1168 GSocket_Debug(( "GSocket_Output_Timeout, didn't try select!\n" ));
aac67d4c
GRG
1169 }
1170
483249fc 1171 return GSOCK_NOERROR;
2f7c2af5
GRG
1172}
1173
a324a7bc
GL
1174int _GSocket_Recv_Stream(GSocket *socket, char *buffer, int size)
1175{
04e1eb03 1176 return recv(socket->m_fd, buffer, size, 0);
a324a7bc
GL
1177}
1178
1179int _GSocket_Recv_Dgram(GSocket *socket, char *buffer, int size)
1180{
1181 struct sockaddr from;
85806dc2 1182 SOCKLEN_T fromlen = sizeof(from);
ca17eff3 1183 int ret;
aa6d9706 1184 GSocketError err;
a324a7bc
GL
1185
1186 fromlen = sizeof(from);
1187
85806dc2 1188 ret = recvfrom(socket->m_fd, buffer, size, 0, &from, (SOCKLEN_T *) &fromlen);
483249fc
GRG
1189
1190 if (ret == -1)
aa6d9706 1191 return -1;
a324a7bc 1192
f61815af 1193 /* Translate a system address into a GSocket address */
483249fc
GRG
1194 if (!socket->m_peer)
1195 {
a324a7bc 1196 socket->m_peer = GAddress_new();
483249fc
GRG
1197 if (!socket->m_peer)
1198 {
e00f35bb
GL
1199 socket->m_error = GSOCK_MEMERR;
1200 return -1;
1201 }
1202 }
aa6d9706 1203 err = _GAddress_translate_from(socket->m_peer, &from, fromlen);
483249fc
GRG
1204 if (err != GSOCK_NOERROR)
1205 {
aa6d9706
GL
1206 GAddress_destroy(socket->m_peer);
1207 socket->m_peer = NULL;
1208 socket->m_error = err;
e00f35bb 1209 return -1;
aa6d9706 1210 }
a324a7bc
GL
1211
1212 return ret;
1213}
1214
1215int _GSocket_Send_Stream(GSocket *socket, const char *buffer, int size)
1216{
1217 int ret;
1218
1219 MASK_SIGNAL();
1220 ret = send(socket->m_fd, buffer, size, 0);
1221 UNMASK_SIGNAL();
483249fc 1222
a324a7bc
GL
1223 return ret;
1224}
1225
1226int _GSocket_Send_Dgram(GSocket *socket, const char *buffer, int size)
1227{
1228 struct sockaddr *addr;
1229 int len, ret;
aa6d9706 1230 GSocketError err;
a324a7bc 1231
9bf10d6b
GRG
1232 if (!socket->m_peer)
1233 {
a324a7bc
GL
1234 socket->m_error = GSOCK_INVADDR;
1235 return -1;
1236 }
1237
aa6d9706 1238 err = _GAddress_translate_to(socket->m_peer, &addr, &len);
9bf10d6b
GRG
1239 if (err != GSOCK_NOERROR)
1240 {
aa6d9706 1241 socket->m_error = err;
e00f35bb
GL
1242 return -1;
1243 }
a324a7bc
GL
1244
1245 MASK_SIGNAL();
1246 ret = sendto(socket->m_fd, buffer, size, 0, addr, len);
1247 UNMASK_SIGNAL();
a324a7bc 1248
f61815af 1249 /* Frees memory allocated from _GAddress_translate_to */
a324a7bc
GL
1250 free(addr);
1251
1252 return ret;
1253}
1254
1255void _GSocket_Detected_Read(GSocket *socket)
1256{
1257 char c;
9bf10d6b 1258
aa6ca3dc
GRG
1259 /* If we have already detected a LOST event, then don't try
1260 * to do any further processing.
1261 */
1262 if ((socket->m_detected & GSOCK_LOST_FLAG) != 0)
1263 {
1264 socket->m_establishing = FALSE;
1265
1266 CALL_CALLBACK(socket, GSOCK_LOST);
1267 GSocket_Shutdown(socket);
1268 return;
1269 }
1270
8e907a13 1271 if (recv(socket->m_fd, &c, 1, MSG_PEEK) > 0)
9bf10d6b
GRG
1272 {
1273 CALL_CALLBACK(socket, GSOCK_INPUT);
1274 }
1275 else
1276 {
8e907a13
VZ
1277 if (socket->m_server && socket->m_stream)
1278 {
1279 CALL_CALLBACK(socket, GSOCK_CONNECTION);
1280 }
1281 else
1282 {
1283 CALL_CALLBACK(socket, GSOCK_LOST);
aa6ca3dc 1284 GSocket_Shutdown(socket);
8e907a13 1285 }
a324a7bc
GL
1286 }
1287}
1288
1289void _GSocket_Detected_Write(GSocket *socket)
1290{
aa6ca3dc
GRG
1291 /* If we have already detected a LOST event, then don't try
1292 * to do any further processing.
1293 */
1294 if ((socket->m_detected & GSOCK_LOST_FLAG) != 0)
1295 {
1296 socket->m_establishing = FALSE;
1297
1298 CALL_CALLBACK(socket, GSOCK_LOST);
1299 GSocket_Shutdown(socket);
1300 return;
1301 }
1302
483249fc
GRG
1303 if (socket->m_establishing && !socket->m_server)
1304 {
9bf10d6b
GRG
1305 int error;
1306 SOCKLEN_T len = sizeof(error);
aa6d9706 1307
aa6d9706 1308 socket->m_establishing = FALSE;
aa6d9706 1309
8e907a13 1310 getsockopt(socket->m_fd, SOL_SOCKET, SO_ERROR, (void*)&error, &len);
aa6d9706 1311
483249fc
GRG
1312 if (error)
1313 {
1314 CALL_CALLBACK(socket, GSOCK_LOST);
aa6ca3dc 1315 GSocket_Shutdown(socket);
483249fc
GRG
1316 }
1317 else
1318 {
1319 CALL_CALLBACK(socket, GSOCK_CONNECTION);
1320 /* We have to fire this event by hand because CONNECTION (for clients)
1321 * and OUTPUT are internally the same and we just disabled CONNECTION
1322 * events with the above macro.
1323 */
1324 CALL_CALLBACK(socket, GSOCK_OUTPUT);
1325 }
1326 }
1327 else
1328 {
aa6d9706 1329 CALL_CALLBACK(socket, GSOCK_OUTPUT);
483249fc 1330 }
aa6d9706 1331}
a324a7bc
GL
1332
1333/*
1334 * -------------------------------------------------------------------------
1335 * GAddress
1336 * -------------------------------------------------------------------------
1337 */
1338
032d5581
GRG
1339/* CHECK_ADDRESS verifies that the current address family is either
1340 * GSOCK_NOFAMILY or GSOCK_*family*, and if it is GSOCK_NOFAMILY, it
1341 * initalizes it to be a GSOCK_*family*. In other cases, it returns
1342 * an appropiate error code.
1343 *
1344 * CHECK_ADDRESS_RETVAL does the same but returning 'retval' on error.
f61815af 1345 */
032d5581 1346#define CHECK_ADDRESS(address, family) \
9bf10d6b
GRG
1347{ \
1348 if (address->m_family == GSOCK_NOFAMILY) \
1349 if (_GAddress_Init_##family(address) != GSOCK_NOERROR) \
1350 return address->m_error; \
1351 if (address->m_family != GSOCK_##family) \
032d5581
GRG
1352 { \
1353 address->m_error = GSOCK_INVADDR; \
1354 return GSOCK_INVADDR; \
1355 } \
1356}
1357
1358#define CHECK_ADDRESS_RETVAL(address, family, retval) \
1359{ \
1360 if (address->m_family == GSOCK_NOFAMILY) \
1361 if (_GAddress_Init_##family(address) != GSOCK_NOERROR) \
1362 return retval; \
1363 if (address->m_family != GSOCK_##family) \
9bf10d6b
GRG
1364 { \
1365 address->m_error = GSOCK_INVADDR; \
1366 return retval; \
1367 } \
a324a7bc
GL
1368}
1369
032d5581 1370
da051b23 1371GAddress *GAddress_new(void)
a324a7bc
GL
1372{
1373 GAddress *address;
1374
9bf10d6b 1375 if ((address = (GAddress *) malloc(sizeof(GAddress))) == NULL)
e00f35bb
GL
1376 return NULL;
1377
a324a7bc
GL
1378 address->m_family = GSOCK_NOFAMILY;
1379 address->m_addr = NULL;
1380 address->m_len = 0;
1381
1382 return address;
1383}
1384
1385GAddress *GAddress_copy(GAddress *address)
1386{
1387 GAddress *addr2;
1388
1389 assert(address != NULL);
1390
9bf10d6b 1391 if ((addr2 = (GAddress *) malloc(sizeof(GAddress))) == NULL)
e00f35bb
GL
1392 return NULL;
1393
a324a7bc
GL
1394 memcpy(addr2, address, sizeof(GAddress));
1395
007c77ab 1396 if (address->m_addr && address->m_len > 0)
9bf10d6b 1397 {
a324a7bc 1398 addr2->m_addr = (struct sockaddr *)malloc(addr2->m_len);
9bf10d6b
GRG
1399 if (addr2->m_addr == NULL)
1400 {
e00f35bb
GL
1401 free(addr2);
1402 return NULL;
1403 }
a324a7bc
GL
1404 memcpy(addr2->m_addr, address->m_addr, addr2->m_len);
1405 }
1406
1407 return addr2;
1408}
1409
1410void GAddress_destroy(GAddress *address)
1411{
1412 assert(address != NULL);
1413
29c25a8e
GRG
1414 if (address->m_addr)
1415 free(address->m_addr);
1416
a324a7bc
GL
1417 free(address);
1418}
1419
1420void GAddress_SetFamily(GAddress *address, GAddressType type)
1421{
1422 assert(address != NULL);
1423
1424 address->m_family = type;
1425}
1426
1427GAddressType GAddress_GetFamily(GAddress *address)
1428{
1429 assert(address != NULL);
1430
1431 return address->m_family;
1432}
1433
9bf10d6b
GRG
1434GSocketError _GAddress_translate_from(GAddress *address,
1435 struct sockaddr *addr, int len)
1436{
a324a7bc 1437 address->m_realfamily = addr->sa_family;
9bf10d6b
GRG
1438 switch (addr->sa_family)
1439 {
1440 case AF_INET:
1441 address->m_family = GSOCK_INET;
1442 break;
1443 case AF_UNIX:
1444 address->m_family = GSOCK_UNIX;
1445 break;
efee48a0 1446#ifdef AF_INET6
9bf10d6b
GRG
1447 case AF_INET6:
1448 address->m_family = GSOCK_INET6;
1449 break;
efee48a0 1450#endif
9bf10d6b 1451 default:
ca17eff3 1452 {
9bf10d6b
GRG
1453 address->m_error = GSOCK_INVOP;
1454 return GSOCK_INVOP;
ca17eff3 1455 }
a324a7bc
GL
1456 }
1457
1458 if (address->m_addr)
1459 free(address->m_addr);
1460
1461 address->m_len = len;
1462 address->m_addr = (struct sockaddr *)malloc(len);
9bf10d6b
GRG
1463
1464 if (address->m_addr == NULL)
1465 {
54e575f9
GL
1466 address->m_error = GSOCK_MEMERR;
1467 return GSOCK_MEMERR;
1468 }
a324a7bc 1469 memcpy(address->m_addr, addr, len);
e00f35bb 1470
54e575f9 1471 return GSOCK_NOERROR;
a324a7bc
GL
1472}
1473
54e575f9
GL
1474GSocketError _GAddress_translate_to(GAddress *address,
1475 struct sockaddr **addr, int *len)
a324a7bc 1476{
9bf10d6b
GRG
1477 if (!address->m_addr)
1478 {
54e575f9
GL
1479 address->m_error = GSOCK_INVADDR;
1480 return GSOCK_INVADDR;
a324a7bc
GL
1481 }
1482
1483 *len = address->m_len;
1484 *addr = (struct sockaddr *)malloc(address->m_len);
032d5581
GRG
1485 if (*addr == NULL)
1486 {
54e575f9
GL
1487 address->m_error = GSOCK_MEMERR;
1488 return GSOCK_MEMERR;
1489 }
e00f35bb 1490
a324a7bc 1491 memcpy(*addr, address->m_addr, address->m_len);
54e575f9 1492 return GSOCK_NOERROR;
a324a7bc
GL
1493}
1494
1495/*
1496 * -------------------------------------------------------------------------
1497 * Internet address family
1498 * -------------------------------------------------------------------------
1499 */
1500
54e575f9 1501GSocketError _GAddress_Init_INET(GAddress *address)
a324a7bc 1502{
f3e60952 1503 address->m_len = sizeof(struct sockaddr_in);
9bf10d6b 1504 address->m_addr = (struct sockaddr *) malloc(address->m_len);
f3e60952
GRG
1505 if (address->m_addr == NULL)
1506 {
54e575f9
GL
1507 address->m_error = GSOCK_MEMERR;
1508 return GSOCK_MEMERR;
1509 }
e00f35bb 1510
a324a7bc
GL
1511 address->m_family = GSOCK_INET;
1512 address->m_realfamily = PF_INET;
1513 ((struct sockaddr_in *)address->m_addr)->sin_family = AF_INET;
9bf10d6b 1514 ((struct sockaddr_in *)address->m_addr)->sin_addr.s_addr = INADDR_ANY;
e00f35bb 1515
cc345f78 1516 return GSOCK_NOERROR;
a324a7bc
GL
1517}
1518
1519GSocketError GAddress_INET_SetHostName(GAddress *address, const char *hostname)
1520{
1521 struct hostent *he;
1522 struct in_addr *addr;
1523
1524 assert(address != NULL);
1525
032d5581 1526 CHECK_ADDRESS(address, INET);
a324a7bc
GL
1527
1528 addr = &(((struct sockaddr_in *)address->m_addr)->sin_addr);
1529
f61815af 1530 /* If it is a numeric host name, convert it now */
d5b08e7b 1531#if defined(HAVE_INET_ATON)
f3e60952
GRG
1532 if (inet_aton(hostname, addr) == 0)
1533 {
d5b08e7b 1534#elif defined(HAVE_INET_ADDR)
f3e60952
GRG
1535 if ( (addr->s_addr = inet_addr(hostname)) == -1 )
1536 {
e96ac54e
GL
1537#else
1538 /* Use gethostbyname by default */
f3e60952
GRG
1539 if (1)
1540 {
e96ac54e 1541#endif
a324a7bc
GL
1542 struct in_addr *array_addr;
1543
f61815af 1544 /* It is a real name, we solve it */
f3e60952
GRG
1545 if ((he = gethostbyname(hostname)) == NULL)
1546 {
9bf10d6b
GRG
1547 /* Reset to invalid address */
1548 addr->s_addr = INADDR_NONE;
a324a7bc
GL
1549 address->m_error = GSOCK_NOHOST;
1550 return GSOCK_NOHOST;
1551 }
1552 array_addr = (struct in_addr *) *(he->h_addr_list);
1553 addr->s_addr = array_addr[0].s_addr;
1554 }
1555 return GSOCK_NOERROR;
1556}
1557
9bf10d6b
GRG
1558GSocketError GAddress_INET_SetAnyAddress(GAddress *address)
1559{
1560 return GAddress_INET_SetHostAddress(address, INADDR_ANY);
1561}
1562
a324a7bc
GL
1563GSocketError GAddress_INET_SetHostAddress(GAddress *address,
1564 unsigned long hostaddr)
1565{
1566 struct in_addr *addr;
1567
1568 assert(address != NULL);
1569
032d5581 1570 CHECK_ADDRESS(address, INET);
a324a7bc
GL
1571
1572 addr = &(((struct sockaddr_in *)address->m_addr)->sin_addr);
1573 addr->s_addr = hostaddr;
1574
1575 return GSOCK_NOERROR;
1576}
1577
5a96d2f4
GL
1578GSocketError GAddress_INET_SetPortName(GAddress *address, const char *port,
1579 const char *protocol)
a324a7bc
GL
1580{
1581 struct servent *se;
1582 struct sockaddr_in *addr;
1583
1584 assert(address != NULL);
032d5581 1585 CHECK_ADDRESS(address, INET);
a324a7bc 1586
f3e60952
GRG
1587 if (!port)
1588 {
a324a7bc 1589 address->m_error = GSOCK_INVPORT;
54e575f9 1590 return GSOCK_INVPORT;
a324a7bc
GL
1591 }
1592
5a96d2f4 1593 se = getservbyname(port, protocol);
9bf10d6b
GRG
1594 if (!se)
1595 {
72c71d39
VZ
1596 /* the cast to int suppresses compiler warnings about subscript having the
1597 type char */
1598 if (isdigit((int)port[0]))
f3e60952 1599 {
a324a7bc
GL
1600 int port_int;
1601
1602 port_int = atoi(port);
1603 addr = (struct sockaddr_in *)address->m_addr;
1604 addr->sin_port = htons(port_int);
1605 return GSOCK_NOERROR;
1606 }
1607
1608 address->m_error = GSOCK_INVPORT;
1609 return GSOCK_INVPORT;
1610 }
1611
1612 addr = (struct sockaddr_in *)address->m_addr;
1613 addr->sin_port = se->s_port;
1614
1615 return GSOCK_NOERROR;
1616}
1617
1618GSocketError GAddress_INET_SetPort(GAddress *address, unsigned short port)
1619{
1620 struct sockaddr_in *addr;
1621
1622 assert(address != NULL);
032d5581 1623 CHECK_ADDRESS(address, INET);
a324a7bc
GL
1624
1625 addr = (struct sockaddr_in *)address->m_addr;
1626 addr->sin_port = htons(port);
1627
1628 return GSOCK_NOERROR;
1629}
1630
1631GSocketError GAddress_INET_GetHostName(GAddress *address, char *hostname, size_t sbuf)
1632{
1633 struct hostent *he;
1634 char *addr_buf;
1635 struct sockaddr_in *addr;
1636
1637 assert(address != NULL);
032d5581 1638 CHECK_ADDRESS(address, INET);
a324a7bc
GL
1639
1640 addr = (struct sockaddr_in *)address->m_addr;
1641 addr_buf = (char *)&(addr->sin_addr);
1642
f3e60952
GRG
1643 he = gethostbyaddr(addr_buf, sizeof(addr->sin_addr), AF_INET);
1644 if (he == NULL)
1645 {
a324a7bc
GL
1646 address->m_error = GSOCK_NOHOST;
1647 return GSOCK_NOHOST;
1648 }
1649
1650 strncpy(hostname, he->h_name, sbuf);
1651
1652 return GSOCK_NOERROR;
1653}
1654
1655unsigned long GAddress_INET_GetHostAddress(GAddress *address)
1656{
1657 struct sockaddr_in *addr;
1658
1659 assert(address != NULL);
032d5581 1660 CHECK_ADDRESS_RETVAL(address, INET, 0);
a324a7bc
GL
1661
1662 addr = (struct sockaddr_in *)address->m_addr;
1663
1664 return addr->sin_addr.s_addr;
1665}
1666
1667unsigned short GAddress_INET_GetPort(GAddress *address)
1668{
1669 struct sockaddr_in *addr;
1670
1671 assert(address != NULL);
032d5581 1672 CHECK_ADDRESS_RETVAL(address, INET, 0);
a324a7bc
GL
1673
1674 addr = (struct sockaddr_in *)address->m_addr;
1675 return ntohs(addr->sin_port);
1676}
1677
1678/*
1679 * -------------------------------------------------------------------------
1680 * Unix address family
1681 * -------------------------------------------------------------------------
1682 */
1683
54e575f9 1684GSocketError _GAddress_Init_UNIX(GAddress *address)
a324a7bc 1685{
f3e60952 1686 address->m_len = sizeof(struct sockaddr_un);
a324a7bc 1687 address->m_addr = (struct sockaddr *)malloc(address->m_len);
f3e60952
GRG
1688 if (address->m_addr == NULL)
1689 {
54e575f9
GL
1690 address->m_error = GSOCK_MEMERR;
1691 return GSOCK_MEMERR;
1692 }
e00f35bb 1693
a324a7bc
GL
1694 address->m_family = GSOCK_UNIX;
1695 address->m_realfamily = PF_UNIX;
1696 ((struct sockaddr_un *)address->m_addr)->sun_family = AF_UNIX;
1697 ((struct sockaddr_un *)address->m_addr)->sun_path[0] = 0;
e00f35bb 1698
032d5581 1699 return GSOCK_NOERROR;
a324a7bc
GL
1700}
1701
70914290
VZ
1702#define UNIX_SOCK_PATHLEN (sizeof(addr->sun_path)/sizeof(addr->sun_path[0]))
1703
a324a7bc
GL
1704GSocketError GAddress_UNIX_SetPath(GAddress *address, const char *path)
1705{
1706 struct sockaddr_un *addr;
1707
1708 assert(address != NULL);
1709
032d5581 1710 CHECK_ADDRESS(address, UNIX);
a324a7bc
GL
1711
1712 addr = ((struct sockaddr_un *)address->m_addr);
70914290
VZ
1713 strncpy(addr->sun_path, path, UNIX_SOCK_PATHLEN);
1714 addr->sun_path[UNIX_SOCK_PATHLEN - 1] = '\0';
a324a7bc
GL
1715
1716 return GSOCK_NOERROR;
1717}
1718
1719GSocketError GAddress_UNIX_GetPath(GAddress *address, char *path, size_t sbuf)
1720{
1721 struct sockaddr_un *addr;
1722
1723 assert(address != NULL);
032d5581 1724 CHECK_ADDRESS(address, UNIX);
a324a7bc
GL
1725
1726 addr = (struct sockaddr_un *)address->m_addr;
1727
1728 strncpy(path, addr->sun_path, sbuf);
1729
1730 return GSOCK_NOERROR;
1731}
813c20a6 1732
9bf10d6b 1733#endif /* wxUSE_SOCKETS || defined(__GSOCKET_STANDALONE__) */
85806dc2 1734