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