]>
git.saurik.com Git - wxWidgets.git/blob - src/unix/sockunix.cpp
0a0fbac7167e4d7d2addc37012110d573091dfeb
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/unix/sockunix.cpp
3 // Purpose: wxSocketImpl implementation for Unix systems
4 // Authors: Guilhem Lavaux, Guillermo Rodriguez Garcia, David Elliott,
8 // Copyright: (c) 1997 Guilhem Lavaux
9 // (c) 2008 Vadim Zeitlin
10 // Licence: wxWindows licence
11 /////////////////////////////////////////////////////////////////////////////
14 #include "wx/wxprec.h"
18 #include "wx/private/fd.h"
19 #include "wx/private/socket.h"
20 #include "wx/unix/private/sockunix.h"
21 #include "wx/private/gsocketiohandler.h"
23 #if defined(__VISAGECPP__)
24 #define BSD_SELECT /* use Berkeley Sockets select */
27 #if defined(__WATCOMC__)
33 #include <sys/types.h>
38 #include <netinet/in.h>
41 #include <sys/ioctl.h>
43 #ifdef HAVE_SYS_SELECT_H
44 # include <sys/select.h>
51 u_char sun_len
; /* sockaddr len including null */
52 u_char sun_family
; /* AF_UNIX */
53 char sun_path
[108]; /* path name (gag) */
56 #include <sys/socket.h>
62 #include <netinet/in.h>
63 #include <arpa/inet.h>
70 #include <machine/endian.h>
76 #define EBADF SOCEBADF
82 #include <sys/socket.h>
83 #include <sys/ioctl.h>
84 #include <sys/select.h>
86 #define close(a) soclose(a)
87 #define select(a,b,c,d,e) bsdselect(a,b,c,d,e)
88 int _System
bsdselect(int,
93 int _System
soclose(int);
97 #include <sys/select.h>
105 # include <sys/filio.h>
108 # include <bstring.h>
111 # include <strings.h>
118 # define WX_SOCKLEN_T unsigned int
122 # define WX_SOCKLEN_T socklen_t
124 # elif defined(__WXMAC__)
125 # define WX_SOCKLEN_T socklen_t
127 # define WX_SOCKLEN_T int
131 #endif /* SOCKLEN_T */
134 #define SOCKOPTLEN_T WX_SOCKLEN_T
137 /* UnixWare reportedly needs this for FIONBIO definition */
139 #include <sys/filio.h>
143 * INADDR_BROADCAST is identical to INADDR_NONE which is not defined
144 * on all systems. INADDR_BROADCAST should be fine to indicate an error.
147 #define INADDR_NONE INADDR_BROADCAST
150 #if defined(__VISAGECPP__) || defined(__WATCOMC__)
152 #define MASK_SIGNAL() {
153 #define UNMASK_SIGNAL() }
156 extern "C" { typedef void (*wxSigHandler
)(int); }
158 #define MASK_SIGNAL() \
160 wxSigHandler old_handler = signal(SIGPIPE, SIG_IGN);
162 #define UNMASK_SIGNAL() \
163 signal(SIGPIPE, old_handler); \
168 /* If a SIGPIPE is issued by a socket call on a remotely closed socket,
169 the program will "crash" unless it explicitly handles the SIGPIPE.
170 By using MSG_NOSIGNAL, the SIGPIPE is suppressed. Later, we will
171 use SO_NOSIGPIPE (if available), the BSD equivalent. */
173 # define GSOCKET_MSG_NOSIGNAL MSG_NOSIGNAL
174 #else /* MSG_NOSIGNAL not available (FreeBSD including OS X) */
175 # define GSOCKET_MSG_NOSIGNAL 0
176 #endif /* MSG_NOSIGNAL */
178 #if wxUSE_THREADS && (defined(HAVE_GETHOSTBYNAME) || defined(HAVE_GETSERVBYNAME))
179 # include "wx/thread.h"
182 #if defined(HAVE_GETHOSTBYNAME)
183 static struct hostent
* deepCopyHostent(struct hostent
*h
,
184 const struct hostent
*he
,
185 char *buffer
, int size
, int *err
)
187 /* copy old structure */
188 memcpy(h
, he
, sizeof(struct hostent
));
191 int len
= strlen(h
->h_name
);
197 memcpy(buffer
, h
->h_name
, len
);
201 /* track position in the buffer */
204 /* reuse len to store address length */
207 /* ensure pointer alignment */
208 unsigned int misalign
= sizeof(char *) - pos%sizeof
(char *);
209 if(misalign
< sizeof(char *))
212 /* leave space for pointer list */
213 char **p
= h
->h_addr_list
, **q
;
214 char **h_addr_list
= (char **)(buffer
+ pos
);
216 pos
+= sizeof(char *);
218 /* copy addresses and fill new pointer list */
219 for (p
= h
->h_addr_list
, q
= h_addr_list
; *p
!= 0; p
++, q
++)
221 if (size
< pos
+ len
)
226 memcpy(buffer
+ pos
, *p
, len
); /* copy content */
227 *q
= buffer
+ pos
; /* set copied pointer to copied content */
230 *++q
= 0; /* null terminate the pointer list */
231 h
->h_addr_list
= h_addr_list
; /* copy pointer to pointers */
233 /* ensure word alignment of pointers */
234 misalign
= sizeof(char *) - pos%sizeof
(char *);
235 if(misalign
< sizeof(char *))
238 /* leave space for pointer list */
240 char **h_aliases
= (char **)(buffer
+ pos
);
242 pos
+= sizeof(char *);
244 /* copy aliases and fill new pointer list */
245 for (p
= h
->h_aliases
, q
= h_aliases
; *p
!= 0; p
++, q
++)
248 if (size
<= pos
+ len
)
253 memcpy(buffer
+ pos
, *p
, len
); /* copy content */
254 buffer
[pos
+ len
] = '\0';
255 *q
= buffer
+ pos
; /* set copied pointer to copied content */
258 *++q
= 0; /* null terminate the pointer list */
259 h
->h_aliases
= h_aliases
; /* copy pointer to pointers */
265 #if defined(HAVE_GETHOSTBYNAME) && wxUSE_THREADS
266 static wxMutex nameLock
;
268 struct hostent
* wxGethostbyname_r(const char *hostname
, struct hostent
*h
,
269 void *buffer
, int size
, int *err
)
272 struct hostent
*he
= NULL
;
274 #if defined(HAVE_FUNC_GETHOSTBYNAME_R_6)
275 if (gethostbyname_r(hostname
, h
, (char*)buffer
, size
, &he
, err
))
277 #elif defined(HAVE_FUNC_GETHOSTBYNAME_R_5)
278 he
= gethostbyname_r(hostname
, h
, (char*)buffer
, size
, err
);
279 #elif defined(HAVE_FUNC_GETHOSTBYNAME_R_3)
280 if (gethostbyname_r(hostname
, h
, (struct hostent_data
*) buffer
))
287 #elif defined(HAVE_GETHOSTBYNAME)
289 wxMutexLocker
locker(nameLock
);
291 he
= gethostbyname(hostname
);
295 he
= deepCopyHostent(h
, he
, (char*)buffer
, size
, err
);
300 #if defined(HAVE_GETHOSTBYNAME) && wxUSE_THREADS
301 static wxMutex addrLock
;
303 struct hostent
* wxGethostbyaddr_r(const char *addr_buf
, int buf_size
,
304 int proto
, struct hostent
*h
,
305 void *buffer
, int size
, int *err
)
307 struct hostent
*he
= NULL
;
309 #if defined(HAVE_FUNC_GETHOSTBYNAME_R_6)
310 if (gethostbyaddr_r(addr_buf
, buf_size
, proto
, h
,
311 (char*)buffer
, size
, &he
, err
))
313 #elif defined(HAVE_FUNC_GETHOSTBYNAME_R_5)
314 he
= gethostbyaddr_r(addr_buf
, buf_size
, proto
, h
, (char*)buffer
, size
, err
);
315 #elif defined(HAVE_FUNC_GETHOSTBYNAME_R_3)
316 if (gethostbyaddr_r(addr_buf
, buf_size
, proto
, h
,
317 (struct hostent_data
*) buffer
))
324 #elif defined(HAVE_GETHOSTBYNAME)
326 wxMutexLocker
locker(addrLock
);
328 he
= gethostbyaddr(addr_buf
, buf_size
, proto
);
332 he
= deepCopyHostent(h
, he
, (char*)buffer
, size
, err
);
337 #if defined(HAVE_GETSERVBYNAME)
338 static struct servent
* deepCopyServent(struct servent
*s
,
339 const struct servent
*se
,
340 char *buffer
, int size
)
342 /* copy plain old structure */
343 memcpy(s
, se
, sizeof(struct servent
));
346 int len
= strlen(s
->s_name
);
351 memcpy(buffer
, s
->s_name
, len
);
355 /* track position in the buffer */
359 len
= strlen(s
->s_proto
);
360 if (pos
+ len
>= size
)
364 memcpy(buffer
+ pos
, s
->s_proto
, len
);
365 buffer
[pos
+ len
] = '\0';
366 s
->s_proto
= buffer
+ pos
;
368 /* track position in the buffer */
371 /* ensure pointer alignment */
372 unsigned int misalign
= sizeof(char *) - pos%sizeof
(char *);
373 if(misalign
< sizeof(char *))
376 /* leave space for pointer list */
377 char **p
= s
->s_aliases
, **q
;
378 char **s_aliases
= (char **)(buffer
+ pos
);
380 pos
+= sizeof(char *);
382 /* copy addresses and fill new pointer list */
383 for (p
= s
->s_aliases
, q
= s_aliases
; *p
!= 0; p
++, q
++){
385 if (size
<= pos
+ len
)
389 memcpy(buffer
+ pos
, *p
, len
); /* copy content */
390 buffer
[pos
+ len
] = '\0';
391 *q
= buffer
+ pos
; /* set copied pointer to copied content */
394 *++q
= 0; /* null terminate the pointer list */
395 s
->s_aliases
= s_aliases
; /* copy pointer to pointers */
400 #if defined(HAVE_GETSERVBYNAME) && wxUSE_THREADS
401 static wxMutex servLock
;
403 struct servent
*wxGetservbyname_r(const char *port
, const char *protocol
,
404 struct servent
*serv
, void *buffer
, int size
)
406 struct servent
*se
= NULL
;
407 #if defined(HAVE_FUNC_GETSERVBYNAME_R_6)
408 if (getservbyname_r(port
, protocol
, serv
, (char*)buffer
, size
, &se
))
410 #elif defined(HAVE_FUNC_GETSERVBYNAME_R_5)
411 se
= getservbyname_r(port
, protocol
, serv
, (char*)buffer
, size
);
412 #elif defined(HAVE_FUNC_GETSERVBYNAME_R_4)
413 if (getservbyname_r(port
, protocol
, serv
, (struct servent_data
*) buffer
))
417 #elif defined(HAVE_GETSERVBYNAME)
419 wxMutexLocker
locker(servLock
);
421 se
= getservbyname(port
, protocol
);
423 se
= deepCopyServent(serv
, se
, (char*)buffer
, size
);
428 /* debugging helpers */
429 #ifdef __GSOCKET_DEBUG__
430 # define SOCKET_DEBUG(args) printf args
432 # define SOCKET_DEBUG(args)
433 #endif /* __GSOCKET_DEBUG__ */
435 /* Constructors / Destructors for wxSocketImplUnix */
437 wxSocketImplUnix::wxSocketImplUnix(wxSocketBase
& wxsocket
)
438 : wxSocketImpl(wxsocket
)
443 m_use_events
= false;
447 * Disallow further read/write operations on this socket, close
448 * the fd and disable all callbacks.
450 void wxSocketImplUnix::Shutdown()
452 /* Don't allow events to fire after socket has been closed */
455 wxSocketImpl::Shutdown();
459 * Waits for an incoming client connection. Returns a pointer to
460 * a wxSocketImplUnix object, or NULL if there was an error, in which case
461 * the last error field will be updated for the calling wxSocketImplUnix.
463 * Error codes (set in the calling wxSocketImplUnix)
464 * wxSOCKET_INVSOCK - the socket is not valid or not a server.
465 * wxSOCKET_TIMEDOUT - timeout, no incoming connections.
466 * wxSOCKET_WOULDBLOCK - the call would block and the socket is nonblocking.
467 * wxSOCKET_MEMERR - couldn't allocate memory.
468 * wxSOCKET_IOERR - low-level error.
470 wxSocketImpl
*wxSocketImplUnix::WaitConnection(wxSocketBase
& wxsocket
)
473 WX_SOCKLEN_T fromlen
= sizeof(from
);
474 wxSocketImpl
*connection
;
478 /* If the socket has already been created, we exit immediately */
479 if (m_fd
== INVALID_SOCKET
|| !m_server
)
481 m_error
= wxSOCKET_INVSOCK
;
485 /* Create a wxSocketImplUnix object for the new connection */
486 connection
= wxSocketImplUnix::Create(wxsocket
);
490 m_error
= wxSOCKET_MEMERR
;
494 /* Wait for a connection (with timeout) */
495 if (Input_Timeout() == wxSOCKET_TIMEDOUT
)
498 /* m_error set by Input_Timeout */
502 connection
->m_fd
= accept(m_fd
, (sockaddr
*)&from
, (WX_SOCKLEN_T
*) &fromlen
);
504 /* Reenable CONNECTION events */
505 EnableEvent(wxSOCKET_CONNECTION
);
507 if (connection
->m_fd
== INVALID_SOCKET
)
509 if (errno
== EWOULDBLOCK
)
510 m_error
= wxSOCKET_WOULDBLOCK
;
512 m_error
= wxSOCKET_IOERR
;
518 /* Initialize all fields */
519 connection
->m_server
= false;
520 connection
->m_stream
= true;
522 /* Setup the peer address field */
523 connection
->m_peer
= GAddress_new();
524 if (!connection
->m_peer
)
527 m_error
= wxSOCKET_MEMERR
;
531 err
= _GAddress_translate_from(connection
->m_peer
, (sockaddr
*)&from
, fromlen
);
532 if (err
!= wxSOCKET_NOERROR
)
539 #if defined(__EMX__) || defined(__VISAGECPP__)
540 ioctl(connection
->m_fd
, FIONBIO
, (char*)&arg
, sizeof(arg
));
542 ioctl(connection
->m_fd
, FIONBIO
, &arg
);
545 connection
->Notify(true);
550 void wxSocketImplUnix::Notify(bool flag
)
552 if (flag
== m_use_events
)
555 DoEnableEvents(flag
);
558 void wxSocketImplUnix::DoEnableEvents(bool flag
)
560 wxSocketManager
* const manager
= wxSocketManager::Get();
563 manager
->Install_Callback(this, wxSOCKET_INPUT
);
564 manager
->Install_Callback(this, wxSOCKET_OUTPUT
);
568 manager
->Uninstall_Callback(this, wxSOCKET_INPUT
);
569 manager
->Uninstall_Callback(this, wxSOCKET_OUTPUT
);
573 wxSocketError
wxSocketImplUnix::DoHandleConnect(int ret
)
575 /* We only call EnableEvents() if we know we aren't shutting down the socket.
576 * NB: EnableEvents() needs to be called whether the socket is blocking or
577 * non-blocking, it just shouldn't be called prior to knowing there is a
578 * connection _if_ blocking sockets are being used.
579 * If connect above returns 0, we are already connected and need to make the
580 * call to EnableEvents() now.
582 if ( m_non_blocking
|| (ret
== 0) )
587 const int err
= errno
;
589 /* If connect failed with EINPROGRESS and the wxSocketImplUnix object
590 * is in blocking mode, we select() for the specified timeout
591 * checking for writability to see if the connection request
594 if ((err
== EINPROGRESS
) && (!m_non_blocking
))
596 if (Output_Timeout() == wxSOCKET_TIMEDOUT
)
599 /* m_error is set in Output_Timeout */
600 return wxSOCKET_TIMEDOUT
;
605 SOCKOPTLEN_T len
= sizeof(error
);
607 getsockopt(m_fd
, SOL_SOCKET
, SO_ERROR
, (char*) &error
, &len
);
611 return wxSOCKET_NOERROR
;
615 /* If connect failed with EINPROGRESS and the wxSocketImplUnix object
616 * is set to nonblocking, we set m_error to wxSOCKET_WOULDBLOCK
617 * (and return wxSOCKET_WOULDBLOCK) but we don't close the socket;
618 * this way if the connection completes, a wxSOCKET_CONNECTION
619 * event will be generated, if enabled.
621 if ((err
== EINPROGRESS
) && (m_non_blocking
))
623 m_establishing
= true;
624 m_error
= wxSOCKET_WOULDBLOCK
;
625 return wxSOCKET_WOULDBLOCK
;
628 /* If connect failed with an error other than EINPROGRESS,
629 * then the call to Connect has failed.
632 m_error
= wxSOCKET_IOERR
;
634 return wxSOCKET_IOERR
;
637 return wxSOCKET_NOERROR
;
642 /* Like recv(), send(), ... */
643 int wxSocketImplUnix::Read(char *buffer
, int size
)
647 if (m_fd
== INVALID_SOCKET
|| m_server
)
649 m_error
= wxSOCKET_INVSOCK
;
653 /* Disable events during query of socket status */
654 DisableEvent(wxSOCKET_INPUT
);
656 /* If the socket is blocking, wait for data (with a timeout) */
657 if (Input_Timeout() == wxSOCKET_TIMEDOUT
) {
658 m_error
= wxSOCKET_TIMEDOUT
;
659 /* Don't return here immediately, otherwise socket events would not be
667 ret
= Recv_Stream(buffer
, size
);
669 ret
= Recv_Dgram(buffer
, size
);
672 * If recv returned zero for a TCP socket (if m_stream == NULL, it's an UDP
673 * socket and empty datagrams are possible), then the connection has been
676 * Otherwise, recv has returned an error (-1), in which case we have lost
677 * the socket only if errno does _not_ indicate that there may be more data
680 if ((ret
== 0) && m_stream
)
682 /* Make sure wxSOCKET_LOST event gets sent and shut down the socket */
685 m_detected
= wxSOCKET_LOST_FLAG
;
692 if ((errno
== EWOULDBLOCK
) || (errno
== EAGAIN
))
693 m_error
= wxSOCKET_WOULDBLOCK
;
695 m_error
= wxSOCKET_IOERR
;
699 /* Enable events again now that we are done processing */
700 EnableEvent(wxSOCKET_INPUT
);
705 int wxSocketImplUnix::Write(const char *buffer
, int size
)
709 SOCKET_DEBUG(( "Write #1, size %d\n", size
));
711 if (m_fd
== INVALID_SOCKET
|| m_server
)
713 m_error
= wxSOCKET_INVSOCK
;
717 SOCKET_DEBUG(( "Write #2, size %d\n", size
));
719 /* If the socket is blocking, wait for writability (with a timeout) */
720 if (Output_Timeout() == wxSOCKET_TIMEDOUT
)
723 SOCKET_DEBUG(( "Write #3, size %d\n", size
));
727 ret
= Send_Stream(buffer
, size
);
729 ret
= Send_Dgram(buffer
, size
);
731 SOCKET_DEBUG(( "Write #4, size %d\n", size
));
735 if ((errno
== EWOULDBLOCK
) || (errno
== EAGAIN
))
737 m_error
= wxSOCKET_WOULDBLOCK
;
738 SOCKET_DEBUG(( "Write error WOULDBLOCK\n" ));
742 m_error
= wxSOCKET_IOERR
;
743 SOCKET_DEBUG(( "Write error IOERR\n" ));
746 /* Only reenable OUTPUT events after an error (just like WSAAsyncSelect
747 * in MSW). Once the first OUTPUT event is received, users can assume
748 * that the socket is writable until a read operation fails. Only then
749 * will further OUTPUT events be posted.
751 EnableEvent(wxSOCKET_OUTPUT
);
756 SOCKET_DEBUG(( "Write #5, size %d ret %d\n", size
, ret
));
763 void wxSocketImplUnix::EnableEvent(wxSocketNotify event
)
767 m_detected
&= ~(1 << event
);
768 wxSocketManager::Get()->Install_Callback(this, event
);
772 void wxSocketImplUnix::DisableEvent(wxSocketNotify event
)
776 m_detected
|= (1 << event
);
777 wxSocketManager::Get()->Uninstall_Callback(this, event
);
782 * For blocking sockets, wait until data is available or
783 * until timeout ellapses.
785 wxSocketError
wxSocketImplUnix::Input_Timeout()
790 // Linux select() will overwrite the struct on return so make a copy
791 struct timeval tv
= m_timeout
;
796 wxFD_SET(m_fd
, &readfds
);
797 ret
= select(m_fd
+ 1, &readfds
, NULL
, NULL
, &tv
);
800 SOCKET_DEBUG(( "Input_Timeout, select returned 0\n" ));
801 m_error
= wxSOCKET_TIMEDOUT
;
802 return wxSOCKET_TIMEDOUT
;
807 SOCKET_DEBUG(( "Input_Timeout, select returned -1\n" ));
808 if (errno
== EBADF
) { SOCKET_DEBUG(( "Invalid file descriptor\n" )); }
809 if (errno
== EINTR
) { SOCKET_DEBUG(( "A non blocked signal was caught\n" )); }
810 if (errno
== EINVAL
) { SOCKET_DEBUG(( "The highest number descriptor is negative\n" )); }
811 if (errno
== ENOMEM
) { SOCKET_DEBUG(( "Not enough memory\n" )); }
812 m_error
= wxSOCKET_TIMEDOUT
;
813 return wxSOCKET_TIMEDOUT
;
817 return wxSOCKET_NOERROR
;
821 * For blocking sockets, wait until data can be sent without
822 * blocking or until timeout ellapses.
824 wxSocketError
wxSocketImplUnix::Output_Timeout()
829 // Linux select() will overwrite the struct on return so make a copy
830 struct timeval tv
= m_timeout
;
832 SOCKET_DEBUG( ("m_non_blocking has: %d\n", (int)m_non_blocking
) );
836 wxFD_ZERO(&writefds
);
837 wxFD_SET(m_fd
, &writefds
);
838 ret
= select(m_fd
+ 1, NULL
, &writefds
, NULL
, &tv
);
841 SOCKET_DEBUG(( "Output_Timeout, select returned 0\n" ));
842 m_error
= wxSOCKET_TIMEDOUT
;
843 return wxSOCKET_TIMEDOUT
;
848 SOCKET_DEBUG(( "Output_Timeout, select returned -1\n" ));
849 if (errno
== EBADF
) { SOCKET_DEBUG(( "Invalid file descriptor\n" )); }
850 if (errno
== EINTR
) { SOCKET_DEBUG(( "A non blocked signal was caught\n" )); }
851 if (errno
== EINVAL
) { SOCKET_DEBUG(( "The highest number descriptor is negative\n" )); }
852 if (errno
== ENOMEM
) { SOCKET_DEBUG(( "Not enough memory\n" )); }
853 m_error
= wxSOCKET_TIMEDOUT
;
854 return wxSOCKET_TIMEDOUT
;
857 if ( ! wxFD_ISSET(m_fd
, &writefds
) )
859 SOCKET_DEBUG(( "Output_Timeout is buggy!\n" ));
863 SOCKET_DEBUG(( "Output_Timeout seems correct\n" ));
868 SOCKET_DEBUG(( "Output_Timeout, didn't try select!\n" ));
871 return wxSOCKET_NOERROR
;
874 int wxSocketImplUnix::Recv_Stream(char *buffer
, int size
)
879 ret
= recv(m_fd
, buffer
, size
, GSOCKET_MSG_NOSIGNAL
);
881 while (ret
== -1 && errno
== EINTR
); /* Loop until not interrupted */
886 int wxSocketImplUnix::Recv_Dgram(char *buffer
, int size
)
889 WX_SOCKLEN_T fromlen
= sizeof(from
);
893 fromlen
= sizeof(from
);
897 ret
= recvfrom(m_fd
, buffer
, size
, 0, (sockaddr
*)&from
, (WX_SOCKLEN_T
*) &fromlen
);
899 while (ret
== -1 && errno
== EINTR
); /* Loop until not interrupted */
904 /* Translate a system address into a wxSocketImplUnix address */
907 m_peer
= GAddress_new();
910 m_error
= wxSOCKET_MEMERR
;
915 err
= _GAddress_translate_from(m_peer
, (sockaddr
*)&from
, fromlen
);
916 if (err
!= wxSOCKET_NOERROR
)
918 GAddress_destroy(m_peer
);
927 int wxSocketImplUnix::Send_Stream(const char *buffer
, int size
)
935 ret
= send(m_fd
, (char *)buffer
, size
, GSOCKET_MSG_NOSIGNAL
);
937 while (ret
== -1 && errno
== EINTR
); /* Loop until not interrupted */
944 int wxSocketImplUnix::Send_Dgram(const char *buffer
, int size
)
946 struct sockaddr
*addr
;
952 m_error
= wxSOCKET_INVADDR
;
956 err
= _GAddress_translate_to(m_peer
, &addr
, &len
);
957 if (err
!= wxSOCKET_NOERROR
)
967 ret
= sendto(m_fd
, (char *)buffer
, size
, 0, addr
, len
);
969 while (ret
== -1 && errno
== EINTR
); /* Loop until not interrupted */
973 /* Frees memory allocated from _GAddress_translate_to */
979 void wxSocketImplUnix::OnStateChange(wxSocketNotify event
)
982 NotifyOnStateChange(event
);
984 if ( event
== wxSOCKET_LOST
)
988 void wxSocketImplUnix::Detected_Read()
992 /* Safeguard against straggling call to Detected_Read */
993 if (m_fd
== INVALID_SOCKET
)
998 /* If we have already detected a LOST event, then don't try
999 * to do any further processing.
1001 if ((m_detected
& wxSOCKET_LOST_FLAG
) != 0)
1003 m_establishing
= false;
1005 OnStateChange(wxSOCKET_LOST
);
1009 int num
= recv(m_fd
, &c
, 1, MSG_PEEK
| GSOCKET_MSG_NOSIGNAL
);
1013 OnStateChange(wxSOCKET_INPUT
);
1017 if (m_server
&& m_stream
)
1019 OnStateChange(wxSOCKET_CONNECTION
);
1025 /* graceful shutdown */
1026 OnStateChange(wxSOCKET_LOST
);
1030 /* Empty datagram received */
1031 OnStateChange(wxSOCKET_INPUT
);
1036 /* Do not throw a lost event in cases where the socket isn't really lost */
1037 if ((errno
== EWOULDBLOCK
) || (errno
== EAGAIN
) || (errno
== EINTR
))
1039 OnStateChange(wxSOCKET_INPUT
);
1043 OnStateChange(wxSOCKET_LOST
);
1049 void wxSocketImplUnix::Detected_Write()
1051 /* If we have already detected a LOST event, then don't try
1052 * to do any further processing.
1054 if ((m_detected
& wxSOCKET_LOST_FLAG
) != 0)
1056 m_establishing
= false;
1058 OnStateChange(wxSOCKET_LOST
);
1062 if (m_establishing
&& !m_server
)
1065 SOCKOPTLEN_T len
= sizeof(error
);
1067 m_establishing
= false;
1069 getsockopt(m_fd
, SOL_SOCKET
, SO_ERROR
, (char*)&error
, &len
);
1073 OnStateChange(wxSOCKET_LOST
);
1077 OnStateChange(wxSOCKET_CONNECTION
);
1078 /* We have to fire this event by hand because CONNECTION (for clients)
1079 * and OUTPUT are internally the same and we just disabled CONNECTION
1080 * events with the above macro.
1082 OnStateChange(wxSOCKET_OUTPUT
);
1087 OnStateChange(wxSOCKET_OUTPUT
);
1092 * -------------------------------------------------------------------------
1094 * -------------------------------------------------------------------------
1097 /* CHECK_ADDRESS verifies that the current address family is either
1098 * wxSOCKET_NOFAMILY or wxSOCKET_*family*, and if it is wxSOCKET_NOFAMILY, it
1099 * initalizes it to be a wxSOCKET_*family*. In other cases, it returns
1100 * an appropiate error code.
1102 * CHECK_ADDRESS_RETVAL does the same but returning 'retval' on error.
1104 #define CHECK_ADDRESS(address, family) \
1106 if (address->m_family == wxSOCKET_NOFAMILY) \
1107 if (_GAddress_Init_##family(address) != wxSOCKET_NOERROR) \
1108 return address->m_error; \
1109 if (address->m_family != wxSOCKET_##family) \
1111 address->m_error = wxSOCKET_INVADDR; \
1112 return wxSOCKET_INVADDR; \
1116 #define CHECK_ADDRESS_RETVAL(address, family, retval) \
1118 if (address->m_family == wxSOCKET_NOFAMILY) \
1119 if (_GAddress_Init_##family(address) != wxSOCKET_NOERROR) \
1121 if (address->m_family != wxSOCKET_##family) \
1123 address->m_error = wxSOCKET_INVADDR; \
1129 GAddress
*GAddress_new(void)
1133 if ((address
= (GAddress
*) malloc(sizeof(GAddress
))) == NULL
)
1136 address
->m_family
= wxSOCKET_NOFAMILY
;
1137 address
->m_addr
= NULL
;
1143 GAddress
*GAddress_copy(GAddress
*address
)
1147 assert(address
!= NULL
);
1149 if ((addr2
= (GAddress
*) malloc(sizeof(GAddress
))) == NULL
)
1152 memcpy(addr2
, address
, sizeof(GAddress
));
1154 if (address
->m_addr
&& address
->m_len
> 0)
1156 addr2
->m_addr
= (struct sockaddr
*)malloc(addr2
->m_len
);
1157 if (addr2
->m_addr
== NULL
)
1162 memcpy(addr2
->m_addr
, address
->m_addr
, addr2
->m_len
);
1168 void GAddress_destroy(GAddress
*address
)
1170 assert(address
!= NULL
);
1172 if (address
->m_addr
)
1173 free(address
->m_addr
);
1178 void GAddress_SetFamily(GAddress
*address
, GAddressType type
)
1180 assert(address
!= NULL
);
1182 address
->m_family
= type
;
1185 GAddressType
GAddress_GetFamily(GAddress
*address
)
1187 assert(address
!= NULL
);
1189 return address
->m_family
;
1192 wxSocketError
_GAddress_translate_from(GAddress
*address
,
1193 struct sockaddr
*addr
, int len
)
1195 address
->m_realfamily
= addr
->sa_family
;
1196 switch (addr
->sa_family
)
1199 address
->m_family
= wxSOCKET_INET
;
1202 address
->m_family
= wxSOCKET_UNIX
;
1206 address
->m_family
= wxSOCKET_INET6
;
1208 #endif // wxUSE_IPV6
1211 address
->m_error
= wxSOCKET_INVOP
;
1212 return wxSOCKET_INVOP
;
1216 if (address
->m_addr
)
1217 free(address
->m_addr
);
1219 address
->m_len
= len
;
1220 address
->m_addr
= (struct sockaddr
*)malloc(len
);
1222 if (address
->m_addr
== NULL
)
1224 address
->m_error
= wxSOCKET_MEMERR
;
1225 return wxSOCKET_MEMERR
;
1228 memcpy(address
->m_addr
, addr
, len
);
1230 return wxSOCKET_NOERROR
;
1233 wxSocketError
_GAddress_translate_to(GAddress
*address
,
1234 struct sockaddr
**addr
, int *len
)
1236 if (!address
->m_addr
)
1238 address
->m_error
= wxSOCKET_INVADDR
;
1239 return wxSOCKET_INVADDR
;
1242 *len
= address
->m_len
;
1243 *addr
= (struct sockaddr
*)malloc(address
->m_len
);
1246 address
->m_error
= wxSOCKET_MEMERR
;
1247 return wxSOCKET_MEMERR
;
1250 memcpy(*addr
, address
->m_addr
, address
->m_len
);
1251 return wxSOCKET_NOERROR
;
1255 * -------------------------------------------------------------------------
1256 * Internet address family
1257 * -------------------------------------------------------------------------
1260 wxSocketError
_GAddress_Init_INET(GAddress
*address
)
1262 address
->m_len
= sizeof(struct sockaddr_in
);
1263 address
->m_addr
= (struct sockaddr
*) malloc(address
->m_len
);
1264 if (address
->m_addr
== NULL
)
1266 address
->m_error
= wxSOCKET_MEMERR
;
1267 return wxSOCKET_MEMERR
;
1270 address
->m_family
= wxSOCKET_INET
;
1271 address
->m_realfamily
= PF_INET
;
1272 ((struct sockaddr_in
*)address
->m_addr
)->sin_family
= AF_INET
;
1273 ((struct sockaddr_in
*)address
->m_addr
)->sin_addr
.s_addr
= INADDR_ANY
;
1275 return wxSOCKET_NOERROR
;
1278 wxSocketError
GAddress_INET_SetHostName(GAddress
*address
, const char *hostname
)
1281 struct in_addr
*addr
;
1283 assert(address
!= NULL
);
1285 CHECK_ADDRESS(address
, INET
);
1287 addr
= &(((struct sockaddr_in
*)address
->m_addr
)->sin_addr
);
1289 /* If it is a numeric host name, convert it now */
1290 #if defined(HAVE_INET_ATON)
1291 if (inet_aton(hostname
, addr
) == 0)
1293 #elif defined(HAVE_INET_ADDR)
1294 if ( (addr
->s_addr
= inet_addr(hostname
)) == (unsigned)-1 )
1297 /* Use gethostbyname by default */
1299 int val
= 1; /* VA doesn't like constants in conditional expressions */
1304 struct in_addr
*array_addr
;
1306 /* It is a real name, we solve it */
1308 #if defined(HAVE_FUNC_GETHOSTBYNAME_R_3)
1309 struct hostent_data buffer
;
1314 he
= wxGethostbyname_r(hostname
, &h
, (void*)&buffer
, sizeof(buffer
), &err
);
1317 /* Reset to invalid address */
1318 addr
->s_addr
= INADDR_NONE
;
1319 address
->m_error
= wxSOCKET_NOHOST
;
1320 return wxSOCKET_NOHOST
;
1323 array_addr
= (struct in_addr
*) *(he
->h_addr_list
);
1324 addr
->s_addr
= array_addr
[0].s_addr
;
1327 return wxSOCKET_NOERROR
;
1331 wxSocketError
GAddress_INET_SetBroadcastAddress(GAddress
*address
)
1333 return GAddress_INET_SetHostAddress(address
, INADDR_BROADCAST
);
1336 wxSocketError
GAddress_INET_SetAnyAddress(GAddress
*address
)
1338 return GAddress_INET_SetHostAddress(address
, INADDR_ANY
);
1341 wxSocketError
GAddress_INET_SetHostAddress(GAddress
*address
,
1342 unsigned long hostaddr
)
1344 struct in_addr
*addr
;
1346 assert(address
!= NULL
);
1348 CHECK_ADDRESS(address
, INET
);
1350 addr
= &(((struct sockaddr_in
*)address
->m_addr
)->sin_addr
);
1351 addr
->s_addr
= htonl(hostaddr
);
1353 return wxSOCKET_NOERROR
;
1356 wxSocketError
GAddress_INET_SetPortName(GAddress
*address
, const char *port
,
1357 const char *protocol
)
1360 struct sockaddr_in
*addr
;
1362 assert(address
!= NULL
);
1363 CHECK_ADDRESS(address
, INET
);
1367 address
->m_error
= wxSOCKET_INVPORT
;
1368 return wxSOCKET_INVPORT
;
1371 #if defined(HAVE_FUNC_GETSERVBYNAME_R_4)
1372 struct servent_data buffer
;
1376 struct servent serv
;
1377 se
= wxGetservbyname_r(port
, protocol
, &serv
,
1378 (void*)&buffer
, sizeof(buffer
));
1381 /* the cast to int suppresses compiler warnings about subscript having the
1383 if (isdigit((int)port
[0]))
1387 port_int
= atoi(port
);
1388 addr
= (struct sockaddr_in
*)address
->m_addr
;
1389 addr
->sin_port
= htons(port_int
);
1390 return wxSOCKET_NOERROR
;
1393 address
->m_error
= wxSOCKET_INVPORT
;
1394 return wxSOCKET_INVPORT
;
1397 addr
= (struct sockaddr_in
*)address
->m_addr
;
1398 addr
->sin_port
= se
->s_port
;
1400 return wxSOCKET_NOERROR
;
1403 wxSocketError
GAddress_INET_SetPort(GAddress
*address
, unsigned short port
)
1405 struct sockaddr_in
*addr
;
1407 assert(address
!= NULL
);
1408 CHECK_ADDRESS(address
, INET
);
1410 addr
= (struct sockaddr_in
*)address
->m_addr
;
1411 addr
->sin_port
= htons(port
);
1413 return wxSOCKET_NOERROR
;
1416 wxSocketError
GAddress_INET_GetHostName(GAddress
*address
, char *hostname
, size_t sbuf
)
1420 struct sockaddr_in
*addr
;
1422 assert(address
!= NULL
);
1423 CHECK_ADDRESS(address
, INET
);
1425 addr
= (struct sockaddr_in
*)address
->m_addr
;
1426 addr_buf
= (char *)&(addr
->sin_addr
);
1428 struct hostent temphost
;
1429 #if defined(HAVE_FUNC_GETHOSTBYNAME_R_3)
1430 struct hostent_data buffer
;
1435 he
= wxGethostbyaddr_r(addr_buf
, sizeof(addr
->sin_addr
), AF_INET
, &temphost
,
1436 (void*)&buffer
, sizeof(buffer
), &err
);
1439 address
->m_error
= wxSOCKET_NOHOST
;
1440 return wxSOCKET_NOHOST
;
1443 strncpy(hostname
, he
->h_name
, sbuf
);
1445 return wxSOCKET_NOERROR
;
1448 unsigned long GAddress_INET_GetHostAddress(GAddress
*address
)
1450 struct sockaddr_in
*addr
;
1452 assert(address
!= NULL
);
1453 CHECK_ADDRESS_RETVAL(address
, INET
, 0);
1455 addr
= (struct sockaddr_in
*)address
->m_addr
;
1457 return ntohl(addr
->sin_addr
.s_addr
);
1460 unsigned short GAddress_INET_GetPort(GAddress
*address
)
1462 struct sockaddr_in
*addr
;
1464 assert(address
!= NULL
);
1465 CHECK_ADDRESS_RETVAL(address
, INET
, 0);
1467 addr
= (struct sockaddr_in
*)address
->m_addr
;
1468 return ntohs(addr
->sin_port
);
1473 * -------------------------------------------------------------------------
1474 * Internet IPv6 address family
1475 * -------------------------------------------------------------------------
1478 wxSocketError
_GAddress_Init_INET6(GAddress
*address
)
1480 struct in6_addr any_address
= IN6ADDR_ANY_INIT
;
1481 address
->m_len
= sizeof(struct sockaddr_in6
);
1482 address
->m_addr
= (struct sockaddr
*) malloc(address
->m_len
);
1483 if (address
->m_addr
== NULL
)
1485 address
->m_error
= wxSOCKET_MEMERR
;
1486 return wxSOCKET_MEMERR
;
1488 memset(address
->m_addr
,0,address
->m_len
);
1490 address
->m_family
= wxSOCKET_INET6
;
1491 address
->m_realfamily
= AF_INET6
;
1492 ((struct sockaddr_in6
*)address
->m_addr
)->sin6_family
= AF_INET6
;
1493 ((struct sockaddr_in6
*)address
->m_addr
)->sin6_addr
= any_address
;
1495 return wxSOCKET_NOERROR
;
1498 wxSocketError
GAddress_INET6_SetHostName(GAddress
*address
, const char *hostname
)
1500 assert(address
!= NULL
);
1501 CHECK_ADDRESS(address
, INET6
);
1504 memset( & hints
, 0, sizeof( hints
) );
1505 hints
.ai_family
= AF_INET6
;
1506 addrinfo
* info
= 0;
1507 if ( getaddrinfo( hostname
, "0", & hints
, & info
) || ! info
)
1509 address
->m_error
= wxSOCKET_NOHOST
;
1510 return wxSOCKET_NOHOST
;
1513 memcpy( address
->m_addr
, info
->ai_addr
, info
->ai_addrlen
);
1514 freeaddrinfo( info
);
1515 return wxSOCKET_NOERROR
;
1518 wxSocketError
GAddress_INET6_SetAnyAddress(GAddress
*address
)
1520 assert(address
!= NULL
);
1522 CHECK_ADDRESS(address
, INET6
);
1524 struct in6_addr addr
;
1525 memset( & addr
, 0, sizeof( addr
) );
1526 return GAddress_INET6_SetHostAddress(address
, addr
);
1528 wxSocketError
GAddress_INET6_SetHostAddress(GAddress
*address
,
1529 struct in6_addr hostaddr
)
1531 assert(address
!= NULL
);
1533 CHECK_ADDRESS(address
, INET6
);
1535 ((struct sockaddr_in6
*)address
->m_addr
)->sin6_addr
= hostaddr
;
1537 return wxSOCKET_NOERROR
;
1540 wxSocketError
GAddress_INET6_SetPortName(GAddress
*address
, const char *port
,
1541 const char *protocol
)
1544 struct sockaddr_in6
*addr
;
1546 assert(address
!= NULL
);
1547 CHECK_ADDRESS(address
, INET6
);
1551 address
->m_error
= wxSOCKET_INVPORT
;
1552 return wxSOCKET_INVPORT
;
1555 se
= getservbyname(port
, protocol
);
1558 if (isdigit(port
[0]))
1562 port_int
= atoi(port
);
1563 addr
= (struct sockaddr_in6
*)address
->m_addr
;
1564 addr
->sin6_port
= htons((u_short
) port_int
);
1565 return wxSOCKET_NOERROR
;
1568 address
->m_error
= wxSOCKET_INVPORT
;
1569 return wxSOCKET_INVPORT
;
1572 addr
= (struct sockaddr_in6
*)address
->m_addr
;
1573 addr
->sin6_port
= se
->s_port
;
1575 return wxSOCKET_NOERROR
;
1578 wxSocketError
GAddress_INET6_SetPort(GAddress
*address
, unsigned short port
)
1580 struct sockaddr_in6
*addr
;
1582 assert(address
!= NULL
);
1583 CHECK_ADDRESS(address
, INET6
);
1585 addr
= (struct sockaddr_in6
*)address
->m_addr
;
1586 addr
->sin6_port
= htons(port
);
1588 return wxSOCKET_NOERROR
;
1591 wxSocketError
GAddress_INET6_GetHostName(GAddress
*address
, char *hostname
, size_t sbuf
)
1595 struct sockaddr_in6
*addr
;
1597 assert(address
!= NULL
);
1598 CHECK_ADDRESS(address
, INET6
);
1600 addr
= (struct sockaddr_in6
*)address
->m_addr
;
1601 addr_buf
= (char *)&(addr
->sin6_addr
);
1603 he
= gethostbyaddr(addr_buf
, sizeof(addr
->sin6_addr
), AF_INET6
);
1606 address
->m_error
= wxSOCKET_NOHOST
;
1607 return wxSOCKET_NOHOST
;
1610 strncpy(hostname
, he
->h_name
, sbuf
);
1612 return wxSOCKET_NOERROR
;
1615 wxSocketError
GAddress_INET6_GetHostAddress(GAddress
*address
,struct in6_addr
*hostaddr
)
1617 assert(address
!= NULL
);
1618 assert(hostaddr
!= NULL
);
1619 CHECK_ADDRESS_RETVAL(address
, INET6
, wxSOCKET_INVADDR
);
1620 *hostaddr
= ( (struct sockaddr_in6
*)address
->m_addr
)->sin6_addr
;
1621 return wxSOCKET_NOERROR
;
1624 unsigned short GAddress_INET6_GetPort(GAddress
*address
)
1626 assert(address
!= NULL
);
1627 CHECK_ADDRESS_RETVAL(address
, INET6
, 0);
1629 return ntohs( ((struct sockaddr_in6
*)address
->m_addr
)->sin6_port
);
1632 #endif // wxUSE_IPV6
1635 * -------------------------------------------------------------------------
1636 * Unix address family
1637 * -------------------------------------------------------------------------
1640 #ifndef __VISAGECPP__
1641 wxSocketError
_GAddress_Init_UNIX(GAddress
*address
)
1643 address
->m_len
= sizeof(struct sockaddr_un
);
1644 address
->m_addr
= (struct sockaddr
*)malloc(address
->m_len
);
1645 if (address
->m_addr
== NULL
)
1647 address
->m_error
= wxSOCKET_MEMERR
;
1648 return wxSOCKET_MEMERR
;
1651 address
->m_family
= wxSOCKET_UNIX
;
1652 address
->m_realfamily
= PF_UNIX
;
1653 ((struct sockaddr_un
*)address
->m_addr
)->sun_family
= AF_UNIX
;
1654 ((struct sockaddr_un
*)address
->m_addr
)->sun_path
[0] = 0;
1656 return wxSOCKET_NOERROR
;
1659 #define UNIX_SOCK_PATHLEN (sizeof(addr->sun_path)/sizeof(addr->sun_path[0]))
1661 wxSocketError
GAddress_UNIX_SetPath(GAddress
*address
, const char *path
)
1663 struct sockaddr_un
*addr
;
1665 assert(address
!= NULL
);
1667 CHECK_ADDRESS(address
, UNIX
);
1669 addr
= ((struct sockaddr_un
*)address
->m_addr
);
1670 strncpy(addr
->sun_path
, path
, UNIX_SOCK_PATHLEN
);
1671 addr
->sun_path
[UNIX_SOCK_PATHLEN
- 1] = '\0';
1673 return wxSOCKET_NOERROR
;
1676 wxSocketError
GAddress_UNIX_GetPath(GAddress
*address
, char *path
, size_t sbuf
)
1678 struct sockaddr_un
*addr
;
1680 assert(address
!= NULL
);
1681 CHECK_ADDRESS(address
, UNIX
);
1683 addr
= (struct sockaddr_un
*)address
->m_addr
;
1685 strncpy(path
, addr
->sun_path
, sbuf
);
1687 return wxSOCKET_NOERROR
;
1689 #endif /* !defined(__VISAGECPP__) */
1690 #endif /* wxUSE_SOCKETS */