]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/unix/gsocket.cpp
added functions for setting the columns order in wxListCtrl (modified patch 1828074)
[wxWidgets.git] / src / unix / gsocket.cpp
... / ...
CommitLineData
1/* -------------------------------------------------------------------------
2 * Project: GSocket (Generic Socket) for WX
3 * Name: gsocket.c
4 * Copyright: (c) Guilhem Lavaux
5 * Licence: wxWindows Licence
6 * Authors: David Elliott (C++ conversion, maintainer)
7 * Guilhem Lavaux,
8 * Guillermo Rodriguez Garcia <guille@iies.es>
9 * Purpose: GSocket main Unix and OS/2 file
10 * Licence: The wxWindows licence
11 * CVSID: $Id$
12 * -------------------------------------------------------------------------
13 */
14
15#if defined(__WATCOMC__)
16#include "wx/wxprec.h"
17#include <errno.h>
18#include <nerrno.h>
19#endif
20
21#ifndef __GSOCKET_STANDALONE__
22#include "wx/defs.h"
23#include "wx/private/gsocketiohandler.h"
24#endif
25
26#if defined(__VISAGECPP__)
27#define BSD_SELECT /* use Berkeley Sockets select */
28#endif
29
30#if wxUSE_SOCKETS || defined(__GSOCKET_STANDALONE__)
31
32#include <assert.h>
33#include <sys/types.h>
34#ifdef __VISAGECPP__
35#include <string.h>
36#include <sys/time.h>
37#include <types.h>
38#include <netinet/in.h>
39#endif
40#include <netdb.h>
41#include <sys/ioctl.h>
42
43#ifdef HAVE_SYS_SELECT_H
44# include <sys/select.h>
45#endif
46
47#ifdef __VMS__
48#include <socket.h>
49struct sockaddr_un
50{
51 u_char sun_len; /* sockaddr len including null */
52 u_char sun_family; /* AF_UNIX */
53 char sun_path[108]; /* path name (gag) */
54};
55#else
56#include <sys/socket.h>
57#include <sys/un.h>
58#endif
59
60#ifndef __VISAGECPP__
61#include <sys/time.h>
62#include <netinet/in.h>
63#include <arpa/inet.h>
64#include <errno.h>
65#include <string.h>
66#include <unistd.h>
67#else
68#include <nerrno.h>
69# if __IBMCPP__ < 400
70#include <machine/endian.h>
71#include <socket.h>
72#include <ioctl.h>
73#include <select.h>
74#include <unistd.h>
75
76#define EBADF SOCEBADF
77
78# ifdef min
79# undef min
80# endif
81# else
82#include <sys/socket.h>
83#include <sys/ioctl.h>
84#include <sys/select.h>
85
86#define close(a) soclose(a)
87#define select(a,b,c,d,e) bsdselect(a,b,c,d,e)
88int _System bsdselect(int,
89 struct fd_set *,
90 struct fd_set *,
91 struct fd_set *,
92 struct timeval *);
93int _System soclose(int);
94# endif
95#endif
96#ifdef __EMX__
97#include <sys/select.h>
98#endif
99
100#include <stdio.h>
101#include <stdlib.h>
102#include <stddef.h>
103#include <ctype.h>
104#ifdef sun
105# include <sys/filio.h>
106#endif
107#ifdef sgi
108# include <bstring.h>
109#endif
110#ifdef _AIX
111# include <strings.h>
112#endif
113#include <signal.h>
114
115#ifndef WX_SOCKLEN_T
116
117#ifdef VMS
118# define WX_SOCKLEN_T unsigned int
119#else
120# ifdef __GLIBC__
121# if __GLIBC__ == 2
122# define WX_SOCKLEN_T socklen_t
123# endif
124# elif defined(__WXMAC__)
125# define WX_SOCKLEN_T socklen_t
126# else
127# define WX_SOCKLEN_T int
128# endif
129#endif
130
131#endif /* SOCKLEN_T */
132
133#ifndef SOCKOPTLEN_T
134#define SOCKOPTLEN_T WX_SOCKLEN_T
135#endif
136
137/*
138 * MSW defines this, Unices don't.
139 */
140#ifndef INVALID_SOCKET
141#define INVALID_SOCKET -1
142#endif
143
144/* UnixWare reportedly needs this for FIONBIO definition */
145#ifdef __UNIXWARE__
146#include <sys/filio.h>
147#endif
148
149/*
150 * INADDR_BROADCAST is identical to INADDR_NONE which is not defined
151 * on all systems. INADDR_BROADCAST should be fine to indicate an error.
152 */
153#ifndef INADDR_NONE
154#define INADDR_NONE INADDR_BROADCAST
155#endif
156
157#if defined(__VISAGECPP__) || defined(__WATCOMC__)
158
159 #define MASK_SIGNAL() {
160 #define UNMASK_SIGNAL() }
161
162#else
163 extern "C" { typedef void (*wxSigHandler)(int); }
164
165 #define MASK_SIGNAL() \
166 { \
167 wxSigHandler old_handler = signal(SIGPIPE, SIG_IGN);
168
169 #define UNMASK_SIGNAL() \
170 signal(SIGPIPE, old_handler); \
171 }
172
173#endif
174
175/* If a SIGPIPE is issued by a socket call on a remotely closed socket,
176 the program will "crash" unless it explicitly handles the SIGPIPE.
177 By using MSG_NOSIGNAL, the SIGPIPE is suppressed. Later, we will
178 use SO_NOSIGPIPE (if available), the BSD equivalent. */
179#ifdef MSG_NOSIGNAL
180# define GSOCKET_MSG_NOSIGNAL MSG_NOSIGNAL
181#else /* MSG_NOSIGNAL not available (FreeBSD including OS X) */
182# define GSOCKET_MSG_NOSIGNAL 0
183#endif /* MSG_NOSIGNAL */
184
185#ifndef __GSOCKET_STANDALONE__
186# include "wx/unix/gsockunx.h"
187# include "wx/unix/private.h"
188# include "wx/gsocket.h"
189#if wxUSE_THREADS && (defined(HAVE_GETHOSTBYNAME) || defined(HAVE_GETSERVBYNAME))
190# include "wx/thread.h"
191#endif
192#else
193# include "gsockunx.h"
194# include "gsocket.h"
195# ifndef WXUNUSED
196# define WXUNUSED(x)
197# endif
198#endif /* __GSOCKET_STANDALONE__ */
199
200#if defined(HAVE_GETHOSTBYNAME)
201static struct hostent * deepCopyHostent(struct hostent *h,
202 const struct hostent *he,
203 char *buffer, int size, int *err)
204{
205 /* copy old structure */
206 memcpy(h, he, sizeof(struct hostent));
207
208 /* copy name */
209 int len = strlen(h->h_name);
210 if (len > size)
211 {
212 *err = ENOMEM;
213 return NULL;
214 }
215 memcpy(buffer, h->h_name, len);
216 buffer[len] = '\0';
217 h->h_name = buffer;
218
219 /* track position in the buffer */
220 int pos = len + 1;
221
222 /* reuse len to store address length */
223 len = h->h_length;
224
225 /* ensure pointer alignment */
226 unsigned int misalign = sizeof(char *) - pos%sizeof(char *);
227 if(misalign < sizeof(char *))
228 pos += misalign;
229
230 /* leave space for pointer list */
231 char **p = h->h_addr_list, **q;
232 char **h_addr_list = (char **)(buffer + pos);
233 while(*(p++) != 0)
234 pos += sizeof(char *);
235
236 /* copy addresses and fill new pointer list */
237 for (p = h->h_addr_list, q = h_addr_list; *p != 0; p++, q++)
238 {
239 if (size < pos + len)
240 {
241 *err = ENOMEM;
242 return NULL;
243 }
244 memcpy(buffer + pos, *p, len); /* copy content */
245 *q = buffer + pos; /* set copied pointer to copied content */
246 pos += len;
247 }
248 *++q = 0; /* null terminate the pointer list */
249 h->h_addr_list = h_addr_list; /* copy pointer to pointers */
250
251 /* ensure word alignment of pointers */
252 misalign = sizeof(char *) - pos%sizeof(char *);
253 if(misalign < sizeof(char *))
254 pos += misalign;
255
256 /* leave space for pointer list */
257 p = h->h_aliases;
258 char **h_aliases = (char **)(buffer + pos);
259 while(*(p++) != 0)
260 pos += sizeof(char *);
261
262 /* copy aliases and fill new pointer list */
263 for (p = h->h_aliases, q = h_aliases; *p != 0; p++, q++)
264 {
265 len = strlen(*p);
266 if (size <= pos + len)
267 {
268 *err = ENOMEM;
269 return NULL;
270 }
271 memcpy(buffer + pos, *p, len); /* copy content */
272 buffer[pos + len] = '\0';
273 *q = buffer + pos; /* set copied pointer to copied content */
274 pos += len + 1;
275 }
276 *++q = 0; /* null terminate the pointer list */
277 h->h_aliases = h_aliases; /* copy pointer to pointers */
278
279 return h;
280}
281#endif
282
283#if defined(HAVE_GETHOSTBYNAME) && wxUSE_THREADS
284static wxMutex nameLock;
285#endif
286struct hostent * wxGethostbyname_r(const char *hostname, struct hostent *h,
287 void *buffer, int size, int *err)
288
289{
290 struct hostent *he = NULL;
291 *err = 0;
292#if defined(HAVE_FUNC_GETHOSTBYNAME_R_6)
293 if (gethostbyname_r(hostname, h, (char*)buffer, size, &he, err))
294 he = NULL;
295#elif defined(HAVE_FUNC_GETHOSTBYNAME_R_5)
296 he = gethostbyname_r(hostname, h, (char*)buffer, size, err);
297#elif defined(HAVE_FUNC_GETHOSTBYNAME_R_3)
298 if (gethostbyname_r(hostname, h, (struct hostent_data*) buffer))
299 {
300 he = NULL;
301 *err = h_errno;
302 }
303 else
304 he = h;
305#elif defined(HAVE_GETHOSTBYNAME)
306#if wxUSE_THREADS
307 wxMutexLocker locker(nameLock);
308#endif
309 he = gethostbyname(hostname);
310 if (!he)
311 *err = h_errno;
312 else
313 he = deepCopyHostent(h, he, (char*)buffer, size, err);
314#endif
315 return he;
316}
317
318#if defined(HAVE_GETHOSTBYNAME) && wxUSE_THREADS
319static wxMutex addrLock;
320#endif
321struct hostent * wxGethostbyaddr_r(const char *addr_buf, int buf_size,
322 int proto, struct hostent *h,
323 void *buffer, int size, int *err)
324{
325 struct hostent *he = NULL;
326 *err = 0;
327#if defined(HAVE_FUNC_GETHOSTBYNAME_R_6)
328 if (gethostbyaddr_r(addr_buf, buf_size, proto, h,
329 (char*)buffer, size, &he, err))
330 he = NULL;
331#elif defined(HAVE_FUNC_GETHOSTBYNAME_R_5)
332 he = gethostbyaddr_r(addr_buf, buf_size, proto, h, (char*)buffer, size, err);
333#elif defined(HAVE_FUNC_GETHOSTBYNAME_R_3)
334 if (gethostbyaddr_r(addr_buf, buf_size, proto, h,
335 (struct hostent_data*) buffer))
336 {
337 he = NULL;
338 *err = h_errno;
339 }
340 else
341 he = h;
342#elif defined(HAVE_GETHOSTBYNAME)
343#if wxUSE_THREADS
344 wxMutexLocker locker(addrLock);
345#endif
346 he = gethostbyaddr(addr_buf, buf_size, proto);
347 if (!he)
348 *err = h_errno;
349 else
350 he = deepCopyHostent(h, he, (char*)buffer, size, err);
351#endif
352 return he;
353}
354
355#if defined(HAVE_GETSERVBYNAME)
356static struct servent * deepCopyServent(struct servent *s,
357 const struct servent *se,
358 char *buffer, int size)
359{
360 /* copy plain old structure */
361 memcpy(s, se, sizeof(struct servent));
362
363 /* copy name */
364 int len = strlen(s->s_name);
365 if (len >= size)
366 {
367 return NULL;
368 }
369 memcpy(buffer, s->s_name, len);
370 buffer[len] = '\0';
371 s->s_name = buffer;
372
373 /* track position in the buffer */
374 int pos = len + 1;
375
376 /* copy protocol */
377 len = strlen(s->s_proto);
378 if (pos + len >= size)
379 {
380 return NULL;
381 }
382 memcpy(buffer + pos, s->s_proto, len);
383 buffer[pos + len] = '\0';
384 s->s_proto = buffer + pos;
385
386 /* track position in the buffer */
387 pos += len + 1;
388
389 /* ensure pointer alignment */
390 unsigned int misalign = sizeof(char *) - pos%sizeof(char *);
391 if(misalign < sizeof(char *))
392 pos += misalign;
393
394 /* leave space for pointer list */
395 char **p = s->s_aliases, **q;
396 char **s_aliases = (char **)(buffer + pos);
397 while(*(p++) != 0)
398 pos += sizeof(char *);
399
400 /* copy addresses and fill new pointer list */
401 for (p = s->s_aliases, q = s_aliases; *p != 0; p++, q++){
402 len = strlen(*p);
403 if (size <= pos + len)
404 {
405 return NULL;
406 }
407 memcpy(buffer + pos, *p, len); /* copy content */
408 buffer[pos + len] = '\0';
409 *q = buffer + pos; /* set copied pointer to copied content */
410 pos += len + 1;
411 }
412 *++q = 0; /* null terminate the pointer list */
413 s->s_aliases = s_aliases; /* copy pointer to pointers */
414 return s;
415}
416#endif
417
418#if defined(HAVE_GETSERVBYNAME) && wxUSE_THREADS
419static wxMutex servLock;
420#endif
421struct servent *wxGetservbyname_r(const char *port, const char *protocol,
422 struct servent *serv, void *buffer, int size)
423{
424 struct servent *se = NULL;
425#if defined(HAVE_FUNC_GETSERVBYNAME_R_6)
426 if (getservbyname_r(port, protocol, serv, (char*)buffer, size, &se))
427 se = NULL;
428#elif defined(HAVE_FUNC_GETSERVBYNAME_R_5)
429 se = getservbyname_r(port, protocol, serv, (char*)buffer, size);
430#elif defined(HAVE_FUNC_GETSERVBYNAME_R_4)
431 if (getservbyname_r(port, protocol, serv, (struct servent_data*) buffer))
432 se = NULL;
433 else
434 se = serv;
435#elif defined(HAVE_GETSERVBYNAME)
436#if wxUSE_THREADS
437 wxMutexLocker locker(servLock);
438#endif
439 se = getservbyname(port, protocol);
440 if (se)
441 se = deepCopyServent(serv, se, (char*)buffer, size);
442#endif
443 return se;
444}
445
446/* debugging helpers */
447#ifdef __GSOCKET_DEBUG__
448# define GSocket_Debug(args) printf args
449#else
450# define GSocket_Debug(args)
451#endif /* __GSOCKET_DEBUG__ */
452
453/* Table of GUI-related functions. We must call them indirectly because
454 * of wxBase and GUI separation: */
455
456static GSocketGUIFunctionsTable *gs_gui_functions;
457
458class GSocketGUIFunctionsTableNull: public GSocketGUIFunctionsTable
459{
460public:
461 virtual bool OnInit();
462 virtual void OnExit();
463 virtual bool CanUseEventLoop();
464 virtual bool Init_Socket(GSocket *socket);
465 virtual void Destroy_Socket(GSocket *socket);
466 virtual void Install_Callback(GSocket *socket, GSocketEvent event);
467 virtual void Uninstall_Callback(GSocket *socket, GSocketEvent event);
468 virtual void Enable_Events(GSocket *socket);
469 virtual void Disable_Events(GSocket *socket);
470};
471
472bool GSocketGUIFunctionsTableNull::OnInit()
473{ return true; }
474void GSocketGUIFunctionsTableNull::OnExit()
475{}
476bool GSocketGUIFunctionsTableNull::CanUseEventLoop()
477{ return false; }
478bool GSocketGUIFunctionsTableNull::Init_Socket(GSocket *WXUNUSED(socket))
479{ return true; }
480void GSocketGUIFunctionsTableNull::Destroy_Socket(GSocket *WXUNUSED(socket))
481{}
482void GSocketGUIFunctionsTableNull::Install_Callback(GSocket *WXUNUSED(socket), GSocketEvent WXUNUSED(event))
483{}
484void GSocketGUIFunctionsTableNull::Uninstall_Callback(GSocket *WXUNUSED(socket), GSocketEvent WXUNUSED(event))
485{}
486void GSocketGUIFunctionsTableNull::Enable_Events(GSocket *WXUNUSED(socket))
487{}
488void GSocketGUIFunctionsTableNull::Disable_Events(GSocket *WXUNUSED(socket))
489{}
490/* Global initialisers */
491
492void GSocket_SetGUIFunctions(GSocketGUIFunctionsTable *guifunc)
493{
494 gs_gui_functions = guifunc;
495}
496
497int GSocket_Init(void)
498{
499 if (!gs_gui_functions)
500 {
501 static GSocketGUIFunctionsTableNull table;
502 gs_gui_functions = &table;
503 }
504 if ( !gs_gui_functions->OnInit() )
505 return 0;
506 return 1;
507}
508
509void GSocket_Cleanup(void)
510{
511 if (gs_gui_functions)
512 {
513 gs_gui_functions->OnExit();
514 }
515}
516
517/* Constructors / Destructors for GSocket */
518
519GSocket::GSocket()
520{
521 int i;
522
523 m_fd = INVALID_SOCKET;
524 m_handler = NULL;
525
526 for (i=0;i<GSOCK_MAX_EVENT;i++)
527 {
528 m_cbacks[i] = NULL;
529 }
530 m_detected = 0;
531 m_local = NULL;
532 m_peer = NULL;
533 m_error = GSOCK_NOERROR;
534 m_server = false;
535 m_stream = true;
536 m_gui_dependent = NULL;
537 m_non_blocking = false;
538 m_reusable = false;
539 m_broadcast = false;
540 m_dobind = true;
541 m_timeout = 10*60*1000;
542 /* 10 minutes * 60 sec * 1000 millisec */
543 m_establishing = false;
544
545 assert(gs_gui_functions);
546 /* Per-socket GUI-specific initialization */
547 m_ok = gs_gui_functions->Init_Socket(this);
548}
549
550void GSocket::Close()
551{
552 gs_gui_functions->Disable_Events(this);
553
554 /* When running on OS X, the gsockosx implementation of GSocketGUIFunctionsTable
555 will close the socket during Disable_Events. However, it will only do this
556 if it is being used. That is, it won't do it in a console program. To
557 ensure we get the right behavior, we have gsockosx set m_fd = INVALID_SOCKET
558 if it has closed the socket which indicates to us (at runtime, instead of
559 at compile time as this had been before) that the socket has already
560 been closed.
561 */
562 if(m_fd != INVALID_SOCKET)
563 close(m_fd);
564 m_fd = INVALID_SOCKET;
565}
566
567GSocket::~GSocket()
568{
569 assert(this);
570
571 /* Check that the socket is really shutdowned */
572 if (m_fd != INVALID_SOCKET)
573 Shutdown();
574
575 /* Per-socket GUI-specific cleanup */
576 gs_gui_functions->Destroy_Socket(this);
577
578 delete m_handler;
579
580 /* Destroy private addresses */
581 if (m_local)
582 GAddress_destroy(m_local);
583
584 if (m_peer)
585 GAddress_destroy(m_peer);
586}
587
588/* GSocket_Shutdown:
589 * Disallow further read/write operations on this socket, close
590 * the fd and disable all callbacks.
591 */
592void GSocket::Shutdown()
593{
594 int evt;
595
596 assert(this);
597
598 /* Don't allow events to fire after socket has been closed */
599 gs_gui_functions->Disable_Events(this);
600
601 /* If socket has been created, shutdown it */
602 if (m_fd != INVALID_SOCKET)
603 {
604 shutdown(m_fd, 1);
605 Close();
606 }
607
608 /* Disable GUI callbacks */
609 for (evt = 0; evt < GSOCK_MAX_EVENT; evt++)
610 m_cbacks[evt] = NULL;
611
612 m_detected = GSOCK_LOST_FLAG;
613}
614
615/* Address handling */
616
617/* GSocket_SetLocal:
618 * GSocket_GetLocal:
619 * GSocket_SetPeer:
620 * GSocket_GetPeer:
621 * Set or get the local or peer address for this socket. The 'set'
622 * functions return GSOCK_NOERROR on success, an error code otherwise.
623 * The 'get' functions return a pointer to a GAddress object on success,
624 * or NULL otherwise, in which case they set the error code of the
625 * corresponding GSocket.
626 *
627 * Error codes:
628 * GSOCK_INVSOCK - the socket is not valid.
629 * GSOCK_INVADDR - the address is not valid.
630 */
631GSocketError GSocket::SetLocal(GAddress *address)
632{
633 assert(this);
634
635 /* the socket must be initialized, or it must be a server */
636 if ((m_fd != INVALID_SOCKET && !m_server))
637 {
638 m_error = GSOCK_INVSOCK;
639 return GSOCK_INVSOCK;
640 }
641
642 /* check address */
643 if (address == NULL || address->m_family == GSOCK_NOFAMILY)
644 {
645 m_error = GSOCK_INVADDR;
646 return GSOCK_INVADDR;
647 }
648
649 if (m_local)
650 GAddress_destroy(m_local);
651
652 m_local = GAddress_copy(address);
653
654 return GSOCK_NOERROR;
655}
656
657GSocketError GSocket::SetPeer(GAddress *address)
658{
659 assert(this);
660
661 /* check address */
662 if (address == NULL || address->m_family == GSOCK_NOFAMILY)
663 {
664 m_error = GSOCK_INVADDR;
665 return GSOCK_INVADDR;
666 }
667
668 if (m_peer)
669 GAddress_destroy(m_peer);
670
671 m_peer = GAddress_copy(address);
672
673 return GSOCK_NOERROR;
674}
675
676GAddress *GSocket::GetLocal()
677{
678 GAddress *address;
679 struct sockaddr addr;
680 WX_SOCKLEN_T size = sizeof(addr);
681 GSocketError err;
682
683 assert(this);
684
685 /* try to get it from the m_local var first */
686 if (m_local)
687 return GAddress_copy(m_local);
688
689 /* else, if the socket is initialized, try getsockname */
690 if (m_fd == INVALID_SOCKET)
691 {
692 m_error = GSOCK_INVSOCK;
693 return NULL;
694 }
695
696 if (getsockname(m_fd, &addr, (WX_SOCKLEN_T *) &size) < 0)
697 {
698 m_error = GSOCK_IOERR;
699 return NULL;
700 }
701
702 /* got a valid address from getsockname, create a GAddress object */
703 address = GAddress_new();
704 if (address == NULL)
705 {
706 m_error = GSOCK_MEMERR;
707 return NULL;
708 }
709
710 err = _GAddress_translate_from(address, &addr, size);
711 if (err != GSOCK_NOERROR)
712 {
713 GAddress_destroy(address);
714 m_error = err;
715 return NULL;
716 }
717
718 return address;
719}
720
721GAddress *GSocket::GetPeer()
722{
723 assert(this);
724
725 /* try to get it from the m_peer var */
726 if (m_peer)
727 return GAddress_copy(m_peer);
728
729 return NULL;
730}
731
732/* Server specific parts */
733
734/* GSocket_SetServer:
735 * Sets up this socket as a server. The local address must have been
736 * set with GSocket_SetLocal() before GSocket_SetServer() is called.
737 * Returns GSOCK_NOERROR on success, one of the following otherwise:
738 *
739 * Error codes:
740 * GSOCK_INVSOCK - the socket is in use.
741 * GSOCK_INVADDR - the local address has not been set.
742 * GSOCK_IOERR - low-level error.
743 */
744GSocketError GSocket::SetServer()
745{
746 int arg = 1;
747
748 assert(this);
749
750 /* must not be in use */
751 if (m_fd != INVALID_SOCKET)
752 {
753 m_error = GSOCK_INVSOCK;
754 return GSOCK_INVSOCK;
755 }
756
757 /* the local addr must have been set */
758 if (!m_local)
759 {
760 m_error = GSOCK_INVADDR;
761 return GSOCK_INVADDR;
762 }
763
764 /* Initialize all fields */
765 m_stream = true;
766 m_server = true;
767
768 /* Create the socket */
769 m_fd = socket(m_local->m_realfamily, SOCK_STREAM, 0);
770
771 if (m_fd == INVALID_SOCKET)
772 {
773 m_error = GSOCK_IOERR;
774 return GSOCK_IOERR;
775 }
776
777 /* FreeBSD variants can't use MSG_NOSIGNAL, and instead use a socket option */
778#ifdef SO_NOSIGPIPE
779 setsockopt(m_fd, SOL_SOCKET, SO_NOSIGPIPE, (const char*)&arg, sizeof(arg));
780#endif
781
782 ioctl(m_fd, FIONBIO, &arg);
783 gs_gui_functions->Enable_Events(this);
784
785 /* allow a socket to re-bind if the socket is in the TIME_WAIT
786 state after being previously closed.
787 */
788 if (m_reusable)
789 {
790 setsockopt(m_fd, SOL_SOCKET, SO_REUSEADDR, (const char*)&arg, sizeof(arg));
791#ifdef SO_REUSEPORT
792 setsockopt(m_fd, SOL_SOCKET, SO_REUSEPORT, (const char*)&arg, sizeof(arg));
793#endif
794 }
795
796 /* Bind to the local address,
797 * retrieve the actual address bound,
798 * and listen up to 5 connections.
799 */
800 if ((bind(m_fd, m_local->m_addr, m_local->m_len) != 0) ||
801 (getsockname(m_fd,
802 m_local->m_addr,
803 (WX_SOCKLEN_T *) &m_local->m_len) != 0) ||
804 (listen(m_fd, 5) != 0))
805 {
806 Close();
807 m_error = GSOCK_IOERR;
808 return GSOCK_IOERR;
809 }
810
811 return GSOCK_NOERROR;
812}
813
814/* GSocket_WaitConnection:
815 * Waits for an incoming client connection. Returns a pointer to
816 * a GSocket object, or NULL if there was an error, in which case
817 * the last error field will be updated for the calling GSocket.
818 *
819 * Error codes (set in the calling GSocket)
820 * GSOCK_INVSOCK - the socket is not valid or not a server.
821 * GSOCK_TIMEDOUT - timeout, no incoming connections.
822 * GSOCK_WOULDBLOCK - the call would block and the socket is nonblocking.
823 * GSOCK_MEMERR - couldn't allocate memory.
824 * GSOCK_IOERR - low-level error.
825 */
826GSocket *GSocket::WaitConnection()
827{
828 struct sockaddr from;
829 WX_SOCKLEN_T fromlen = sizeof(from);
830 GSocket *connection;
831 GSocketError err;
832 int arg = 1;
833
834 assert(this);
835
836 /* If the socket has already been created, we exit immediately */
837 if (m_fd == INVALID_SOCKET || !m_server)
838 {
839 m_error = GSOCK_INVSOCK;
840 return NULL;
841 }
842
843 /* Create a GSocket object for the new connection */
844 connection = GSocket_new();
845
846 if (!connection)
847 {
848 m_error = GSOCK_MEMERR;
849 return NULL;
850 }
851
852 /* Wait for a connection (with timeout) */
853 if (Input_Timeout() == GSOCK_TIMEDOUT)
854 {
855 delete connection;
856 /* m_error set by _GSocket_Input_Timeout */
857 return NULL;
858 }
859
860 connection->m_fd = accept(m_fd, &from, (WX_SOCKLEN_T *) &fromlen);
861
862 /* Reenable CONNECTION events */
863 Enable(GSOCK_CONNECTION);
864
865 if (connection->m_fd == INVALID_SOCKET)
866 {
867 if (errno == EWOULDBLOCK)
868 m_error = GSOCK_WOULDBLOCK;
869 else
870 m_error = GSOCK_IOERR;
871
872 delete connection;
873 return NULL;
874 }
875
876 /* Initialize all fields */
877 connection->m_server = false;
878 connection->m_stream = true;
879
880 /* Setup the peer address field */
881 connection->m_peer = GAddress_new();
882 if (!connection->m_peer)
883 {
884 delete connection;
885 m_error = GSOCK_MEMERR;
886 return NULL;
887 }
888
889 err = _GAddress_translate_from(connection->m_peer, &from, fromlen);
890 if (err != GSOCK_NOERROR)
891 {
892 delete connection;
893 m_error = err;
894 return NULL;
895 }
896
897#if defined(__EMX__) || defined(__VISAGECPP__)
898 ioctl(connection->m_fd, FIONBIO, (char*)&arg, sizeof(arg));
899#else
900 ioctl(connection->m_fd, FIONBIO, &arg);
901#endif
902 gs_gui_functions->Enable_Events(connection);
903
904 return connection;
905}
906
907bool GSocket::SetReusable()
908{
909 /* socket must not be null, and must not be in use/already bound */
910 if (this && m_fd == INVALID_SOCKET)
911 {
912 m_reusable = true;
913
914 return true;
915 }
916
917 return false;
918}
919
920bool GSocket::SetBroadcast()
921{
922 /* socket must not be in use/already bound */
923 if (m_fd == INVALID_SOCKET) {
924 m_broadcast = true;
925 return true;
926 }
927 return false;
928}
929
930bool GSocket::DontDoBind()
931{
932 /* socket must not be in use/already bound */
933 if (m_fd == INVALID_SOCKET) {
934 m_dobind = false;
935 return true;
936 }
937 return false;
938}
939
940/* Client specific parts */
941
942/* GSocket_Connect:
943 * For stream (connection oriented) sockets, GSocket_Connect() tries
944 * to establish a client connection to a server using the peer address
945 * as established with GSocket_SetPeer(). Returns GSOCK_NOERROR if the
946 * connection has been successfully established, or one of the error
947 * codes listed below. Note that for nonblocking sockets, a return
948 * value of GSOCK_WOULDBLOCK doesn't mean a failure. The connection
949 * request can be completed later; you should use GSocket_Select()
950 * to poll for GSOCK_CONNECTION | GSOCK_LOST, or wait for the
951 * corresponding asynchronous events.
952 *
953 * For datagram (non connection oriented) sockets, GSocket_Connect()
954 * just sets the peer address established with GSocket_SetPeer() as
955 * default destination.
956 *
957 * Error codes:
958 * GSOCK_INVSOCK - the socket is in use or not valid.
959 * GSOCK_INVADDR - the peer address has not been established.
960 * GSOCK_TIMEDOUT - timeout, the connection failed.
961 * GSOCK_WOULDBLOCK - connection in progress (nonblocking sockets only)
962 * GSOCK_MEMERR - couldn't allocate memory.
963 * GSOCK_IOERR - low-level error.
964 */
965GSocketError GSocket::Connect(GSocketStream stream)
966{
967 int err, ret;
968 int arg = 1;
969
970 assert(this);
971
972 /* Enable CONNECTION events (needed for nonblocking connections) */
973 Enable(GSOCK_CONNECTION);
974
975 if (m_fd != INVALID_SOCKET)
976 {
977 m_error = GSOCK_INVSOCK;
978 return GSOCK_INVSOCK;
979 }
980
981 if (!m_peer)
982 {
983 m_error = GSOCK_INVADDR;
984 return GSOCK_INVADDR;
985 }
986
987 /* Streamed or dgram socket? */
988 m_stream = (stream == GSOCK_STREAMED);
989 m_server = false;
990 m_establishing = false;
991
992 /* Create the socket */
993 m_fd = socket(m_peer->m_realfamily,
994 m_stream? SOCK_STREAM : SOCK_DGRAM, 0);
995
996 if (m_fd == INVALID_SOCKET)
997 {
998 m_error = GSOCK_IOERR;
999 return GSOCK_IOERR;
1000 }
1001
1002 /* FreeBSD variants can't use MSG_NOSIGNAL, and instead use a socket option */
1003#ifdef SO_NOSIGPIPE
1004 setsockopt(m_fd, SOL_SOCKET, SO_NOSIGPIPE, (const char*)&arg, sizeof(arg));
1005#endif
1006
1007#if defined(__EMX__) || defined(__VISAGECPP__)
1008 ioctl(m_fd, FIONBIO, (char*)&arg, sizeof(arg));
1009#else
1010 ioctl(m_fd, FIONBIO, &arg);
1011#endif
1012
1013 // If the reuse flag is set, use the applicable socket reuse flags(s)
1014 if (m_reusable)
1015 {
1016 setsockopt(m_fd, SOL_SOCKET, SO_REUSEADDR, (const char*)&arg, sizeof(arg));
1017#ifdef SO_REUSEPORT
1018 setsockopt(m_fd, SOL_SOCKET, SO_REUSEPORT, (const char*)&arg, sizeof(arg));
1019#endif
1020 }
1021
1022 // If a local address has been set, then we need to bind to it before calling connect
1023 if (m_local && m_local->m_addr)
1024 {
1025 bind(m_fd, m_local->m_addr, m_local->m_len);
1026 }
1027
1028 /* Connect it to the peer address, with a timeout (see below) */
1029 ret = connect(m_fd, m_peer->m_addr, m_peer->m_len);
1030
1031 /* We only call Enable_Events if we know we aren't shutting down the socket.
1032 * NB: Enable_Events needs to be called whether the socket is blocking or
1033 * non-blocking, it just shouldn't be called prior to knowing there is a
1034 * connection _if_ blocking sockets are being used.
1035 * If connect above returns 0, we are already connected and need to make the
1036 * call to Enable_Events now.
1037 */
1038
1039 if (m_non_blocking || ret == 0)
1040 gs_gui_functions->Enable_Events(this);
1041
1042 if (ret == -1)
1043 {
1044 err = errno;
1045
1046 /* If connect failed with EINPROGRESS and the GSocket object
1047 * is in blocking mode, we select() for the specified timeout
1048 * checking for writability to see if the connection request
1049 * completes.
1050 */
1051 if ((err == EINPROGRESS) && (!m_non_blocking))
1052 {
1053 if (Output_Timeout() == GSOCK_TIMEDOUT)
1054 {
1055 Close();
1056 /* m_error is set in _GSocket_Output_Timeout */
1057 return GSOCK_TIMEDOUT;
1058 }
1059 else
1060 {
1061 int error;
1062 SOCKOPTLEN_T len = sizeof(error);
1063
1064 getsockopt(m_fd, SOL_SOCKET, SO_ERROR, (char*) &error, &len);
1065
1066 gs_gui_functions->Enable_Events(this);
1067
1068 if (!error)
1069 return GSOCK_NOERROR;
1070 }
1071 }
1072
1073 /* If connect failed with EINPROGRESS and the GSocket object
1074 * is set to nonblocking, we set m_error to GSOCK_WOULDBLOCK
1075 * (and return GSOCK_WOULDBLOCK) but we don't close the socket;
1076 * this way if the connection completes, a GSOCK_CONNECTION
1077 * event will be generated, if enabled.
1078 */
1079 if ((err == EINPROGRESS) && (m_non_blocking))
1080 {
1081 m_establishing = true;
1082 m_error = GSOCK_WOULDBLOCK;
1083 return GSOCK_WOULDBLOCK;
1084 }
1085
1086 /* If connect failed with an error other than EINPROGRESS,
1087 * then the call to GSocket_Connect has failed.
1088 */
1089 Close();
1090 m_error = GSOCK_IOERR;
1091
1092 return GSOCK_IOERR;
1093 }
1094
1095 return GSOCK_NOERROR;
1096}
1097
1098/* Datagram sockets */
1099
1100/* GSocket_SetNonOriented:
1101 * Sets up this socket as a non-connection oriented (datagram) socket.
1102 * Before using this function, the local address must have been set
1103 * with GSocket_SetLocal(), or the call will fail. Returns GSOCK_NOERROR
1104 * on success, or one of the following otherwise.
1105 *
1106 * Error codes:
1107 * GSOCK_INVSOCK - the socket is in use.
1108 * GSOCK_INVADDR - the local address has not been set.
1109 * GSOCK_IOERR - low-level error.
1110 */
1111GSocketError GSocket::SetNonOriented()
1112{
1113 int arg = 1;
1114
1115 assert(this);
1116
1117 if (m_fd != INVALID_SOCKET)
1118 {
1119 m_error = GSOCK_INVSOCK;
1120 return GSOCK_INVSOCK;
1121 }
1122
1123 if (!m_local)
1124 {
1125 m_error = GSOCK_INVADDR;
1126 return GSOCK_INVADDR;
1127 }
1128
1129 /* Initialize all fields */
1130 m_stream = false;
1131 m_server = false;
1132
1133 /* Create the socket */
1134 m_fd = socket(m_local->m_realfamily, SOCK_DGRAM, 0);
1135
1136 if (m_fd == INVALID_SOCKET)
1137 {
1138 m_error = GSOCK_IOERR;
1139 return GSOCK_IOERR;
1140 }
1141#if defined(__EMX__) || defined(__VISAGECPP__)
1142 ioctl(m_fd, FIONBIO, (char*)&arg, sizeof(arg));
1143#else
1144 ioctl(m_fd, FIONBIO, &arg);
1145#endif
1146 gs_gui_functions->Enable_Events(this);
1147
1148 if (m_reusable)
1149 {
1150 setsockopt(m_fd, SOL_SOCKET, SO_REUSEADDR, (const char*)&arg, sizeof(arg));
1151#ifdef SO_REUSEPORT
1152 setsockopt(m_fd, SOL_SOCKET, SO_REUSEPORT, (const char*)&arg, sizeof(arg));
1153#endif
1154 }
1155
1156 if (m_broadcast)
1157 {
1158 setsockopt(m_fd, SOL_SOCKET, SO_BROADCAST, (const char*)&arg, sizeof(arg));
1159 }
1160 if (m_dobind)
1161 {
1162 /* Bind to the local address,
1163 * and retrieve the actual address bound.
1164 */
1165 if ((bind(m_fd, m_local->m_addr, m_local->m_len) != 0) ||
1166 (getsockname(m_fd,
1167 m_local->m_addr,
1168 (WX_SOCKLEN_T *) &m_local->m_len) != 0))
1169 {
1170 Close();
1171 m_error = GSOCK_IOERR;
1172 return GSOCK_IOERR;
1173 }
1174 }
1175 return GSOCK_NOERROR;
1176}
1177
1178/* Generic IO */
1179
1180/* Like recv(), send(), ... */
1181int GSocket::Read(char *buffer, int size)
1182{
1183 int ret;
1184
1185 assert(this);
1186
1187 if (m_fd == INVALID_SOCKET || m_server)
1188 {
1189 m_error = GSOCK_INVSOCK;
1190 return -1;
1191 }
1192
1193 /* Disable events during query of socket status */
1194 Disable(GSOCK_INPUT);
1195
1196 /* If the socket is blocking, wait for data (with a timeout) */
1197 if (Input_Timeout() == GSOCK_TIMEDOUT) {
1198 m_error = GSOCK_TIMEDOUT;
1199 /* Don't return here immediately, otherwise socket events would not be
1200 * re-enabled! */
1201 ret = -1;
1202 }
1203 else
1204 {
1205 /* Read the data */
1206 if (m_stream)
1207 ret = Recv_Stream(buffer, size);
1208 else
1209 ret = Recv_Dgram(buffer, size);
1210
1211 /* If recv returned zero, then the connection has been gracefully closed.
1212 * Otherwise, recv has returned an error (-1), in which case we have lost the
1213 * socket only if errno does _not_ indicate that there may be more data to read.
1214 */
1215 if (ret == 0)
1216 {
1217 /* Make sure wxSOCKET_LOST event gets sent and shut down the socket */
1218 m_detected = GSOCK_LOST_FLAG;
1219 Detected_Read();
1220 return 0;
1221 }
1222 else if (ret == -1)
1223 {
1224 if ((errno == EWOULDBLOCK) || (errno == EAGAIN))
1225 m_error = GSOCK_WOULDBLOCK;
1226 else
1227 m_error = GSOCK_IOERR;
1228 }
1229 }
1230
1231 /* Enable events again now that we are done processing */
1232 Enable(GSOCK_INPUT);
1233
1234 return ret;
1235}
1236
1237int GSocket::Write(const char *buffer, int size)
1238{
1239 int ret;
1240
1241 assert(this);
1242
1243 GSocket_Debug(( "GSocket_Write #1, size %d\n", size ));
1244
1245 if (m_fd == INVALID_SOCKET || m_server)
1246 {
1247 m_error = GSOCK_INVSOCK;
1248 return -1;
1249 }
1250
1251 GSocket_Debug(( "GSocket_Write #2, size %d\n", size ));
1252
1253 /* If the socket is blocking, wait for writability (with a timeout) */
1254 if (Output_Timeout() == GSOCK_TIMEDOUT)
1255 return -1;
1256
1257 GSocket_Debug(( "GSocket_Write #3, size %d\n", size ));
1258
1259 /* Write the data */
1260 if (m_stream)
1261 ret = Send_Stream(buffer, size);
1262 else
1263 ret = Send_Dgram(buffer, size);
1264
1265 GSocket_Debug(( "GSocket_Write #4, size %d\n", size ));
1266
1267 if (ret == -1)
1268 {
1269 if ((errno == EWOULDBLOCK) || (errno == EAGAIN))
1270 {
1271 m_error = GSOCK_WOULDBLOCK;
1272 GSocket_Debug(( "GSocket_Write error WOULDBLOCK\n" ));
1273 }
1274 else
1275 {
1276 m_error = GSOCK_IOERR;
1277 GSocket_Debug(( "GSocket_Write error IOERR\n" ));
1278 }
1279
1280 /* Only reenable OUTPUT events after an error (just like WSAAsyncSelect
1281 * in MSW). Once the first OUTPUT event is received, users can assume
1282 * that the socket is writable until a read operation fails. Only then
1283 * will further OUTPUT events be posted.
1284 */
1285 Enable(GSOCK_OUTPUT);
1286
1287 return -1;
1288 }
1289
1290 GSocket_Debug(( "GSocket_Write #5, size %d ret %d\n", size, ret ));
1291
1292 return ret;
1293}
1294
1295/* GSocket_Select:
1296 * Polls the socket to determine its status. This function will
1297 * check for the events specified in the 'flags' parameter, and
1298 * it will return a mask indicating which operations can be
1299 * performed. This function won't block, regardless of the
1300 * mode (blocking | nonblocking) of the socket.
1301 */
1302GSocketEventFlags GSocket::Select(GSocketEventFlags flags)
1303{
1304 if (!gs_gui_functions->CanUseEventLoop())
1305 {
1306
1307 GSocketEventFlags result = 0;
1308 fd_set readfds;
1309 fd_set writefds;
1310 fd_set exceptfds;
1311 struct timeval tv;
1312
1313 assert(this);
1314
1315 if (m_fd == -1)
1316 return (GSOCK_LOST_FLAG & flags);
1317
1318 /* Do not use a static struct, Linux can garble it */
1319 tv.tv_sec = m_timeout / 1000;
1320 tv.tv_usec = (m_timeout % 1000) * 1000;
1321
1322 wxFD_ZERO(&readfds);
1323 wxFD_ZERO(&writefds);
1324 wxFD_ZERO(&exceptfds);
1325 wxFD_SET(m_fd, &readfds);
1326 if (flags & GSOCK_OUTPUT_FLAG || flags & GSOCK_CONNECTION_FLAG)
1327 wxFD_SET(m_fd, &writefds);
1328 wxFD_SET(m_fd, &exceptfds);
1329
1330 /* Check 'sticky' CONNECTION flag first */
1331 result |= (GSOCK_CONNECTION_FLAG & m_detected);
1332
1333 /* If we have already detected a LOST event, then don't try
1334 * to do any further processing.
1335 */
1336 if ((m_detected & GSOCK_LOST_FLAG) != 0)
1337 {
1338 m_establishing = false;
1339
1340 return (GSOCK_LOST_FLAG & flags);
1341 }
1342
1343 /* Try select now */
1344 if (select(m_fd + 1, &readfds, &writefds, &exceptfds, &tv) <= 0)
1345 {
1346 /* What to do here? */
1347 return (result & flags);
1348 }
1349
1350 /* Check for exceptions and errors */
1351 if (wxFD_ISSET(m_fd, &exceptfds))
1352 {
1353 m_establishing = false;
1354 m_detected = GSOCK_LOST_FLAG;
1355
1356 /* LOST event: Abort any further processing */
1357 return (GSOCK_LOST_FLAG & flags);
1358 }
1359
1360 /* Check for readability */
1361 if (wxFD_ISSET(m_fd, &readfds))
1362 {
1363 result |= GSOCK_INPUT_FLAG;
1364
1365 if (m_server && m_stream)
1366 {
1367 /* This is a TCP server socket that detected a connection.
1368 While the INPUT_FLAG is also set, it doesn't matter on
1369 this kind of sockets, as we can only Accept() from them. */
1370 result |= GSOCK_CONNECTION_FLAG;
1371 m_detected |= GSOCK_CONNECTION_FLAG;
1372 }
1373 }
1374
1375 /* Check for writability */
1376 if (wxFD_ISSET(m_fd, &writefds))
1377 {
1378 if (m_establishing && !m_server)
1379 {
1380 int error;
1381 SOCKOPTLEN_T len = sizeof(error);
1382
1383 m_establishing = false;
1384
1385 getsockopt(m_fd, SOL_SOCKET, SO_ERROR, (char*)&error, &len);
1386
1387 if (error)
1388 {
1389 m_detected = GSOCK_LOST_FLAG;
1390
1391 /* LOST event: Abort any further processing */
1392 return (GSOCK_LOST_FLAG & flags);
1393 }
1394 else
1395 {
1396 result |= GSOCK_CONNECTION_FLAG;
1397 m_detected |= GSOCK_CONNECTION_FLAG;
1398 }
1399 }
1400 else
1401 {
1402 result |= GSOCK_OUTPUT_FLAG;
1403 }
1404 }
1405
1406 return (result & flags);
1407
1408 }
1409 else
1410 {
1411 assert(this);
1412 return flags & m_detected;
1413 }
1414}
1415
1416/* Flags */
1417
1418/* GSocket_SetNonBlocking:
1419 * Sets the socket to non-blocking mode. All IO calls will return
1420 * immediately.
1421 */
1422void GSocket::SetNonBlocking(bool non_block)
1423{
1424 assert(this);
1425
1426 GSocket_Debug( ("GSocket_SetNonBlocking: %d\n", (int)non_block) );
1427
1428 m_non_blocking = non_block;
1429}
1430
1431/* GSocket_SetTimeout:
1432 * Sets the timeout for blocking calls. Time is expressed in
1433 * milliseconds.
1434 */
1435void GSocket::SetTimeout(unsigned long millisec)
1436{
1437 assert(this);
1438
1439 m_timeout = millisec;
1440}
1441
1442/* GSocket_GetError:
1443 * Returns the last error occurred for this socket. Note that successful
1444 * operations do not clear this back to GSOCK_NOERROR, so use it only
1445 * after an error.
1446 */
1447GSocketError WXDLLIMPEXP_NET GSocket::GetError()
1448{
1449 assert(this);
1450
1451 return m_error;
1452}
1453
1454/* Callbacks */
1455
1456/* GSOCK_INPUT:
1457 * There is data to be read in the input buffer. If, after a read
1458 * operation, there is still data available, the callback function will
1459 * be called again.
1460 * GSOCK_OUTPUT:
1461 * The socket is available for writing. That is, the next write call
1462 * won't block. This event is generated only once, when the connection is
1463 * first established, and then only if a call failed with GSOCK_WOULDBLOCK,
1464 * when the output buffer empties again. This means that the app should
1465 * assume that it can write since the first OUTPUT event, and no more
1466 * OUTPUT events will be generated unless an error occurs.
1467 * GSOCK_CONNECTION:
1468 * Connection successfully established, for client sockets, or incoming
1469 * client connection, for server sockets. Wait for this event (also watch
1470 * out for GSOCK_LOST) after you issue a nonblocking GSocket_Connect() call.
1471 * GSOCK_LOST:
1472 * The connection is lost (or a connection request failed); this could
1473 * be due to a failure, or due to the peer closing it gracefully.
1474 */
1475
1476/* GSocket_SetCallback:
1477 * Enables the callbacks specified by 'flags'. Note that 'flags'
1478 * may be a combination of flags OR'ed toghether, so the same
1479 * callback function can be made to accept different events.
1480 * The callback function must have the following prototype:
1481 *
1482 * void function(GSocket *socket, GSocketEvent event, char *cdata)
1483 */
1484void GSocket::SetCallback(GSocketEventFlags flags,
1485 GSocketCallback callback, char *cdata)
1486{
1487 int count;
1488
1489 assert(this);
1490
1491 for (count = 0; count < GSOCK_MAX_EVENT; count++)
1492 {
1493 if ((flags & (1 << count)) != 0)
1494 {
1495 m_cbacks[count] = callback;
1496 m_data[count] = cdata;
1497 }
1498 }
1499}
1500
1501/* GSocket_UnsetCallback:
1502 * Disables all callbacks specified by 'flags', which may be a
1503 * combination of flags OR'ed toghether.
1504 */
1505void GSocket::UnsetCallback(GSocketEventFlags flags)
1506{
1507 int count;
1508
1509 assert(this);
1510
1511 for (count = 0; count < GSOCK_MAX_EVENT; count++)
1512 {
1513 if ((flags & (1 << count)) != 0)
1514 {
1515 m_cbacks[count] = NULL;
1516 m_data[count] = NULL;
1517 }
1518 }
1519}
1520
1521GSocketError GSocket::GetSockOpt(int level, int optname,
1522 void *optval, int *optlen)
1523{
1524 if (getsockopt(m_fd, level, optname, (char*)optval, (SOCKOPTLEN_T*)optlen) == 0)
1525 return GSOCK_NOERROR;
1526
1527 return GSOCK_OPTERR;
1528}
1529
1530GSocketError GSocket::SetSockOpt(int level, int optname,
1531 const void *optval, int optlen)
1532{
1533 if (setsockopt(m_fd, level, optname, (const char*)optval, optlen) == 0)
1534 return GSOCK_NOERROR;
1535
1536 return GSOCK_OPTERR;
1537}
1538
1539#define CALL_CALLBACK(socket, event) { \
1540 socket->Disable(event); \
1541 if (socket->m_cbacks[event]) \
1542 socket->m_cbacks[event](socket, event, socket->m_data[event]); \
1543}
1544
1545
1546void GSocket::Enable(GSocketEvent event)
1547{
1548 m_detected &= ~(1 << event);
1549 gs_gui_functions->Install_Callback(this, event);
1550}
1551
1552void GSocket::Disable(GSocketEvent event)
1553{
1554 m_detected |= (1 << event);
1555 gs_gui_functions->Uninstall_Callback(this, event);
1556}
1557
1558/* _GSocket_Input_Timeout:
1559 * For blocking sockets, wait until data is available or
1560 * until timeout ellapses.
1561 */
1562GSocketError GSocket::Input_Timeout()
1563{
1564 struct timeval tv;
1565 fd_set readfds;
1566 int ret;
1567
1568 /* Linux select() will overwrite the struct on return */
1569 tv.tv_sec = (m_timeout / 1000);
1570 tv.tv_usec = (m_timeout % 1000) * 1000;
1571
1572 if (!m_non_blocking)
1573 {
1574 wxFD_ZERO(&readfds);
1575 wxFD_SET(m_fd, &readfds);
1576 ret = select(m_fd + 1, &readfds, NULL, NULL, &tv);
1577 if (ret == 0)
1578 {
1579 GSocket_Debug(( "GSocket_Input_Timeout, select returned 0\n" ));
1580 m_error = GSOCK_TIMEDOUT;
1581 return GSOCK_TIMEDOUT;
1582 }
1583
1584 if (ret == -1)
1585 {
1586 GSocket_Debug(( "GSocket_Input_Timeout, select returned -1\n" ));
1587 if (errno == EBADF) { GSocket_Debug(( "Invalid file descriptor\n" )); }
1588 if (errno == EINTR) { GSocket_Debug(( "A non blocked signal was caught\n" )); }
1589 if (errno == EINVAL) { GSocket_Debug(( "The highest number descriptor is negative\n" )); }
1590 if (errno == ENOMEM) { GSocket_Debug(( "Not enough memory\n" )); }
1591 m_error = GSOCK_TIMEDOUT;
1592 return GSOCK_TIMEDOUT;
1593 }
1594 }
1595
1596 return GSOCK_NOERROR;
1597}
1598
1599/* _GSocket_Output_Timeout:
1600 * For blocking sockets, wait until data can be sent without
1601 * blocking or until timeout ellapses.
1602 */
1603GSocketError GSocket::Output_Timeout()
1604{
1605 struct timeval tv;
1606 fd_set writefds;
1607 int ret;
1608
1609 /* Linux select() will overwrite the struct on return */
1610 tv.tv_sec = (m_timeout / 1000);
1611 tv.tv_usec = (m_timeout % 1000) * 1000;
1612
1613 GSocket_Debug( ("m_non_blocking has: %d\n", (int)m_non_blocking) );
1614
1615 if (!m_non_blocking)
1616 {
1617 wxFD_ZERO(&writefds);
1618 wxFD_SET(m_fd, &writefds);
1619 ret = select(m_fd + 1, NULL, &writefds, NULL, &tv);
1620 if (ret == 0)
1621 {
1622 GSocket_Debug(( "GSocket_Output_Timeout, select returned 0\n" ));
1623 m_error = GSOCK_TIMEDOUT;
1624 return GSOCK_TIMEDOUT;
1625 }
1626
1627 if (ret == -1)
1628 {
1629 GSocket_Debug(( "GSocket_Output_Timeout, select returned -1\n" ));
1630 if (errno == EBADF) { GSocket_Debug(( "Invalid file descriptor\n" )); }
1631 if (errno == EINTR) { GSocket_Debug(( "A non blocked signal was caught\n" )); }
1632 if (errno == EINVAL) { GSocket_Debug(( "The highest number descriptor is negative\n" )); }
1633 if (errno == ENOMEM) { GSocket_Debug(( "Not enough memory\n" )); }
1634 m_error = GSOCK_TIMEDOUT;
1635 return GSOCK_TIMEDOUT;
1636 }
1637
1638 if ( ! wxFD_ISSET(m_fd, &writefds) )
1639 {
1640 GSocket_Debug(( "GSocket_Output_Timeout is buggy!\n" ));
1641 }
1642 else
1643 {
1644 GSocket_Debug(( "GSocket_Output_Timeout seems correct\n" ));
1645 }
1646 }
1647 else
1648 {
1649 GSocket_Debug(( "GSocket_Output_Timeout, didn't try select!\n" ));
1650 }
1651
1652 return GSOCK_NOERROR;
1653}
1654
1655int GSocket::Recv_Stream(char *buffer, int size)
1656{
1657 int ret;
1658 do
1659 {
1660 ret = recv(m_fd, buffer, size, GSOCKET_MSG_NOSIGNAL);
1661 }
1662 while (ret == -1 && errno == EINTR); /* Loop until not interrupted */
1663
1664 return ret;
1665}
1666
1667int GSocket::Recv_Dgram(char *buffer, int size)
1668{
1669 struct sockaddr from;
1670 WX_SOCKLEN_T fromlen = sizeof(from);
1671 int ret;
1672 GSocketError err;
1673
1674 fromlen = sizeof(from);
1675
1676 do
1677 {
1678 ret = recvfrom(m_fd, buffer, size, 0, &from, (WX_SOCKLEN_T *) &fromlen);
1679 }
1680 while (ret == -1 && errno == EINTR); /* Loop until not interrupted */
1681
1682 if (ret == -1)
1683 return -1;
1684
1685 /* Translate a system address into a GSocket address */
1686 if (!m_peer)
1687 {
1688 m_peer = GAddress_new();
1689 if (!m_peer)
1690 {
1691 m_error = GSOCK_MEMERR;
1692 return -1;
1693 }
1694 }
1695
1696 err = _GAddress_translate_from(m_peer, &from, fromlen);
1697 if (err != GSOCK_NOERROR)
1698 {
1699 GAddress_destroy(m_peer);
1700 m_peer = NULL;
1701 m_error = err;
1702 return -1;
1703 }
1704
1705 return ret;
1706}
1707
1708int GSocket::Send_Stream(const char *buffer, int size)
1709{
1710 int ret;
1711
1712 MASK_SIGNAL();
1713
1714 do
1715 {
1716 ret = send(m_fd, (char *)buffer, size, GSOCKET_MSG_NOSIGNAL);
1717 }
1718 while (ret == -1 && errno == EINTR); /* Loop until not interrupted */
1719
1720 UNMASK_SIGNAL();
1721
1722 return ret;
1723}
1724
1725int GSocket::Send_Dgram(const char *buffer, int size)
1726{
1727 struct sockaddr *addr;
1728 int len, ret;
1729 GSocketError err;
1730
1731 if (!m_peer)
1732 {
1733 m_error = GSOCK_INVADDR;
1734 return -1;
1735 }
1736
1737 err = _GAddress_translate_to(m_peer, &addr, &len);
1738 if (err != GSOCK_NOERROR)
1739 {
1740 m_error = err;
1741 return -1;
1742 }
1743
1744 MASK_SIGNAL();
1745
1746 do
1747 {
1748 ret = sendto(m_fd, (char *)buffer, size, 0, addr, len);
1749 }
1750 while (ret == -1 && errno == EINTR); /* Loop until not interrupted */
1751
1752 UNMASK_SIGNAL();
1753
1754 /* Frees memory allocated from _GAddress_translate_to */
1755 free(addr);
1756
1757 return ret;
1758}
1759
1760void GSocket::Detected_Read()
1761{
1762 char c;
1763
1764 /* Safeguard against straggling call to Detected_Read */
1765 if (m_fd == INVALID_SOCKET)
1766 {
1767 return;
1768 }
1769
1770 /* If we have already detected a LOST event, then don't try
1771 * to do any further processing.
1772 */
1773 if ((m_detected & GSOCK_LOST_FLAG) != 0)
1774 {
1775 m_establishing = false;
1776
1777 CALL_CALLBACK(this, GSOCK_LOST);
1778 Shutdown();
1779 return;
1780 }
1781
1782 int num = recv(m_fd, &c, 1, MSG_PEEK | GSOCKET_MSG_NOSIGNAL);
1783
1784 if (num > 0)
1785 {
1786 CALL_CALLBACK(this, GSOCK_INPUT);
1787 }
1788 else
1789 {
1790 if (m_server && m_stream)
1791 {
1792 CALL_CALLBACK(this, GSOCK_CONNECTION);
1793 }
1794 else if (num == 0)
1795 {
1796 /* graceful shutdown */
1797 CALL_CALLBACK(this, GSOCK_LOST);
1798 Shutdown();
1799 }
1800 else
1801 {
1802 /* Do not throw a lost event in cases where the socket isn't really lost */
1803 if ((errno == EWOULDBLOCK) || (errno == EAGAIN) || (errno == EINTR))
1804 {
1805 CALL_CALLBACK(this, GSOCK_INPUT);
1806 }
1807 else
1808 {
1809 CALL_CALLBACK(this, GSOCK_LOST);
1810 Shutdown();
1811 }
1812 }
1813 }
1814}
1815
1816void GSocket::Detected_Write()
1817{
1818 /* If we have already detected a LOST event, then don't try
1819 * to do any further processing.
1820 */
1821 if ((m_detected & GSOCK_LOST_FLAG) != 0)
1822 {
1823 m_establishing = false;
1824
1825 CALL_CALLBACK(this, GSOCK_LOST);
1826 Shutdown();
1827 return;
1828 }
1829
1830 if (m_establishing && !m_server)
1831 {
1832 int error;
1833 SOCKOPTLEN_T len = sizeof(error);
1834
1835 m_establishing = false;
1836
1837 getsockopt(m_fd, SOL_SOCKET, SO_ERROR, (char*)&error, &len);
1838
1839 if (error)
1840 {
1841 CALL_CALLBACK(this, GSOCK_LOST);
1842 Shutdown();
1843 }
1844 else
1845 {
1846 CALL_CALLBACK(this, GSOCK_CONNECTION);
1847 /* We have to fire this event by hand because CONNECTION (for clients)
1848 * and OUTPUT are internally the same and we just disabled CONNECTION
1849 * events with the above macro.
1850 */
1851 CALL_CALLBACK(this, GSOCK_OUTPUT);
1852 }
1853 }
1854 else
1855 {
1856 CALL_CALLBACK(this, GSOCK_OUTPUT);
1857 }
1858}
1859
1860/* Compatibility functions for GSocket */
1861GSocket *GSocket_new(void)
1862{
1863 GSocket *newsocket = new GSocket();
1864 if (newsocket->IsOk())
1865 return newsocket;
1866
1867 delete newsocket;
1868
1869 return NULL;
1870}
1871
1872/*
1873 * -------------------------------------------------------------------------
1874 * GAddress
1875 * -------------------------------------------------------------------------
1876 */
1877
1878/* CHECK_ADDRESS verifies that the current address family is either
1879 * GSOCK_NOFAMILY or GSOCK_*family*, and if it is GSOCK_NOFAMILY, it
1880 * initalizes it to be a GSOCK_*family*. In other cases, it returns
1881 * an appropiate error code.
1882 *
1883 * CHECK_ADDRESS_RETVAL does the same but returning 'retval' on error.
1884 */
1885#define CHECK_ADDRESS(address, family) \
1886{ \
1887 if (address->m_family == GSOCK_NOFAMILY) \
1888 if (_GAddress_Init_##family(address) != GSOCK_NOERROR) \
1889 return address->m_error; \
1890 if (address->m_family != GSOCK_##family) \
1891 { \
1892 address->m_error = GSOCK_INVADDR; \
1893 return GSOCK_INVADDR; \
1894 } \
1895}
1896
1897#define CHECK_ADDRESS_RETVAL(address, family, retval) \
1898{ \
1899 if (address->m_family == GSOCK_NOFAMILY) \
1900 if (_GAddress_Init_##family(address) != GSOCK_NOERROR) \
1901 return retval; \
1902 if (address->m_family != GSOCK_##family) \
1903 { \
1904 address->m_error = GSOCK_INVADDR; \
1905 return retval; \
1906 } \
1907}
1908
1909
1910GAddress *GAddress_new(void)
1911{
1912 GAddress *address;
1913
1914 if ((address = (GAddress *) malloc(sizeof(GAddress))) == NULL)
1915 return NULL;
1916
1917 address->m_family = GSOCK_NOFAMILY;
1918 address->m_addr = NULL;
1919 address->m_len = 0;
1920
1921 return address;
1922}
1923
1924GAddress *GAddress_copy(GAddress *address)
1925{
1926 GAddress *addr2;
1927
1928 assert(address != NULL);
1929
1930 if ((addr2 = (GAddress *) malloc(sizeof(GAddress))) == NULL)
1931 return NULL;
1932
1933 memcpy(addr2, address, sizeof(GAddress));
1934
1935 if (address->m_addr && address->m_len > 0)
1936 {
1937 addr2->m_addr = (struct sockaddr *)malloc(addr2->m_len);
1938 if (addr2->m_addr == NULL)
1939 {
1940 free(addr2);
1941 return NULL;
1942 }
1943 memcpy(addr2->m_addr, address->m_addr, addr2->m_len);
1944 }
1945
1946 return addr2;
1947}
1948
1949void GAddress_destroy(GAddress *address)
1950{
1951 assert(address != NULL);
1952
1953 if (address->m_addr)
1954 free(address->m_addr);
1955
1956 free(address);
1957}
1958
1959void GAddress_SetFamily(GAddress *address, GAddressType type)
1960{
1961 assert(address != NULL);
1962
1963 address->m_family = type;
1964}
1965
1966GAddressType GAddress_GetFamily(GAddress *address)
1967{
1968 assert(address != NULL);
1969
1970 return address->m_family;
1971}
1972
1973GSocketError _GAddress_translate_from(GAddress *address,
1974 struct sockaddr *addr, int len)
1975{
1976 address->m_realfamily = addr->sa_family;
1977 switch (addr->sa_family)
1978 {
1979 case AF_INET:
1980 address->m_family = GSOCK_INET;
1981 break;
1982 case AF_UNIX:
1983 address->m_family = GSOCK_UNIX;
1984 break;
1985#ifdef AF_INET6
1986 case AF_INET6:
1987 address->m_family = GSOCK_INET6;
1988 break;
1989#endif
1990 default:
1991 {
1992 address->m_error = GSOCK_INVOP;
1993 return GSOCK_INVOP;
1994 }
1995 }
1996
1997 if (address->m_addr)
1998 free(address->m_addr);
1999
2000 address->m_len = len;
2001 address->m_addr = (struct sockaddr *)malloc(len);
2002
2003 if (address->m_addr == NULL)
2004 {
2005 address->m_error = GSOCK_MEMERR;
2006 return GSOCK_MEMERR;
2007 }
2008
2009 memcpy(address->m_addr, addr, len);
2010
2011 return GSOCK_NOERROR;
2012}
2013
2014GSocketError _GAddress_translate_to(GAddress *address,
2015 struct sockaddr **addr, int *len)
2016{
2017 if (!address->m_addr)
2018 {
2019 address->m_error = GSOCK_INVADDR;
2020 return GSOCK_INVADDR;
2021 }
2022
2023 *len = address->m_len;
2024 *addr = (struct sockaddr *)malloc(address->m_len);
2025 if (*addr == NULL)
2026 {
2027 address->m_error = GSOCK_MEMERR;
2028 return GSOCK_MEMERR;
2029 }
2030
2031 memcpy(*addr, address->m_addr, address->m_len);
2032 return GSOCK_NOERROR;
2033}
2034
2035/*
2036 * -------------------------------------------------------------------------
2037 * Internet address family
2038 * -------------------------------------------------------------------------
2039 */
2040
2041GSocketError _GAddress_Init_INET(GAddress *address)
2042{
2043 address->m_len = sizeof(struct sockaddr_in);
2044 address->m_addr = (struct sockaddr *) malloc(address->m_len);
2045 if (address->m_addr == NULL)
2046 {
2047 address->m_error = GSOCK_MEMERR;
2048 return GSOCK_MEMERR;
2049 }
2050
2051 address->m_family = GSOCK_INET;
2052 address->m_realfamily = PF_INET;
2053 ((struct sockaddr_in *)address->m_addr)->sin_family = AF_INET;
2054 ((struct sockaddr_in *)address->m_addr)->sin_addr.s_addr = INADDR_ANY;
2055
2056 return GSOCK_NOERROR;
2057}
2058
2059GSocketError GAddress_INET_SetHostName(GAddress *address, const char *hostname)
2060{
2061 struct hostent *he;
2062 struct in_addr *addr;
2063
2064 assert(address != NULL);
2065
2066 CHECK_ADDRESS(address, INET);
2067
2068 addr = &(((struct sockaddr_in *)address->m_addr)->sin_addr);
2069
2070 /* If it is a numeric host name, convert it now */
2071#if defined(HAVE_INET_ATON)
2072 if (inet_aton(hostname, addr) == 0)
2073 {
2074#elif defined(HAVE_INET_ADDR)
2075 if ( (addr->s_addr = inet_addr(hostname)) == (unsigned)-1 )
2076 {
2077#else
2078 /* Use gethostbyname by default */
2079#ifndef __WXMAC__
2080 int val = 1; /* VA doesn't like constants in conditional expressions */
2081 if (val)
2082#endif
2083 {
2084#endif
2085 struct in_addr *array_addr;
2086
2087 /* It is a real name, we solve it */
2088 struct hostent h;
2089#if defined(HAVE_FUNC_GETHOSTBYNAME_R_3)
2090 struct hostent_data buffer;
2091#else
2092 char buffer[1024];
2093#endif
2094 int err;
2095 he = wxGethostbyname_r(hostname, &h, (void*)&buffer, sizeof(buffer), &err);
2096 if (he == NULL)
2097 {
2098 /* Reset to invalid address */
2099 addr->s_addr = INADDR_NONE;
2100 address->m_error = GSOCK_NOHOST;
2101 return GSOCK_NOHOST;
2102 }
2103
2104 array_addr = (struct in_addr *) *(he->h_addr_list);
2105 addr->s_addr = array_addr[0].s_addr;
2106 }
2107
2108 return GSOCK_NOERROR;
2109}
2110
2111
2112GSocketError GAddress_INET_SetBroadcastAddress(GAddress *address)
2113{
2114 return GAddress_INET_SetHostAddress(address, INADDR_BROADCAST);
2115}
2116
2117GSocketError GAddress_INET_SetAnyAddress(GAddress *address)
2118{
2119 return GAddress_INET_SetHostAddress(address, INADDR_ANY);
2120}
2121
2122GSocketError GAddress_INET_SetHostAddress(GAddress *address,
2123 unsigned long hostaddr)
2124{
2125 struct in_addr *addr;
2126
2127 assert(address != NULL);
2128
2129 CHECK_ADDRESS(address, INET);
2130
2131 addr = &(((struct sockaddr_in *)address->m_addr)->sin_addr);
2132 addr->s_addr = htonl(hostaddr);
2133
2134 return GSOCK_NOERROR;
2135}
2136
2137GSocketError GAddress_INET_SetPortName(GAddress *address, const char *port,
2138 const char *protocol)
2139{
2140 struct servent *se;
2141 struct sockaddr_in *addr;
2142
2143 assert(address != NULL);
2144 CHECK_ADDRESS(address, INET);
2145
2146 if (!port)
2147 {
2148 address->m_error = GSOCK_INVPORT;
2149 return GSOCK_INVPORT;
2150 }
2151
2152#if defined(HAVE_FUNC_GETSERVBYNAME_R_4)
2153 struct servent_data buffer;
2154#else
2155 char buffer[1024];
2156#endif
2157 struct servent serv;
2158 se = wxGetservbyname_r(port, protocol, &serv,
2159 (void*)&buffer, sizeof(buffer));
2160 if (!se)
2161 {
2162 /* the cast to int suppresses compiler warnings about subscript having the
2163 type char */
2164 if (isdigit((int)port[0]))
2165 {
2166 int port_int;
2167
2168 port_int = atoi(port);
2169 addr = (struct sockaddr_in *)address->m_addr;
2170 addr->sin_port = htons(port_int);
2171 return GSOCK_NOERROR;
2172 }
2173
2174 address->m_error = GSOCK_INVPORT;
2175 return GSOCK_INVPORT;
2176 }
2177
2178 addr = (struct sockaddr_in *)address->m_addr;
2179 addr->sin_port = se->s_port;
2180
2181 return GSOCK_NOERROR;
2182}
2183
2184GSocketError GAddress_INET_SetPort(GAddress *address, unsigned short port)
2185{
2186 struct sockaddr_in *addr;
2187
2188 assert(address != NULL);
2189 CHECK_ADDRESS(address, INET);
2190
2191 addr = (struct sockaddr_in *)address->m_addr;
2192 addr->sin_port = htons(port);
2193
2194 return GSOCK_NOERROR;
2195}
2196
2197GSocketError GAddress_INET_GetHostName(GAddress *address, char *hostname, size_t sbuf)
2198{
2199 struct hostent *he;
2200 char *addr_buf;
2201 struct sockaddr_in *addr;
2202
2203 assert(address != NULL);
2204 CHECK_ADDRESS(address, INET);
2205
2206 addr = (struct sockaddr_in *)address->m_addr;
2207 addr_buf = (char *)&(addr->sin_addr);
2208
2209 struct hostent temphost;
2210#if defined(HAVE_FUNC_GETHOSTBYNAME_R_3)
2211 struct hostent_data buffer;
2212#else
2213 char buffer[1024];
2214#endif
2215 int err;
2216 he = wxGethostbyaddr_r(addr_buf, sizeof(addr->sin_addr), AF_INET, &temphost,
2217 (void*)&buffer, sizeof(buffer), &err);
2218 if (he == NULL)
2219 {
2220 address->m_error = GSOCK_NOHOST;
2221 return GSOCK_NOHOST;
2222 }
2223
2224 strncpy(hostname, he->h_name, sbuf);
2225
2226 return GSOCK_NOERROR;
2227}
2228
2229unsigned long GAddress_INET_GetHostAddress(GAddress *address)
2230{
2231 struct sockaddr_in *addr;
2232
2233 assert(address != NULL);
2234 CHECK_ADDRESS_RETVAL(address, INET, 0);
2235
2236 addr = (struct sockaddr_in *)address->m_addr;
2237
2238 return ntohl(addr->sin_addr.s_addr);
2239}
2240
2241unsigned short GAddress_INET_GetPort(GAddress *address)
2242{
2243 struct sockaddr_in *addr;
2244
2245 assert(address != NULL);
2246 CHECK_ADDRESS_RETVAL(address, INET, 0);
2247
2248 addr = (struct sockaddr_in *)address->m_addr;
2249 return ntohs(addr->sin_port);
2250}
2251
2252/*
2253 * -------------------------------------------------------------------------
2254 * Unix address family
2255 * -------------------------------------------------------------------------
2256 */
2257
2258#ifndef __VISAGECPP__
2259GSocketError _GAddress_Init_UNIX(GAddress *address)
2260{
2261 address->m_len = sizeof(struct sockaddr_un);
2262 address->m_addr = (struct sockaddr *)malloc(address->m_len);
2263 if (address->m_addr == NULL)
2264 {
2265 address->m_error = GSOCK_MEMERR;
2266 return GSOCK_MEMERR;
2267 }
2268
2269 address->m_family = GSOCK_UNIX;
2270 address->m_realfamily = PF_UNIX;
2271 ((struct sockaddr_un *)address->m_addr)->sun_family = AF_UNIX;
2272 ((struct sockaddr_un *)address->m_addr)->sun_path[0] = 0;
2273
2274 return GSOCK_NOERROR;
2275}
2276
2277#define UNIX_SOCK_PATHLEN (sizeof(addr->sun_path)/sizeof(addr->sun_path[0]))
2278
2279GSocketError GAddress_UNIX_SetPath(GAddress *address, const char *path)
2280{
2281 struct sockaddr_un *addr;
2282
2283 assert(address != NULL);
2284
2285 CHECK_ADDRESS(address, UNIX);
2286
2287 addr = ((struct sockaddr_un *)address->m_addr);
2288 strncpy(addr->sun_path, path, UNIX_SOCK_PATHLEN);
2289 addr->sun_path[UNIX_SOCK_PATHLEN - 1] = '\0';
2290
2291 return GSOCK_NOERROR;
2292}
2293
2294GSocketError GAddress_UNIX_GetPath(GAddress *address, char *path, size_t sbuf)
2295{
2296 struct sockaddr_un *addr;
2297
2298 assert(address != NULL);
2299 CHECK_ADDRESS(address, UNIX);
2300
2301 addr = (struct sockaddr_un *)address->m_addr;
2302
2303 strncpy(path, addr->sun_path, sbuf);
2304
2305 return GSOCK_NOERROR;
2306}
2307#endif /* !defined(__VISAGECPP__) */
2308#endif /* wxUSE_SOCKETS || defined(__GSOCKET_STANDALONE__) */