]> git.saurik.com Git - wxWidgets.git/blob - src/msw/gsocket.cpp
f611abaea5531b9dc11fd7919dba709c47001c83
[wxWidgets.git] / src / msw / gsocket.cpp
1 /* -------------------------------------------------------------------------
2 * Project: wxSocketImpl (Generic Socket)
3 * Name: src/msw/gsocket.cpp
4 * Copyright: (c) Guilhem Lavaux
5 * Licence: wxWindows Licence
6 * Author: Guillermo Rodriguez Garcia <guille@iies.es>
7 * Purpose: wxSocketImpl main MSW file
8 * Licence: The wxWindows licence
9 * CVSID: $Id$
10 * -------------------------------------------------------------------------
11 */
12
13 // For compilers that support precompilation, includes "wx.h".
14 #include "wx/wxprec.h"
15
16 #ifdef __BORLANDC__
17 #pragma hdrstop
18 #endif
19
20 #ifdef _MSC_VER
21 /* RPCNOTIFICATION_ROUTINE in rasasync.h (included from winsock.h),
22 * warning: conditional expression is constant.
23 */
24 # pragma warning(disable:4115)
25 /* FD_SET,
26 * warning: named type definition in parentheses.
27 */
28 # pragma warning(disable:4127)
29 /* GAddress_UNIX_GetPath,
30 * warning: unreferenced formal parameter.
31 */
32 # pragma warning(disable:4100)
33
34 #ifdef __WXWINCE__
35 /* windows.h results in tons of warnings at max warning level */
36 # ifdef _MSC_VER
37 # pragma warning(push, 1)
38 # endif
39 # include <windows.h>
40 # ifdef _MSC_VER
41 # pragma warning(pop)
42 # pragma warning(disable:4514)
43 # endif
44 #endif
45
46 #endif /* _MSC_VER */
47
48 #if defined(__CYGWIN__)
49 //CYGWIN gives annoying warning about runtime stuff if we don't do this
50 # define USE_SYS_TYPES_FD_SET
51 # include <sys/types.h>
52 #endif
53
54 #include <winsock.h>
55
56 #include "wx/platform.h"
57
58 #if wxUSE_SOCKETS
59
60 #include "wx/private/gsocket.h"
61 #include "wx/link.h"
62
63 wxFORCE_LINK_MODULE(gsockmsw)
64
65 #ifdef __WXWINCE__
66 #ifndef isdigit
67 #define isdigit(x) (x > 47 && x < 58)
68 #endif
69 #include "wx/msw/wince/net.h"
70 #endif
71
72 #include <string.h>
73 #include <stdio.h>
74 #include <stdlib.h>
75 #include <stddef.h>
76 #include <ctype.h>
77
78 #include "wx/private/socket.h"
79
80 void wxSocketImplMSW::DoClose()
81 {
82 wxSocketManager::Get()->
83 Uninstall_Callback(this, wxSOCKET_MAX_EVENT /* unused anyhow */);
84
85 closesocket(m_fd);
86 }
87
88 /*
89 * Waits for an incoming client connection. Returns a pointer to
90 * a wxSocketImpl object, or NULL if there was an error, in which case
91 * the last error field will be updated for the calling wxSocketImpl.
92 *
93 * Error codes (set in the calling wxSocketImpl)
94 * wxSOCKET_INVSOCK - the socket is not valid or not a server.
95 * wxSOCKET_TIMEDOUT - timeout, no incoming connections.
96 * wxSOCKET_WOULDBLOCK - the call would block and the socket is nonblocking.
97 * wxSOCKET_MEMERR - couldn't allocate memory.
98 * wxSOCKET_IOERR - low-level error.
99 */
100 wxSocketImpl *wxSocketImplMSW::WaitConnection(wxSocketBase& wxsocket)
101 {
102 wxSocketImpl *connection;
103 wxSockAddr from;
104 WX_SOCKLEN_T fromlen = sizeof(from);
105 wxSocketError err;
106 u_long arg = 1;
107
108 /* Reenable CONNECTION events */
109 m_detected &= ~wxSOCKET_CONNECTION_FLAG;
110
111 /* If the socket has already been created, we exit immediately */
112 if (m_fd == INVALID_SOCKET || !m_server)
113 {
114 m_error = wxSOCKET_INVSOCK;
115 return NULL;
116 }
117
118 /* Create a wxSocketImpl object for the new connection */
119 connection = wxSocketImplMSW::Create(wxsocket);
120
121 if (!connection)
122 {
123 m_error = wxSOCKET_MEMERR;
124 return NULL;
125 }
126
127 /* Wait for a connection (with timeout) */
128 if (Input_Timeout() == wxSOCKET_TIMEDOUT)
129 {
130 delete connection;
131 /* m_error set by Input_Timeout */
132 return NULL;
133 }
134
135 connection->m_fd = accept(m_fd, (sockaddr*)&from, &fromlen);
136
137 if (connection->m_fd == INVALID_SOCKET)
138 {
139 if (WSAGetLastError() == WSAEWOULDBLOCK)
140 m_error = wxSOCKET_WOULDBLOCK;
141 else
142 m_error = wxSOCKET_IOERR;
143
144 delete connection;
145 return NULL;
146 }
147
148 /* Initialize all fields */
149 connection->m_server = false;
150 connection->m_stream = true;
151
152 /* Setup the peer address field */
153 connection->m_peer = GAddress_new();
154 if (!connection->m_peer)
155 {
156 delete connection;
157 m_error = wxSOCKET_MEMERR;
158 return NULL;
159 }
160 err = _GAddress_translate_from(connection->m_peer, (sockaddr*)&from, fromlen);
161 if (err != wxSOCKET_NOERROR)
162 {
163 GAddress_destroy(connection->m_peer);
164 delete connection;
165 m_error = err;
166 return NULL;
167 }
168
169 ioctlsocket(connection->m_fd, FIONBIO, (u_long FAR *) &arg);
170 wxSocketManager::Get()->Install_Callback(connection);
171
172 return connection;
173 }
174
175 wxSocketError wxSocketImplMSW::DoHandleConnect(int ret)
176 {
177 // TODO: review this
178 if (ret == SOCKET_ERROR)
179 {
180 int err = WSAGetLastError();
181
182 /* If connect failed with EWOULDBLOCK and the wxSocketImpl object
183 * is in blocking mode, we select() for the specified timeout
184 * checking for writability to see if the connection request
185 * completes.
186 */
187 if ((err == WSAEWOULDBLOCK) && (!m_non_blocking))
188 {
189 err = Connect_Timeout();
190
191 if (err != wxSOCKET_NOERROR)
192 {
193 Close();
194 /* m_error is set in Connect_Timeout */
195 }
196
197 return (wxSocketError) err;
198 }
199
200 /* If connect failed with EWOULDBLOCK and the wxSocketImpl object
201 * is set to nonblocking, we set m_error to wxSOCKET_WOULDBLOCK
202 * (and return wxSOCKET_WOULDBLOCK) but we don't close the socket;
203 * this way if the connection completes, a wxSOCKET_CONNECTION
204 * event will be generated, if enabled.
205 */
206 if ((err == WSAEWOULDBLOCK) && (m_non_blocking))
207 {
208 m_establishing = true;
209 m_error = wxSOCKET_WOULDBLOCK;
210 return wxSOCKET_WOULDBLOCK;
211 }
212
213 /* If connect failed with an error other than EWOULDBLOCK,
214 * then the call to Connect() has failed.
215 */
216 Close();
217 m_error = wxSOCKET_IOERR;
218 return wxSOCKET_IOERR;
219 }
220
221 return wxSOCKET_NOERROR;
222 }
223
224 /* Generic IO */
225
226 /* Like recv(), send(), ... */
227 int wxSocketImplMSW::Read(char *buffer, int size)
228 {
229 int ret;
230
231 /* Reenable INPUT events */
232 m_detected &= ~wxSOCKET_INPUT_FLAG;
233
234 if (m_fd == INVALID_SOCKET || m_server)
235 {
236 m_error = wxSOCKET_INVSOCK;
237 return -1;
238 }
239
240 /* If the socket is blocking, wait for data (with a timeout) */
241 if (Input_Timeout() == wxSOCKET_TIMEDOUT)
242 {
243 m_error = wxSOCKET_TIMEDOUT;
244 return -1;
245 }
246
247 /* Read the data */
248 if (m_stream)
249 ret = Recv_Stream(buffer, size);
250 else
251 ret = Recv_Dgram(buffer, size);
252
253 if (ret == SOCKET_ERROR)
254 {
255 if (WSAGetLastError() != WSAEWOULDBLOCK)
256 m_error = wxSOCKET_IOERR;
257 else
258 m_error = wxSOCKET_WOULDBLOCK;
259 return -1;
260 }
261
262 return ret;
263 }
264
265 int wxSocketImplMSW::Write(const char *buffer, int size)
266 {
267 int ret;
268
269 if (m_fd == INVALID_SOCKET || m_server)
270 {
271 m_error = wxSOCKET_INVSOCK;
272 return -1;
273 }
274
275 /* If the socket is blocking, wait for writability (with a timeout) */
276 if (Output_Timeout() == wxSOCKET_TIMEDOUT)
277 return -1;
278
279 /* Write the data */
280 if (m_stream)
281 ret = Send_Stream(buffer, size);
282 else
283 ret = Send_Dgram(buffer, size);
284
285 if (ret == SOCKET_ERROR)
286 {
287 if (WSAGetLastError() != WSAEWOULDBLOCK)
288 m_error = wxSOCKET_IOERR;
289 else
290 m_error = wxSOCKET_WOULDBLOCK;
291
292 /* Only reenable OUTPUT events after an error (just like WSAAsyncSelect
293 * does). Once the first OUTPUT event is received, users can assume
294 * that the socket is writable until a read operation fails. Only then
295 * will further OUTPUT events be posted.
296 */
297 m_detected &= ~wxSOCKET_OUTPUT_FLAG;
298 return -1;
299 }
300
301 return ret;
302 }
303
304 /* Internals (IO) */
305
306 /*
307 * For blocking sockets, wait until data is available or
308 * until timeout ellapses.
309 */
310 wxSocketError wxSocketImplMSW::Input_Timeout()
311 {
312 fd_set readfds;
313
314 if (!m_non_blocking)
315 {
316 FD_ZERO(&readfds);
317 FD_SET(m_fd, &readfds);
318 if (select(0, &readfds, NULL, NULL, &m_timeout) == 0)
319 {
320 m_error = wxSOCKET_TIMEDOUT;
321 return wxSOCKET_TIMEDOUT;
322 }
323 }
324 return wxSOCKET_NOERROR;
325 }
326
327 /*
328 * For blocking sockets, wait until data can be sent without
329 * blocking or until timeout ellapses.
330 */
331 wxSocketError wxSocketImplMSW::Output_Timeout()
332 {
333 fd_set writefds;
334
335 if (!m_non_blocking)
336 {
337 FD_ZERO(&writefds);
338 FD_SET(m_fd, &writefds);
339 if (select(0, NULL, &writefds, NULL, &m_timeout) == 0)
340 {
341 m_error = wxSOCKET_TIMEDOUT;
342 return wxSOCKET_TIMEDOUT;
343 }
344 }
345 return wxSOCKET_NOERROR;
346 }
347
348 /*
349 * For blocking sockets, wait until the connection is
350 * established or fails, or until timeout ellapses.
351 */
352 wxSocketError wxSocketImplMSW::Connect_Timeout()
353 {
354 fd_set writefds;
355 fd_set exceptfds;
356
357 FD_ZERO(&writefds);
358 FD_ZERO(&exceptfds);
359 FD_SET(m_fd, &writefds);
360 FD_SET(m_fd, &exceptfds);
361 if (select(0, NULL, &writefds, &exceptfds, &m_timeout) == 0)
362 {
363 m_error = wxSOCKET_TIMEDOUT;
364 return wxSOCKET_TIMEDOUT;
365 }
366 if (!FD_ISSET(m_fd, &writefds))
367 {
368 m_error = wxSOCKET_IOERR;
369 return wxSOCKET_IOERR;
370 }
371
372 return wxSOCKET_NOERROR;
373 }
374
375 int wxSocketImplMSW::Recv_Stream(char *buffer, int size)
376 {
377 return recv(m_fd, buffer, size, 0);
378 }
379
380 int wxSocketImplMSW::Recv_Dgram(char *buffer, int size)
381 {
382 wxSockAddr from;
383 WX_SOCKLEN_T fromlen = sizeof(from);
384 int ret;
385 wxSocketError err;
386
387 ret = recvfrom(m_fd, buffer, size, 0, (sockaddr*)&from, &fromlen);
388
389 if (ret == SOCKET_ERROR)
390 return SOCKET_ERROR;
391
392 /* Translate a system address into a wxSocketImpl address */
393 if (!m_peer)
394 {
395 m_peer = GAddress_new();
396 if (!m_peer)
397 {
398 m_error = wxSOCKET_MEMERR;
399 return -1;
400 }
401 }
402 err = _GAddress_translate_from(m_peer, (sockaddr*)&from, fromlen);
403 if (err != wxSOCKET_NOERROR)
404 {
405 GAddress_destroy(m_peer);
406 m_peer = NULL;
407 m_error = err;
408 return -1;
409 }
410
411 return ret;
412 }
413
414 int wxSocketImplMSW::Send_Stream(const char *buffer, int size)
415 {
416 return send(m_fd, buffer, size, 0);
417 }
418
419 int wxSocketImplMSW::Send_Dgram(const char *buffer, int size)
420 {
421 struct sockaddr *addr;
422 int len, ret;
423 wxSocketError err;
424
425 if (!m_peer)
426 {
427 m_error = wxSOCKET_INVADDR;
428 return -1;
429 }
430
431 err = _GAddress_translate_to(m_peer, &addr, &len);
432 if (err != wxSOCKET_NOERROR)
433 {
434 m_error = err;
435 return -1;
436 }
437
438 ret = sendto(m_fd, buffer, size, 0, addr, len);
439
440 /* Frees memory allocated by _GAddress_translate_to */
441 free(addr);
442
443 return ret;
444 }
445
446 /*
447 * -------------------------------------------------------------------------
448 * GAddress
449 * -------------------------------------------------------------------------
450 */
451
452 /* CHECK_ADDRESS verifies that the current address family is either
453 * wxSOCKET_NOFAMILY or wxSOCKET_*family*, and if it is wxSOCKET_NOFAMILY, it
454 * initalizes it to be a wxSOCKET_*family*. In other cases, it returns
455 * an appropiate error code.
456 *
457 * CHECK_ADDRESS_RETVAL does the same but returning 'retval' on error.
458 */
459 #define CHECK_ADDRESS(address, family) \
460 { \
461 if (address->m_family == wxSOCKET_NOFAMILY) \
462 if (_GAddress_Init_##family(address) != wxSOCKET_NOERROR) \
463 return address->m_error; \
464 if (address->m_family != wxSOCKET_##family) \
465 { \
466 address->m_error = wxSOCKET_INVADDR; \
467 return wxSOCKET_INVADDR; \
468 } \
469 }
470
471 #define CHECK_ADDRESS_RETVAL(address, family, retval) \
472 { \
473 if (address->m_family == wxSOCKET_NOFAMILY) \
474 if (_GAddress_Init_##family(address) != wxSOCKET_NOERROR) \
475 return retval; \
476 if (address->m_family != wxSOCKET_##family) \
477 { \
478 address->m_error = wxSOCKET_INVADDR; \
479 return retval; \
480 } \
481 }
482
483
484 GAddress *GAddress_new()
485 {
486 GAddress *address;
487
488 if ((address = (GAddress *) malloc(sizeof(GAddress))) == NULL)
489 return NULL;
490
491 address->m_family = wxSOCKET_NOFAMILY;
492 address->m_addr = NULL;
493 address->m_len = 0;
494
495 return address;
496 }
497
498 GAddress *GAddress_copy(GAddress *address)
499 {
500 GAddress *addr2;
501
502 if ((addr2 = (GAddress *) malloc(sizeof(GAddress))) == NULL)
503 return NULL;
504
505 memcpy(addr2, address, sizeof(GAddress));
506
507 if (address->m_addr)
508 {
509 addr2->m_addr = (struct sockaddr *) malloc(addr2->m_len);
510 if (addr2->m_addr == NULL)
511 {
512 free(addr2);
513 return NULL;
514 }
515 memcpy(addr2->m_addr, address->m_addr, addr2->m_len);
516 }
517
518 return addr2;
519 }
520
521 void GAddress_destroy(GAddress *address)
522 {
523 if (address->m_addr)
524 free(address->m_addr);
525
526 free(address);
527 }
528
529 void GAddress_SetFamily(GAddress *address, GAddressType type)
530 {
531 address->m_family = type;
532 }
533
534 GAddressType GAddress_GetFamily(GAddress *address)
535 {
536 return address->m_family;
537 }
538
539 wxSocketError _GAddress_translate_from(GAddress *address,
540 struct sockaddr *addr, int len)
541 {
542 address->m_realfamily = addr->sa_family;
543 switch (addr->sa_family)
544 {
545 case AF_INET:
546 address->m_family = wxSOCKET_INET;
547 break;
548 case AF_UNIX:
549 address->m_family = wxSOCKET_UNIX;
550 break;
551 #if wxUSE_IPV6
552 case AF_INET6:
553 address->m_family = wxSOCKET_INET6;
554 break;
555 #endif
556 default:
557 {
558 address->m_error = wxSOCKET_INVOP;
559 return wxSOCKET_INVOP;
560 }
561 }
562
563 if (address->m_addr)
564 free(address->m_addr);
565
566 address->m_len = len;
567 address->m_addr = (struct sockaddr *) malloc(len);
568
569 if (address->m_addr == NULL)
570 {
571 address->m_error = wxSOCKET_MEMERR;
572 return wxSOCKET_MEMERR;
573 }
574 memcpy(address->m_addr, addr, len);
575
576 return wxSOCKET_NOERROR;
577 }
578
579 wxSocketError _GAddress_translate_to(GAddress *address,
580 struct sockaddr **addr, int *len)
581 {
582 if (!address->m_addr)
583 {
584 address->m_error = wxSOCKET_INVADDR;
585 return wxSOCKET_INVADDR;
586 }
587
588 *len = address->m_len;
589 *addr = (struct sockaddr *) malloc(address->m_len);
590 if (*addr == NULL)
591 {
592 address->m_error = wxSOCKET_MEMERR;
593 return wxSOCKET_MEMERR;
594 }
595
596 memcpy(*addr, address->m_addr, address->m_len);
597 return wxSOCKET_NOERROR;
598 }
599
600 /*
601 * -------------------------------------------------------------------------
602 * Internet address family
603 * -------------------------------------------------------------------------
604 */
605
606 wxSocketError _GAddress_Init_INET(GAddress *address)
607 {
608 address->m_len = sizeof(struct sockaddr_in);
609 address->m_addr = (struct sockaddr *) malloc(address->m_len);
610 if (address->m_addr == NULL)
611 {
612 address->m_error = wxSOCKET_MEMERR;
613 return wxSOCKET_MEMERR;
614 }
615
616 address->m_family = wxSOCKET_INET;
617 address->m_realfamily = AF_INET;
618 ((struct sockaddr_in *)address->m_addr)->sin_family = AF_INET;
619 ((struct sockaddr_in *)address->m_addr)->sin_addr.s_addr = INADDR_ANY;
620
621 return wxSOCKET_NOERROR;
622 }
623
624 wxSocketError GAddress_INET_SetHostName(GAddress *address, const char *hostname)
625 {
626 struct hostent *he;
627 struct in_addr *addr;
628
629 CHECK_ADDRESS(address, INET);
630
631 addr = &(((struct sockaddr_in *)address->m_addr)->sin_addr);
632
633 addr->s_addr = inet_addr(hostname);
634
635 /* If it is a numeric host name, convert it now */
636 if (addr->s_addr == INADDR_NONE)
637 {
638 struct in_addr *array_addr;
639
640 /* It is a real name, we solve it */
641 if ((he = gethostbyname(hostname)) == NULL)
642 {
643 /* addr->s_addr = INADDR_NONE just done by inet_addr() above */
644 address->m_error = wxSOCKET_NOHOST;
645 return wxSOCKET_NOHOST;
646 }
647 array_addr = (struct in_addr *) *(he->h_addr_list);
648 addr->s_addr = array_addr[0].s_addr;
649 }
650 return wxSOCKET_NOERROR;
651 }
652
653 wxSocketError GAddress_INET_SetBroadcastAddress(GAddress *address)
654 {
655 return GAddress_INET_SetHostAddress(address, INADDR_BROADCAST);
656 }
657
658 wxSocketError GAddress_INET_SetAnyAddress(GAddress *address)
659 {
660 return GAddress_INET_SetHostAddress(address, INADDR_ANY);
661 }
662
663 wxSocketError GAddress_INET_SetHostAddress(GAddress *address,
664 unsigned long hostaddr)
665 {
666 struct in_addr *addr;
667
668 CHECK_ADDRESS(address, INET);
669
670 addr = &(((struct sockaddr_in *)address->m_addr)->sin_addr);
671 addr->s_addr = htonl(hostaddr);
672
673 return wxSOCKET_NOERROR;
674 }
675
676 wxSocketError GAddress_INET_SetPortName(GAddress *address, const char *port,
677 const char *protocol)
678 {
679 struct servent *se;
680 struct sockaddr_in *addr;
681
682 CHECK_ADDRESS(address, INET);
683
684 if (!port)
685 {
686 address->m_error = wxSOCKET_INVPORT;
687 return wxSOCKET_INVPORT;
688 }
689
690 se = getservbyname(port, protocol);
691 if (!se)
692 {
693 if (isdigit(port[0]))
694 {
695 int port_int;
696
697 port_int = atoi(port);
698 addr = (struct sockaddr_in *)address->m_addr;
699 addr->sin_port = htons((u_short) port_int);
700 return wxSOCKET_NOERROR;
701 }
702
703 address->m_error = wxSOCKET_INVPORT;
704 return wxSOCKET_INVPORT;
705 }
706
707 addr = (struct sockaddr_in *)address->m_addr;
708 addr->sin_port = se->s_port;
709
710 return wxSOCKET_NOERROR;
711 }
712
713 wxSocketError GAddress_INET_SetPort(GAddress *address, unsigned short port)
714 {
715 struct sockaddr_in *addr;
716
717 CHECK_ADDRESS(address, INET);
718
719 addr = (struct sockaddr_in *)address->m_addr;
720 addr->sin_port = htons(port);
721
722 return wxSOCKET_NOERROR;
723 }
724
725 wxSocketError GAddress_INET_GetHostName(GAddress *address, char *hostname, size_t sbuf)
726 {
727 struct hostent *he;
728 char *addr_buf;
729 struct sockaddr_in *addr;
730
731 CHECK_ADDRESS(address, INET);
732
733 addr = (struct sockaddr_in *)address->m_addr;
734 addr_buf = (char *)&(addr->sin_addr);
735
736 he = gethostbyaddr(addr_buf, sizeof(addr->sin_addr), AF_INET);
737 if (he == NULL)
738 {
739 address->m_error = wxSOCKET_NOHOST;
740 return wxSOCKET_NOHOST;
741 }
742
743 strncpy(hostname, he->h_name, sbuf);
744
745 return wxSOCKET_NOERROR;
746 }
747
748 unsigned long GAddress_INET_GetHostAddress(GAddress *address)
749 {
750 struct sockaddr_in *addr;
751
752 CHECK_ADDRESS_RETVAL(address, INET, 0);
753
754 addr = (struct sockaddr_in *)address->m_addr;
755
756 return ntohl(addr->sin_addr.s_addr);
757 }
758
759 unsigned short GAddress_INET_GetPort(GAddress *address)
760 {
761 struct sockaddr_in *addr;
762
763 CHECK_ADDRESS_RETVAL(address, INET, 0);
764
765 addr = (struct sockaddr_in *)address->m_addr;
766 return ntohs(addr->sin_port);
767 }
768
769
770 #if wxUSE_IPV6
771 /*
772 * -------------------------------------------------------------------------
773 * Internet IPv6 address family
774 * -------------------------------------------------------------------------
775 */
776 #include "ws2tcpip.h"
777
778 #ifdef __VISUALC__
779 #pragma comment(lib,"ws2_32")
780 #endif // __VISUALC__
781
782 wxSocketError _GAddress_Init_INET6(GAddress *address)
783 {
784 struct in6_addr any_address = IN6ADDR_ANY_INIT;
785 address->m_len = sizeof(struct sockaddr_in6);
786 address->m_addr = (struct sockaddr *) malloc(address->m_len);
787 if (address->m_addr == NULL)
788 {
789 address->m_error = wxSOCKET_MEMERR;
790 return wxSOCKET_MEMERR;
791 }
792 memset(address->m_addr,0,address->m_len);
793
794 address->m_family = wxSOCKET_INET6;
795 address->m_realfamily = AF_INET6;
796 ((struct sockaddr_in6 *)address->m_addr)->sin6_family = AF_INET6;
797 ((struct sockaddr_in6 *)address->m_addr)->sin6_addr = any_address;
798
799 return wxSOCKET_NOERROR;
800 }
801
802 wxSocketError GAddress_INET6_SetHostName(GAddress *address, const char *hostname)
803 {
804 CHECK_ADDRESS(address, INET6);
805
806 addrinfo hints;
807 memset( & hints, 0, sizeof( hints ) );
808 hints.ai_family = AF_INET6;
809 addrinfo * info = 0;
810 if ( getaddrinfo( hostname, "0", & hints, & info ) || ! info )
811 {
812 address->m_error = wxSOCKET_NOHOST;
813 return wxSOCKET_NOHOST;
814 }
815
816 memcpy( address->m_addr, info->ai_addr, info->ai_addrlen );
817 freeaddrinfo( info );
818 return wxSOCKET_NOERROR;
819 }
820
821 wxSocketError GAddress_INET6_SetAnyAddress(GAddress *address)
822 {
823 CHECK_ADDRESS(address, INET6);
824
825 struct in6_addr addr;
826 memset( & addr, 0, sizeof( addr ) );
827 return GAddress_INET6_SetHostAddress(address, addr);
828 }
829 wxSocketError GAddress_INET6_SetHostAddress(GAddress *address,
830 struct in6_addr hostaddr)
831 {
832 CHECK_ADDRESS(address, INET6);
833
834 ((struct sockaddr_in6 *)address->m_addr)->sin6_addr = hostaddr;
835
836 return wxSOCKET_NOERROR;
837 }
838
839 wxSocketError GAddress_INET6_SetPortName(GAddress *address, const char *port,
840 const char *protocol)
841 {
842 struct servent *se;
843 struct sockaddr_in6 *addr;
844
845 CHECK_ADDRESS(address, INET6);
846
847 if (!port)
848 {
849 address->m_error = wxSOCKET_INVPORT;
850 return wxSOCKET_INVPORT;
851 }
852
853 se = getservbyname(port, protocol);
854 if (!se)
855 {
856 if (isdigit((unsigned char) port[0]))
857 {
858 int port_int;
859
860 port_int = atoi(port);
861 addr = (struct sockaddr_in6 *)address->m_addr;
862 addr->sin6_port = htons((u_short) port_int);
863 return wxSOCKET_NOERROR;
864 }
865
866 address->m_error = wxSOCKET_INVPORT;
867 return wxSOCKET_INVPORT;
868 }
869
870 addr = (struct sockaddr_in6 *)address->m_addr;
871 addr->sin6_port = se->s_port;
872
873 return wxSOCKET_NOERROR;
874 }
875
876 wxSocketError GAddress_INET6_SetPort(GAddress *address, unsigned short port)
877 {
878 struct sockaddr_in6 *addr;
879
880 CHECK_ADDRESS(address, INET6);
881
882 addr = (struct sockaddr_in6 *)address->m_addr;
883 addr->sin6_port = htons(port);
884
885 return wxSOCKET_NOERROR;
886 }
887
888 wxSocketError GAddress_INET6_GetHostName(GAddress *address, char *hostname, size_t sbuf)
889 {
890 struct hostent *he;
891 char *addr_buf;
892 struct sockaddr_in6 *addr;
893
894 CHECK_ADDRESS(address, INET6);
895
896 addr = (struct sockaddr_in6 *)address->m_addr;
897 addr_buf = (char *)&(addr->sin6_addr);
898
899 he = gethostbyaddr(addr_buf, sizeof(addr->sin6_addr), AF_INET6);
900 if (he == NULL)
901 {
902 address->m_error = wxSOCKET_NOHOST;
903 return wxSOCKET_NOHOST;
904 }
905
906 strncpy(hostname, he->h_name, sbuf);
907
908 return wxSOCKET_NOERROR;
909 }
910
911 wxSocketError GAddress_INET6_GetHostAddress(GAddress *address,struct in6_addr *hostaddr)
912 {
913 CHECK_ADDRESS_RETVAL(address, INET6, wxSOCKET_INVADDR);
914 *hostaddr = ( (struct sockaddr_in6 *)address->m_addr )->sin6_addr;
915 return wxSOCKET_NOERROR;
916 }
917
918 unsigned short GAddress_INET6_GetPort(GAddress *address)
919 {
920 CHECK_ADDRESS_RETVAL(address, INET6, 0);
921
922 return ntohs( ((struct sockaddr_in6 *)address->m_addr)->sin6_port );
923 }
924
925 #endif // wxUSE_IPV6
926
927 /*
928 * -------------------------------------------------------------------------
929 * Unix address family
930 * -------------------------------------------------------------------------
931 */
932
933 wxSocketError _GAddress_Init_UNIX(GAddress *address)
934 {
935 address->m_error = wxSOCKET_INVADDR;
936 return wxSOCKET_INVADDR;
937 }
938
939 wxSocketError GAddress_UNIX_SetPath(GAddress *address, const char *WXUNUSED(path))
940 {
941 address->m_error = wxSOCKET_INVADDR;
942 return wxSOCKET_INVADDR;
943 }
944
945 wxSocketError GAddress_UNIX_GetPath(GAddress *address, char *WXUNUSED(path), size_t WXUNUSED(sbuf))
946 {
947 address->m_error = wxSOCKET_INVADDR;
948 return wxSOCKET_INVADDR;
949 }
950
951 #endif // wxUSE_SOCKETS