]> git.saurik.com Git - wxWidgets.git/blame - src/unix/gsocket.c
Cured some bugs/typos/spacing in docs
[wxWidgets.git] / src / unix / gsocket.c
CommitLineData
a324a7bc
GL
1/* -------------------------------------------------------------------------
2 * Project: GSocket (Generic Socket) for WX
3 * Name: gsocket.c
4 * Purpose: GSocket main Unix file
5 * CVSID: $Id$
a324a7bc
GL
6 * -------------------------------------------------------------------------
7 */
8
813c20a6
VZ
9#include "wx/setup.h"
10
11#if wxUSE_SOCKETS
12
a324a7bc
GL
13#include <assert.h>
14#include <sys/ioctl.h>
efee48a0 15#include <sys/types.h>
a324a7bc
GL
16#ifdef vms
17#include <socket.h>
18#else
19#include <sys/socket.h>
20#endif
21#include <sys/un.h>
a324a7bc
GL
22#include <sys/time.h>
23#include <netinet/in.h>
24#include <arpa/inet.h>
25#include <netdb.h>
9592b687 26#include <errno.h>
a324a7bc
GL
27
28#include <string.h>
29#include <unistd.h>
30#include <stdio.h>
31#include <stdlib.h>
552e8bf8 32#include <stddef.h>
9b61f868 33#include <ctype.h>
a324a7bc
GL
34
35#ifdef sun
f61815af 36# include <sys/filio.h>
a324a7bc
GL
37#endif
38
39#ifdef sgi
f61815af 40# include <bstring.h>
a324a7bc
GL
41#endif
42
43#include <signal.h>
5a96d2f4 44
ca17eff3 45#include "wx/gsocket.h"
a324a7bc
GL
46#include "gsockunx.h"
47
efee48a0 48#ifndef SOCKLEN_T
5a96d2f4
GL
49
50#ifdef __GLIBC__
51# if __GLIBC__ == 2
52# define SOCKLEN_T socklen_t
53# endif
54#else
55# define SOCKLEN_T int
56#endif
57
efee48a0
KB
58#endif
59
54e575f9
GL
60#if !defined(__LINUX__) && !defined(__FREEBSD__)
61# define CAN_USE_TIMEOUT
62#elif defined(__GLIBC__) && defined(__GLIBC_MINOR__)
63# if (__GLIBC__ == 2) && (__GLIBC_MINOR__ == 1)
64# define CAN_USE_TIMEOUT
65# endif
66#endif
67
a58d5df4
GL
68/* Global initialisers */
69
31989b0b 70bool GSocket_Init()
a58d5df4 71{
31989b0b 72 return TRUE;
a58d5df4
GL
73}
74
75void GSocket_Cleanup()
76{
77}
78
a324a7bc
GL
79/* Constructors / Destructors */
80
81GSocket *GSocket_new()
82{
83 int i;
84 GSocket *socket;
85
86 socket = (GSocket *)malloc(sizeof(GSocket));
87
e00f35bb
GL
88 if (socket == NULL)
89 return NULL;
90
a324a7bc
GL
91 socket->m_fd = -1;
92 for (i=0;i<GSOCK_MAX_EVENT;i++) {
93 socket->m_fbacks[i] = NULL;
94 socket->m_iocalls[i] = FALSE;
95 }
96 socket->m_local = NULL;
97 socket->m_peer = NULL;
98 socket->m_error = GSOCK_NOERROR;
99 socket->m_server = FALSE;
100 socket->m_stream = TRUE;
101 socket->m_gui_dependent = NULL;
102 socket->m_blocking = FALSE;
39b91eca
GL
103 socket->m_timeout = 10*60*1000;
104 // 10 minutes * 60 sec * 1000 millisec
a324a7bc 105
31989b0b 106 /* We initialize the GUI specific entries here */
a324a7bc
GL
107 _GSocket_GUI_Init(socket);
108
109 return socket;
110}
111
112void GSocket_destroy(GSocket *socket)
113{
114 assert(socket != NULL);
115
31989b0b 116 /* First, we check that the socket is really shutdowned */
a324a7bc
GL
117 if (socket->m_fd != -1)
118 GSocket_Shutdown(socket);
119
31989b0b 120 /* We destroy GUI specific variables */
dbd300df
GL
121 _GSocket_GUI_Destroy(socket);
122
31989b0b 123 /* We destroy private addresses */
a324a7bc
GL
124 if (socket->m_local)
125 GAddress_destroy(socket->m_local);
126
127 if (socket->m_peer)
128 GAddress_destroy(socket->m_peer);
129
31989b0b 130 /* We destroy socket itself */
a324a7bc
GL
131 free(socket);
132}
133
134void GSocket_Shutdown(GSocket *socket)
135{
136 int evt;
137
138 assert(socket != NULL);
139
31989b0b 140 /* If socket has been created, we shutdown it */
a324a7bc
GL
141 if (socket->m_fd != -1) {
142 shutdown(socket->m_fd, 2);
143 close(socket->m_fd);
144 socket->m_fd = -1;
145 }
146
31989b0b 147 /* We also disable GUI callbacks */
a324a7bc 148 for (evt=0;evt<GSOCK_MAX_EVENT;evt++)
39b91eca 149 _GSocket_Uninstall_Callback(socket, evt);
a324a7bc
GL
150}
151
152/* Address handling */
153
154GSocketError GSocket_SetLocal(GSocket *socket, GAddress *address)
155{
5a96d2f4
GL
156 assert(socket != NULL);
157
31989b0b
GL
158 if ((socket->m_fd != -1 && !socket->m_server)) {
159 socket->m_error = GSOCK_INVSOCK;
a324a7bc 160 return GSOCK_INVSOCK;
31989b0b 161 }
a324a7bc 162
31989b0b
GL
163 if (address == NULL || address->m_family == GSOCK_NOFAMILY) {
164 socket->m_error = GSOCK_INVADDR;
a324a7bc 165 return GSOCK_INVADDR;
31989b0b 166 }
a324a7bc
GL
167
168 if (socket->m_local)
169 GAddress_destroy(socket->m_local);
170
171 socket->m_local = GAddress_copy(address);
172
173 return GSOCK_NOERROR;
174}
175
176GSocketError GSocket_SetPeer(GSocket *socket, GAddress *address)
177{
5a96d2f4 178 assert(socket != NULL);
a324a7bc
GL
179
180 if (address == NULL || address->m_family == GSOCK_NOFAMILY) {
181 socket->m_error = GSOCK_INVADDR;
182 return GSOCK_INVADDR;
183 }
184
185 if (socket->m_peer)
186 GAddress_destroy(socket->m_peer);
187
188 socket->m_peer = GAddress_copy(address);
189
190 return GSOCK_NOERROR;
191}
192
193GAddress *GSocket_GetLocal(GSocket *socket)
194{
195 GAddress *address;
196 struct sockaddr addr;
efee48a0 197 SOCKLEN_T size;
a324a7bc
GL
198
199 assert(socket != NULL);
200
201 if (socket->m_local)
202 return GAddress_copy(socket->m_local);
203
204 if (socket->m_fd == -1) {
205 socket->m_error = GSOCK_INVSOCK;
206 return NULL;
207 }
208
209 size = sizeof(addr);
210
211 if (getsockname(socket->m_fd, &addr, &size) < 0) {
212 socket->m_error = GSOCK_IOERR;
213 return NULL;
214 }
215
216 address = GAddress_new();
e00f35bb
GL
217 if (address == NULL) {
218 socket->m_error = GSOCK_MEMERR;
219 return NULL;
220 }
54e575f9 221 if (_GAddress_translate_from(address, &addr, size) != GSOCK_NOERROR) {
e00f35bb
GL
222 GAddress_destroy(address);
223 return NULL;
224 }
a324a7bc
GL
225
226 return address;
227}
228
229GAddress *GSocket_GetPeer(GSocket *socket)
230{
231 assert(socket != NULL);
232
233 if (socket->m_peer)
234 return GAddress_copy(socket->m_peer);
235
236 return NULL;
237}
238
239/* Server specific parts */
240
241/*
242 GSocket_SetServer() setup the socket as a server. It uses the "Local" field
243 of GSocket. "Local" must be set by GSocket_SetLocal() before
244 GSocket_SetServer() is called. GSOCK_INVSOCK if socket has been initialized.
5a96d2f4
GL
245 In case, you haven't yet defined the local address, it returns GSOCK_INVADDR.
246 In the other cases it returns GSOCK_IOERR.
a324a7bc
GL
247*/
248GSocketError GSocket_SetServer(GSocket *sck)
249{
250 int type;
251
252 assert(sck != NULL);
253
254 if (sck->m_fd != -1) {
255 sck->m_error = GSOCK_INVSOCK;
256 return GSOCK_INVSOCK;
257 }
258
259 if (!sck->m_local) {
260 sck->m_error = GSOCK_INVADDR;
261 return GSOCK_INVADDR;
262 }
263
f61815af
GL
264 /* We always have a stream here */
265 sck->m_stream = TRUE;
a324a7bc 266
f61815af
GL
267 /* Create the socket */
268 sck->m_fd = socket(sck->m_local->m_realfamily, SOCK_STREAM, 0);
a324a7bc
GL
269
270 if (sck->m_fd == -1) {
271 sck->m_error = GSOCK_IOERR;
272 return GSOCK_IOERR;
273 }
274
f61815af 275 /* Bind the socket to the LOCAL address */
a324a7bc
GL
276 if (bind(sck->m_fd, sck->m_local->m_addr, sck->m_local->m_len) < 0) {
277 close(sck->m_fd);
278 sck->m_fd = -1;
279 sck->m_error = GSOCK_IOERR;
280 return GSOCK_IOERR;
281 }
282
f61815af 283 /* Enable listening up to 5 connections */
a324a7bc
GL
284 if (listen(sck->m_fd, 5) < 0) {
285 close(sck->m_fd);
286 sck->m_fd = -1;
287 sck->m_error = GSOCK_IOERR;
288 return GSOCK_IOERR;
289 }
290
39b91eca
GL
291 GSocket_SetNonBlocking(sck, sck->m_blocking);
292 GSocket_SetTimeout(sck, sck->m_timeout);
293
a324a7bc 294 return GSOCK_NOERROR;
a324a7bc
GL
295}
296
297/*
298 GSocket_WaitConnection() waits for an incoming client connection.
299*/
300GSocket *GSocket_WaitConnection(GSocket *socket)
301{
302 GSocket *connection;
303
304 assert(socket != NULL);
305
f61815af 306 /* If the socket has already been created, we exit immediately */
a324a7bc
GL
307 if (socket->m_fd == -1 || !socket->m_server) {
308 socket->m_error = GSOCK_INVSOCK;
309 return NULL;
310 }
311
f61815af 312 /* Reenable GSOCK_CONNECTION event */
a324a7bc
GL
313 _GSocket_Enable(socket, GSOCK_CONNECTION);
314
f61815af 315 /* Create a GSocket object for the new connection */
a324a7bc
GL
316 connection = GSocket_new();
317
f61815af 318 /* Accept the incoming connection */
a324a7bc
GL
319 connection->m_fd = accept(socket->m_fd, NULL, NULL);
320 if (connection->m_fd == -1) {
321 GSocket_destroy(connection);
322 socket->m_error = GSOCK_IOERR;
323 return NULL;
324 }
325
f61815af 326 /* Initialize all fields */
a324a7bc
GL
327 connection->m_stream = TRUE;
328 connection->m_server = FALSE;
329 connection->m_oriented = TRUE;
330
331 return connection;
332}
333
334/* Non oriented connections */
335
336GSocketError GSocket_SetNonOriented(GSocket *sck)
337{
338 assert(sck != NULL);
339
340 if (sck->m_fd != -1) {
341 sck->m_error = GSOCK_INVSOCK;
342 return GSOCK_INVSOCK;
343 }
344
345 if (!sck->m_local) {
346 sck->m_error = GSOCK_INVADDR;
347 return GSOCK_INVADDR;
348 }
349
350 sck->m_stream = FALSE;
351 sck->m_server = FALSE;
352 sck->m_oriented = FALSE;
353
f61815af 354 /* Create the socket */
a324a7bc
GL
355 sck->m_fd = socket(sck->m_local->m_realfamily, SOCK_DGRAM, 0);
356
f61815af 357 /* Bind it to the LOCAL address */
a324a7bc
GL
358 if (bind(sck->m_fd, sck->m_local->m_addr, sck->m_local->m_len) < 0) {
359 close(sck->m_fd);
360 sck->m_fd = -1;
361 sck->m_error = GSOCK_IOERR;
362 return GSOCK_IOERR;
363 }
364
9592b687 365 GSocket_SetNonBlocking(sck, sck->m_blocking);
39b91eca
GL
366 GSocket_SetTimeout(sck, sck->m_timeout);
367
a324a7bc
GL
368 return GSOCK_NOERROR;
369}
370
371/* Client specific parts */
372
373/*
374 GSocket_Connect() establishes a client connection to a server using the "Peer"
375 field of GSocket. "Peer" must be set by GSocket_SetPeer() before
376 GSocket_Connect() is called. In the other case, it returns GSOCK_INVADDR.
377*/
378GSocketError GSocket_Connect(GSocket *sck, GSocketStream stream)
379{
380 int type;
381
382 assert(sck != NULL);
383
384 if (sck->m_fd != -1) {
385 sck->m_error = GSOCK_INVSOCK;
386 return GSOCK_INVSOCK;
387 }
388
389 if (!sck->m_peer) {
390 sck->m_error = GSOCK_INVADDR;
391 return GSOCK_INVADDR;
392 }
393
f61815af 394 /* Test whether we want the socket to be a stream (e.g. TCP) */
a324a7bc
GL
395 sck->m_stream = (stream == GSOCK_STREAMED);
396 sck->m_oriented = TRUE;
397
398 if (sck->m_stream)
399 type = SOCK_STREAM;
400 else
401 type = SOCK_DGRAM;
402
f61815af 403 /* Create the socket */
a324a7bc
GL
404 sck->m_fd = socket(sck->m_peer->m_realfamily, type, 0);
405
406 if (sck->m_fd == -1) {
407 sck->m_error = GSOCK_IOERR;
408 return GSOCK_IOERR;
409 }
410
f61815af 411 /* Connect it to the PEER address */
a324a7bc
GL
412 if (connect(sck->m_fd, sck->m_peer->m_addr,
413 sck->m_peer->m_len) != 0) {
414 close(sck->m_fd);
415 sck->m_fd = -1;
416 sck->m_error = GSOCK_IOERR;
417 return GSOCK_IOERR;
418 }
419
f61815af 420 /* It is not a server */
a324a7bc
GL
421 sck->m_server = FALSE;
422
9592b687 423 GSocket_SetNonBlocking(sck, sck->m_blocking);
39b91eca
GL
424 GSocket_SetTimeout(sck, sck->m_timeout);
425
a324a7bc
GL
426 return GSOCK_NOERROR;
427}
428
429/* Generic IO */
430
431/* Like recv(), send(), ... */
432int GSocket_Read(GSocket *socket, char *buffer, int size)
433{
434 assert(socket != NULL);
435
436 if (socket->m_fd == -1 || socket->m_server) {
437 socket->m_error = GSOCK_INVSOCK;
438 return -1;
439 }
440
f61815af 441 /* Reenable GSOCK_INPUT event */
a324a7bc
GL
442 _GSocket_Enable(socket, GSOCK_INPUT);
443
f61815af 444 if (socket->m_stream)
a324a7bc
GL
445 return _GSocket_Recv_Stream(socket, buffer, size);
446 else
447 return _GSocket_Recv_Dgram(socket, buffer, size);
448}
449
450int GSocket_Write(GSocket *socket, const char *buffer,
451 int size)
452{
453 assert(socket != NULL);
454
455 if (socket->m_fd == -1 || socket->m_server) {
456 socket->m_error = GSOCK_INVSOCK;
457 return -1;
458 }
459
460 _GSocket_Enable(socket, GSOCK_OUTPUT);
461
f61815af 462 if (socket->m_stream)
a324a7bc
GL
463 return _GSocket_Send_Stream(socket, buffer, size);
464 else
465 return _GSocket_Send_Dgram(socket, buffer, size);
466}
467
468bool GSocket_DataAvailable(GSocket *socket)
469{
470 fd_set read_set;
471 struct timeval tv;
472
473 assert(socket != NULL);
474
475 if (socket->m_fd == -1 || socket->m_server) {
476 socket->m_error = GSOCK_INVSOCK;
477 return FALSE;
478 }
479
480 FD_ZERO(&read_set);
481 FD_SET(socket->m_fd, &read_set);
482
483 tv.tv_sec = 0;
484 tv.tv_usec = 0;
485
486 select(socket->m_fd+1, &read_set, NULL, NULL, &tv);
487
488 return FD_ISSET(socket->m_fd, &read_set);
489}
490
491/* Flags */
492
493/*
39b91eca 494 GSocket_SetNonBlocking() puts the socket in non-blocking mode. This is useful
a324a7bc
GL
495 if we don't want to wait.
496*/
54e575f9 497void GSocket_SetNonBlocking(GSocket *socket, bool non_block)
a324a7bc
GL
498{
499 assert(socket != NULL);
500
54e575f9 501 socket->m_blocking = non_block;
a324a7bc
GL
502
503 if (socket->m_fd != -1)
54e575f9 504 ioctl(socket->m_fd, FIONBIO, &non_block);
a324a7bc
GL
505}
506
39b91eca
GL
507/*
508 * GSocket_SetTimeout()
509 */
e00f35bb 510
39b91eca
GL
511void GSocket_SetTimeout(GSocket *socket, unsigned long millisec)
512{
513 assert(socket != NULL);
514
54e575f9 515 socket->m_timeout = millisec;
e00f35bb
GL
516 /* Neither GLIBC 2.0 nor the kernel 2.0.36 define SO_SNDTIMEO or
517 SO_RCVTIMEO. The man pages, that these flags should exist but
518 are read only. RR. */
519 /* OK, restrict this to GLIBC 2.1. GL. */
520#ifdef CAN_USE_TIMEOUT
39b91eca
GL
521 if (socket->m_fd != -1) {
522 struct timeval tval;
523
524 tval.tv_sec = millisec / 1000;
525 tval.tv_usec = (millisec % 1000) * 1000;
526 setsockopt(socket->m_fd, SOL_SOCKET, SO_SNDTIMEO, &tval, sizeof(tval));
527 setsockopt(socket->m_fd, SOL_SOCKET, SO_RCVTIMEO, &tval, sizeof(tval));
528 }
23a54e14 529#endif
39b91eca
GL
530}
531
a324a7bc
GL
532/*
533 GSocket_GetError() returns the last error occured on the socket stream.
534*/
535
536GSocketError GSocket_GetError(GSocket *socket)
537{
538 assert(socket != NULL);
539
540 return socket->m_error;
541}
542
543/* Callbacks */
544
545/*
546 Only one fallback is possible for each event (INPUT, OUTPUT, CONNECTION)
547 INPUT: The function is called when there is at least a byte in the
548 input buffer
549 OUTPUT: The function is called when the system is sure the next write call
550 will not block
551 CONNECTION: Two cases is possible:
552 Client socket -> the connection is established
553 Server socket -> a client request a connection
554 LOST: the connection is lost
555
39b91eca 556 SetCallback accepts a combination of these flags so a same callback can
a324a7bc
GL
557 receive different events.
558
559 An event is generated only once and its state is reseted when the relative
560 IO call is requested.
561 For example: INPUT -> GSocket_Read()
562 CONNECTION -> GSocket_Accept()
563*/
39b91eca
GL
564void GSocket_SetCallback(GSocket *socket, GSocketEventFlags event,
565 GSocketCallback fallback, char *cdata)
a324a7bc
GL
566{
567 int count;
568
569 assert (socket != NULL);
570
571 for (count=0;count<GSOCK_MAX_EVENT;count++) {
f61815af
GL
572 /* We test each flag and, if it is enabled, we enable the corresponding
573 event */
a324a7bc
GL
574 if ((event & (1 << count)) != 0) {
575 socket->m_fbacks[count] = fallback;
576 socket->m_data[count] = cdata;
a324a7bc
GL
577 _GSocket_Enable(socket, count);
578 }
579 }
580}
581
582/*
39b91eca 583 UnsetCallback will disables all fallbacks specified by "event".
a324a7bc
GL
584 NOTE: event may be a combination of flags
585*/
39b91eca 586void GSocket_UnsetCallback(GSocket *socket, GSocketEventFlags event)
a324a7bc
GL
587{
588 int count = 0;
589
590 assert(socket != NULL);
591
592 for (count=0;count<GSOCK_MAX_EVENT;count++) {
593 if ((event & (1 << count)) != 0) {
594 _GSocket_Disable(socket, count);
595 socket->m_fbacks[count] = NULL;
a324a7bc
GL
596 }
597 }
598}
599
600#define CALL_FALLBACK(socket, event) \
601if (socket->m_iocalls[event] && \
602 socket->m_fbacks[event]) {\
603 _GSocket_Disable(socket, event); \
604 socket->m_fbacks[event](socket, event, \
605 socket->m_data[event]); \
606}
607
608#define MASK_SIGNAL() \
609{ \
610 void (*old_handler)(int); \
611\
612 old_handler = signal(SIGPIPE, SIG_IGN);
613
614#define UNMASK_SIGNAL() \
615 signal(SIGPIPE, old_handler); \
616}
617
54e575f9
GL
618#if 0
619#ifndef CAN_USE_TIMEOUT
620
621#define ENABLE_TIMEOUT(socket) \
622{ \
623 struct itimerval old_ival, new_ival; \
624 void (*old_timer_sig)(int); \
625\
626 new_ival.it_interval.tv_sec = socket->m_timeout / 1000; \
627 new_ival.it_interval.tv_usec = (socket->m_timeout % 1000) * 1000; \
628 setitimer(ITIMER_REAL, &new_ival, &old_ival); \
60b6c062 629 old_timer_sig = signal(SIGALRM, SIG_DFL);
54e575f9
GL
630
631#define DISABLE_TIMEOUT(socket) \
632 signal(SIGALRM, old_timer_sig); \
633 setitimer(ITIMER_REAL, &old_ival, NULL); \
634}
635
636#else
637
638#define ENABLE_TIMEOUT(s)
639#define DISABLE_TIMEOUT(s)
640
641#endif
642
643#endif
644
645/* Temporary */
646#define ENABLE_TIMEOUT(s)
647#define DISABLE_TIMEOUT(s)
648
a324a7bc
GL
649void _GSocket_Enable(GSocket *socket, GSocketEvent event)
650{
651 socket->m_iocalls[event] = TRUE;
652 if (socket->m_fbacks[event])
39b91eca 653 _GSocket_Install_Callback(socket, event);
a324a7bc
GL
654}
655
656void _GSocket_Disable(GSocket *socket, GSocketEvent event)
657{
658 socket->m_iocalls[event] = FALSE;
659 if (socket->m_fbacks[event])
39b91eca 660 _GSocket_Uninstall_Callback(socket, event);
a324a7bc
GL
661}
662
663int _GSocket_Recv_Stream(GSocket *socket, char *buffer, int size)
664{
665 int ret;
666
667 MASK_SIGNAL();
54e575f9 668 ENABLE_TIMEOUT(socket);
a324a7bc 669 ret = recv(socket->m_fd, buffer, size, 0);
54e575f9 670 DISABLE_TIMEOUT(socket);
a324a7bc 671 UNMASK_SIGNAL();
54e575f9 672
9592b687 673 if (ret == -1 && errno != EAGAIN) {
a324a7bc
GL
674 socket->m_error = GSOCK_IOERR;
675 return -1;
676 }
9592b687
GL
677 if (errno == EAGAIN) {
678 socket->m_error = GSOCK_TRYAGAIN;
679 return -1;
680 }
a324a7bc
GL
681 return ret;
682}
683
684int _GSocket_Recv_Dgram(GSocket *socket, char *buffer, int size)
685{
686 struct sockaddr from;
ca17eff3
RR
687 SOCKLEN_T fromlen;
688 int ret;
a324a7bc
GL
689
690 fromlen = sizeof(from);
691
692 MASK_SIGNAL();
54e575f9 693 ENABLE_TIMEOUT(socket);
a324a7bc 694 ret = recvfrom(socket->m_fd, buffer, size, 0, &from, &fromlen);
54e575f9 695 DISABLE_TIMEOUT(socket);
a324a7bc 696 UNMASK_SIGNAL();
9592b687 697 if (ret == -1 && errno != EAGAIN) {
a324a7bc
GL
698 socket->m_error = GSOCK_IOERR;
699 return -1;
700 }
9592b687
GL
701 if (errno == EAGAIN) {
702 socket->m_error = GSOCK_TRYAGAIN;
703 return -1;
704 }
a324a7bc 705
f61815af 706 /* Translate a system address into a GSocket address */
e00f35bb 707 if (!socket->m_peer) {
a324a7bc 708 socket->m_peer = GAddress_new();
e00f35bb
GL
709 if (!socket->m_peer) {
710 socket->m_error = GSOCK_MEMERR;
711 return -1;
712 }
713 }
54e575f9 714 if (_GAddress_translate_from(socket->m_peer, &from, fromlen) != GSOCK_NOERROR)
e00f35bb 715 return -1;
a324a7bc
GL
716
717 return ret;
718}
719
720int _GSocket_Send_Stream(GSocket *socket, const char *buffer, int size)
721{
722 int ret;
723
724 MASK_SIGNAL();
54e575f9 725 ENABLE_TIMEOUT(socket);
a324a7bc 726 ret = send(socket->m_fd, buffer, size, 0);
54e575f9 727 DISABLE_TIMEOUT(socket);
a324a7bc 728 UNMASK_SIGNAL();
9592b687 729 if (ret == -1 && errno != EAGAIN) {
a324a7bc
GL
730 socket->m_error = GSOCK_IOERR;
731 return -1;
732 }
9592b687
GL
733 if (errno == EAGAIN) {
734 socket->m_error = GSOCK_TRYAGAIN;
735 return -1;
736 }
a324a7bc
GL
737 return ret;
738}
739
740int _GSocket_Send_Dgram(GSocket *socket, const char *buffer, int size)
741{
742 struct sockaddr *addr;
743 int len, ret;
744
745 if (!socket->m_peer) {
746 socket->m_error = GSOCK_INVADDR;
747 return -1;
748 }
749
54e575f9 750 if (_GAddress_translate_to(socket->m_peer, &addr, &len) != GSOCK_NOERROR) {
e00f35bb
GL
751 return -1;
752 }
a324a7bc
GL
753
754 MASK_SIGNAL();
54e575f9 755 ENABLE_TIMEOUT(socket);
a324a7bc 756 ret = sendto(socket->m_fd, buffer, size, 0, addr, len);
54e575f9 757 DISABLE_TIMEOUT(socket);
a324a7bc 758 UNMASK_SIGNAL();
a324a7bc 759
f61815af 760 /* Frees memory allocated from _GAddress_translate_to */
a324a7bc
GL
761 free(addr);
762
9592b687
GL
763 if (ret == -1 && errno != EAGAIN) {
764 socket->m_error = GSOCK_IOERR;
765 return -1;
766 }
767 if (errno == EAGAIN) {
768 socket->m_error = GSOCK_TRYAGAIN;
769 return -1;
770 }
771
a324a7bc
GL
772 return ret;
773}
774
775void _GSocket_Detected_Read(GSocket *socket)
776{
777 char c;
778 int ret;
779
780 if (socket->m_stream) {
781 ret = recv(socket->m_fd, &c, 1, MSG_PEEK);
782
783 if (ret < 0 && socket->m_server) {
784 CALL_FALLBACK(socket, GSOCK_CONNECTION);
785 return;
786 }
787
788 if (ret > 0) {
789 CALL_FALLBACK(socket, GSOCK_INPUT);
790 } else {
791 CALL_FALLBACK(socket, GSOCK_LOST);
792 }
793 }
794}
795
796void _GSocket_Detected_Write(GSocket *socket)
797{
798 CALL_FALLBACK(socket, GSOCK_OUTPUT);
799}
800
801#undef CALL_FALLBACK
802#undef MASK_SIGNAL
803#undef UNMASK_SIGNAL
804
805/*
806 * -------------------------------------------------------------------------
807 * GAddress
808 * -------------------------------------------------------------------------
809 */
810
f61815af
GL
811/* CHECK_ADDRESS verifies that the current family is either GSOCK_NOFAMILY or
812 * GSOCK_*family*. In case it is GSOCK_NOFAMILY, it initializes address to be
813 * a GSOCK_*family*. In other cases, it returns GSOCK_INVADDR.
814 */
a324a7bc
GL
815#define CHECK_ADDRESS(address, family, retval) \
816{ \
817 if (address->m_family == GSOCK_NOFAMILY) \
54e575f9
GL
818 if (_GAddress_Init_##family(address) != GSOCK_NOERROR) {\
819 return address->m_error; \
e00f35bb 820 }\
a324a7bc
GL
821 if (address->m_family != GSOCK_##family) {\
822 address->m_error = GSOCK_INVADDR; \
823 return retval; \
824 } \
825}
826
827GAddress *GAddress_new()
828{
829 GAddress *address;
830
831 address = (GAddress *)malloc(sizeof(GAddress));
832
e00f35bb
GL
833 if (address == NULL)
834 return NULL;
835
a324a7bc
GL
836 address->m_family = GSOCK_NOFAMILY;
837 address->m_addr = NULL;
838 address->m_len = 0;
839
840 return address;
841}
842
843GAddress *GAddress_copy(GAddress *address)
844{
845 GAddress *addr2;
846
847 assert(address != NULL);
848
849 addr2 = (GAddress *)malloc(sizeof(GAddress));
e00f35bb
GL
850
851 if (addr2 == NULL)
852 return NULL;
853
a324a7bc
GL
854 memcpy(addr2, address, sizeof(GAddress));
855
856 if (address->m_addr) {
857 addr2->m_addr = (struct sockaddr *)malloc(addr2->m_len);
e00f35bb
GL
858 if (addr2->m_addr == NULL) {
859 free(addr2);
860 return NULL;
861 }
a324a7bc
GL
862 memcpy(addr2->m_addr, address->m_addr, addr2->m_len);
863 }
864
865 return addr2;
866}
867
868void GAddress_destroy(GAddress *address)
869{
870 assert(address != NULL);
871
872 free(address);
873}
874
875void GAddress_SetFamily(GAddress *address, GAddressType type)
876{
877 assert(address != NULL);
878
879 address->m_family = type;
880}
881
882GAddressType GAddress_GetFamily(GAddress *address)
883{
884 assert(address != NULL);
885
886 return address->m_family;
887}
888
54e575f9 889GSocketError _GAddress_translate_from(GAddress *address, struct sockaddr *addr, int len){
a324a7bc
GL
890 address->m_realfamily = addr->sa_family;
891 switch (addr->sa_family) {
892 case AF_INET:
893 address->m_family = GSOCK_INET;
894 break;
895 case AF_UNIX:
896 address->m_family = GSOCK_UNIX;
897 break;
efee48a0 898#ifdef AF_INET6
a324a7bc
GL
899 case AF_INET6:
900 address->m_family = GSOCK_INET6;
901 break;
efee48a0 902#endif
a324a7bc 903 default:
ca17eff3 904 {
54e575f9
GL
905 address->m_error = GSOCK_INVOP;
906 return GSOCK_INVOP;
ca17eff3 907 }
a324a7bc
GL
908 }
909
910 if (address->m_addr)
911 free(address->m_addr);
912
913 address->m_len = len;
914 address->m_addr = (struct sockaddr *)malloc(len);
54e575f9
GL
915 if (address->m_addr == NULL) {
916 address->m_error = GSOCK_MEMERR;
917 return GSOCK_MEMERR;
918 }
a324a7bc 919 memcpy(address->m_addr, addr, len);
e00f35bb 920
54e575f9 921 return GSOCK_NOERROR;
a324a7bc
GL
922}
923
54e575f9
GL
924GSocketError _GAddress_translate_to(GAddress *address,
925 struct sockaddr **addr, int *len)
a324a7bc
GL
926{
927 if (!address->m_addr) {
54e575f9
GL
928 address->m_error = GSOCK_INVADDR;
929 return GSOCK_INVADDR;
a324a7bc
GL
930 }
931
932 *len = address->m_len;
933 *addr = (struct sockaddr *)malloc(address->m_len);
54e575f9
GL
934 if (*addr == NULL) {
935 address->m_error = GSOCK_MEMERR;
936 return GSOCK_MEMERR;
937 }
e00f35bb 938
a324a7bc 939 memcpy(*addr, address->m_addr, address->m_len);
54e575f9 940 return GSOCK_NOERROR;
a324a7bc
GL
941}
942
943/*
944 * -------------------------------------------------------------------------
945 * Internet address family
946 * -------------------------------------------------------------------------
947 */
948
54e575f9 949GSocketError _GAddress_Init_INET(GAddress *address)
a324a7bc 950{
e00f35bb 951 address->m_addr = (struct sockaddr *)malloc(sizeof(struct sockaddr_in));
54e575f9
GL
952 if (address->m_addr == NULL) {
953 address->m_error = GSOCK_MEMERR;
954 return GSOCK_MEMERR;
955 }
e00f35bb 956
a324a7bc 957 address->m_len = sizeof(struct sockaddr_in);
e00f35bb 958
a324a7bc
GL
959 address->m_family = GSOCK_INET;
960 address->m_realfamily = PF_INET;
961 ((struct sockaddr_in *)address->m_addr)->sin_family = AF_INET;
962 ((struct sockaddr_in *)address->m_addr)->sin_addr.s_addr = INADDR_ANY;
e00f35bb
GL
963
964 return TRUE;
a324a7bc
GL
965}
966
967GSocketError GAddress_INET_SetHostName(GAddress *address, const char *hostname)
968{
969 struct hostent *he;
970 struct in_addr *addr;
971
972 assert(address != NULL);
973
974 CHECK_ADDRESS(address, INET, GSOCK_INVADDR);
975
976 addr = &(((struct sockaddr_in *)address->m_addr)->sin_addr);
977
f61815af 978 /* If it is a numeric host name, convert it now */
a324a7bc
GL
979 if (inet_aton(hostname, addr) == 0) {
980 struct in_addr *array_addr;
981
f61815af 982 /* It is a real name, we solve it */
a324a7bc
GL
983 if ((he = gethostbyname(hostname)) == NULL) {
984 address->m_error = GSOCK_NOHOST;
985 return GSOCK_NOHOST;
986 }
987 array_addr = (struct in_addr *) *(he->h_addr_list);
988 addr->s_addr = array_addr[0].s_addr;
989 }
990 return GSOCK_NOERROR;
991}
992
993GSocketError GAddress_INET_SetHostAddress(GAddress *address,
994 unsigned long hostaddr)
995{
996 struct in_addr *addr;
997
998 assert(address != NULL);
999
1000 CHECK_ADDRESS(address, INET, GSOCK_INVADDR);
1001
1002 addr = &(((struct sockaddr_in *)address->m_addr)->sin_addr);
1003 addr->s_addr = hostaddr;
1004
1005 return GSOCK_NOERROR;
1006}
1007
5a96d2f4
GL
1008GSocketError GAddress_INET_SetPortName(GAddress *address, const char *port,
1009 const char *protocol)
a324a7bc
GL
1010{
1011 struct servent *se;
1012 struct sockaddr_in *addr;
1013
1014 assert(address != NULL);
1015 CHECK_ADDRESS(address, INET, GSOCK_INVADDR);
1016
1017 if (!port) {
1018 address->m_error = GSOCK_INVPORT;
54e575f9 1019 return GSOCK_INVPORT;
a324a7bc
GL
1020 }
1021
5a96d2f4 1022 se = getservbyname(port, protocol);
a324a7bc
GL
1023 if (!se) {
1024 if (isdigit(port[0])) {
1025 int port_int;
1026
1027 port_int = atoi(port);
1028 addr = (struct sockaddr_in *)address->m_addr;
1029 addr->sin_port = htons(port_int);
1030 return GSOCK_NOERROR;
1031 }
1032
1033 address->m_error = GSOCK_INVPORT;
1034 return GSOCK_INVPORT;
1035 }
1036
1037 addr = (struct sockaddr_in *)address->m_addr;
1038 addr->sin_port = se->s_port;
1039
1040 return GSOCK_NOERROR;
1041}
1042
1043GSocketError GAddress_INET_SetPort(GAddress *address, unsigned short port)
1044{
1045 struct sockaddr_in *addr;
1046
1047 assert(address != NULL);
1048 CHECK_ADDRESS(address, INET, GSOCK_INVADDR);
1049
1050 addr = (struct sockaddr_in *)address->m_addr;
1051 addr->sin_port = htons(port);
1052
1053 return GSOCK_NOERROR;
1054}
1055
1056GSocketError GAddress_INET_GetHostName(GAddress *address, char *hostname, size_t sbuf)
1057{
1058 struct hostent *he;
1059 char *addr_buf;
1060 struct sockaddr_in *addr;
1061
1062 assert(address != NULL);
1063 CHECK_ADDRESS(address, INET, GSOCK_INVADDR);
1064
1065 addr = (struct sockaddr_in *)address->m_addr;
1066 addr_buf = (char *)&(addr->sin_addr);
1067
1068 he = gethostbyaddr(addr_buf, sizeof(addr->sin_addr), AF_INET);
1069 if (he == NULL) {
1070 address->m_error = GSOCK_NOHOST;
1071 return GSOCK_NOHOST;
1072 }
1073
1074 strncpy(hostname, he->h_name, sbuf);
1075
1076 return GSOCK_NOERROR;
1077}
1078
1079unsigned long GAddress_INET_GetHostAddress(GAddress *address)
1080{
1081 struct sockaddr_in *addr;
1082
1083 assert(address != NULL);
1084 CHECK_ADDRESS(address, INET, 0);
1085
1086 addr = (struct sockaddr_in *)address->m_addr;
1087
1088 return addr->sin_addr.s_addr;
1089}
1090
1091unsigned short GAddress_INET_GetPort(GAddress *address)
1092{
1093 struct sockaddr_in *addr;
1094
1095 assert(address != NULL);
1096 CHECK_ADDRESS(address, INET, 0);
1097
1098 addr = (struct sockaddr_in *)address->m_addr;
1099 return ntohs(addr->sin_port);
1100}
1101
1102/*
1103 * -------------------------------------------------------------------------
1104 * Unix address family
1105 * -------------------------------------------------------------------------
1106 */
1107
54e575f9 1108GSocketError _GAddress_Init_UNIX(GAddress *address)
a324a7bc 1109{
a324a7bc 1110 address->m_addr = (struct sockaddr *)malloc(address->m_len);
54e575f9
GL
1111 if (address->m_addr == NULL) {
1112 address->m_error = GSOCK_MEMERR;
1113 return GSOCK_MEMERR;
1114 }
e00f35bb
GL
1115
1116 address->m_len = sizeof(struct sockaddr_un);
a324a7bc
GL
1117 address->m_family = GSOCK_UNIX;
1118 address->m_realfamily = PF_UNIX;
1119 ((struct sockaddr_un *)address->m_addr)->sun_family = AF_UNIX;
1120 ((struct sockaddr_un *)address->m_addr)->sun_path[0] = 0;
e00f35bb
GL
1121
1122 return TRUE;
a324a7bc
GL
1123}
1124
1125GSocketError GAddress_UNIX_SetPath(GAddress *address, const char *path)
1126{
1127 struct sockaddr_un *addr;
1128
1129 assert(address != NULL);
1130
1131 CHECK_ADDRESS(address, UNIX, GSOCK_INVADDR);
1132
1133 addr = ((struct sockaddr_un *)address->m_addr);
1134 memcpy(addr->sun_path, path, strlen(path));
1135
1136 return GSOCK_NOERROR;
1137}
1138
1139GSocketError GAddress_UNIX_GetPath(GAddress *address, char *path, size_t sbuf)
1140{
1141 struct sockaddr_un *addr;
1142
1143 assert(address != NULL);
1144 CHECK_ADDRESS(address, UNIX, GSOCK_INVADDR);
1145
1146 addr = (struct sockaddr_un *)address->m_addr;
1147
1148 strncpy(path, addr->sun_path, sbuf);
1149
1150 return GSOCK_NOERROR;
1151}
813c20a6
VZ
1152
1153#endif // wxUSE_SOCKETS