]> git.saurik.com Git - wxWidgets.git/blob - src/msw/gsocket.cpp
export wxSettableHeaderColumn from DLL
[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(char *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 char *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(char *buffer, int size)
382 {
383 return recv(m_fd, buffer, size, 0);
384 }
385
386 int wxSocketImplMSW::Recv_Dgram(char *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, buffer, size, 0, (sockaddr*)&from, &fromlen);
394
395 if (ret == SOCKET_ERROR)
396 return SOCKET_ERROR;
397
398 /* Translate a system address into a wxSocketImpl address */
399 if (!m_peer)
400 {
401 m_peer = GAddress_new();
402 if (!m_peer)
403 {
404 m_error = wxSOCKET_MEMERR;
405 return -1;
406 }
407 }
408 err = _GAddress_translate_from(m_peer, (sockaddr*)&from, fromlen);
409 if (err != wxSOCKET_NOERROR)
410 {
411 GAddress_destroy(m_peer);
412 m_peer = NULL;
413 m_error = err;
414 return -1;
415 }
416
417 return ret;
418 }
419
420 int wxSocketImplMSW::Send_Stream(const char *buffer, int size)
421 {
422 return send(m_fd, buffer, size, 0);
423 }
424
425 int wxSocketImplMSW::Send_Dgram(const char *buffer, int size)
426 {
427 struct sockaddr *addr;
428 int len, ret;
429 wxSocketError err;
430
431 if (!m_peer)
432 {
433 m_error = wxSOCKET_INVADDR;
434 return -1;
435 }
436
437 err = _GAddress_translate_to(m_peer, &addr, &len);
438 if (err != wxSOCKET_NOERROR)
439 {
440 m_error = err;
441 return -1;
442 }
443
444 ret = sendto(m_fd, buffer, size, 0, addr, len);
445
446 /* Frees memory allocated by _GAddress_translate_to */
447 free(addr);
448
449 return ret;
450 }
451
452 /*
453 * -------------------------------------------------------------------------
454 * GAddress
455 * -------------------------------------------------------------------------
456 */
457
458 /* CHECK_ADDRESS verifies that the current address family is either
459 * wxSOCKET_NOFAMILY or wxSOCKET_*family*, and if it is wxSOCKET_NOFAMILY, it
460 * initalizes it to be a wxSOCKET_*family*. In other cases, it returns
461 * an appropiate error code.
462 *
463 * CHECK_ADDRESS_RETVAL does the same but returning 'retval' on error.
464 */
465 #define CHECK_ADDRESS(address, family) \
466 { \
467 if (address->m_family == wxSOCKET_NOFAMILY) \
468 if (_GAddress_Init_##family(address) != wxSOCKET_NOERROR) \
469 return address->m_error; \
470 if (address->m_family != wxSOCKET_##family) \
471 { \
472 address->m_error = wxSOCKET_INVADDR; \
473 return wxSOCKET_INVADDR; \
474 } \
475 }
476
477 #define CHECK_ADDRESS_RETVAL(address, family, retval) \
478 { \
479 if (address->m_family == wxSOCKET_NOFAMILY) \
480 if (_GAddress_Init_##family(address) != wxSOCKET_NOERROR) \
481 return retval; \
482 if (address->m_family != wxSOCKET_##family) \
483 { \
484 address->m_error = wxSOCKET_INVADDR; \
485 return retval; \
486 } \
487 }
488
489
490 GAddress *GAddress_new()
491 {
492 GAddress *address;
493
494 if ((address = (GAddress *) malloc(sizeof(GAddress))) == NULL)
495 return NULL;
496
497 address->m_family = wxSOCKET_NOFAMILY;
498 address->m_addr = NULL;
499 address->m_len = 0;
500
501 return address;
502 }
503
504 GAddress *GAddress_copy(GAddress *address)
505 {
506 GAddress *addr2;
507
508 if ((addr2 = (GAddress *) malloc(sizeof(GAddress))) == NULL)
509 return NULL;
510
511 memcpy(addr2, address, sizeof(GAddress));
512
513 if (address->m_addr)
514 {
515 addr2->m_addr = (struct sockaddr *) malloc(addr2->m_len);
516 if (addr2->m_addr == NULL)
517 {
518 free(addr2);
519 return NULL;
520 }
521 memcpy(addr2->m_addr, address->m_addr, addr2->m_len);
522 }
523
524 return addr2;
525 }
526
527 void GAddress_destroy(GAddress *address)
528 {
529 if (address->m_addr)
530 free(address->m_addr);
531
532 free(address);
533 }
534
535 void GAddress_SetFamily(GAddress *address, GAddressType type)
536 {
537 address->m_family = type;
538 }
539
540 GAddressType GAddress_GetFamily(GAddress *address)
541 {
542 return address->m_family;
543 }
544
545 wxSocketError _GAddress_translate_from(GAddress *address,
546 struct sockaddr *addr, int len)
547 {
548 address->m_realfamily = addr->sa_family;
549 switch (addr->sa_family)
550 {
551 case AF_INET:
552 address->m_family = wxSOCKET_INET;
553 break;
554 case AF_UNIX:
555 address->m_family = wxSOCKET_UNIX;
556 break;
557 #if wxUSE_IPV6
558 case AF_INET6:
559 address->m_family = wxSOCKET_INET6;
560 break;
561 #endif
562 default:
563 {
564 address->m_error = wxSOCKET_INVOP;
565 return wxSOCKET_INVOP;
566 }
567 }
568
569 if (address->m_addr)
570 free(address->m_addr);
571
572 address->m_len = len;
573 address->m_addr = (struct sockaddr *) malloc(len);
574
575 if (address->m_addr == NULL)
576 {
577 address->m_error = wxSOCKET_MEMERR;
578 return wxSOCKET_MEMERR;
579 }
580 memcpy(address->m_addr, addr, len);
581
582 return wxSOCKET_NOERROR;
583 }
584
585 wxSocketError _GAddress_translate_to(GAddress *address,
586 struct sockaddr **addr, int *len)
587 {
588 if (!address->m_addr)
589 {
590 address->m_error = wxSOCKET_INVADDR;
591 return wxSOCKET_INVADDR;
592 }
593
594 *len = address->m_len;
595 *addr = (struct sockaddr *) malloc(address->m_len);
596 if (*addr == NULL)
597 {
598 address->m_error = wxSOCKET_MEMERR;
599 return wxSOCKET_MEMERR;
600 }
601
602 memcpy(*addr, address->m_addr, address->m_len);
603 return wxSOCKET_NOERROR;
604 }
605
606 /*
607 * -------------------------------------------------------------------------
608 * Internet address family
609 * -------------------------------------------------------------------------
610 */
611
612 wxSocketError _GAddress_Init_INET(GAddress *address)
613 {
614 address->m_len = sizeof(struct sockaddr_in);
615 address->m_addr = (struct sockaddr *) malloc(address->m_len);
616 if (address->m_addr == NULL)
617 {
618 address->m_error = wxSOCKET_MEMERR;
619 return wxSOCKET_MEMERR;
620 }
621
622 address->m_family = wxSOCKET_INET;
623 address->m_realfamily = AF_INET;
624 ((struct sockaddr_in *)address->m_addr)->sin_family = AF_INET;
625 ((struct sockaddr_in *)address->m_addr)->sin_addr.s_addr = INADDR_ANY;
626
627 return wxSOCKET_NOERROR;
628 }
629
630 wxSocketError GAddress_INET_SetHostName(GAddress *address, const char *hostname)
631 {
632 struct hostent *he;
633 struct in_addr *addr;
634
635 CHECK_ADDRESS(address, INET);
636
637 addr = &(((struct sockaddr_in *)address->m_addr)->sin_addr);
638
639 addr->s_addr = inet_addr(hostname);
640
641 /* If it is a numeric host name, convert it now */
642 if (addr->s_addr == INADDR_NONE)
643 {
644 struct in_addr *array_addr;
645
646 /* It is a real name, we solve it */
647 if ((he = gethostbyname(hostname)) == NULL)
648 {
649 /* addr->s_addr = INADDR_NONE just done by inet_addr() above */
650 address->m_error = wxSOCKET_NOHOST;
651 return wxSOCKET_NOHOST;
652 }
653 array_addr = (struct in_addr *) *(he->h_addr_list);
654 addr->s_addr = array_addr[0].s_addr;
655 }
656 return wxSOCKET_NOERROR;
657 }
658
659 wxSocketError GAddress_INET_SetBroadcastAddress(GAddress *address)
660 {
661 return GAddress_INET_SetHostAddress(address, INADDR_BROADCAST);
662 }
663
664 wxSocketError GAddress_INET_SetAnyAddress(GAddress *address)
665 {
666 return GAddress_INET_SetHostAddress(address, INADDR_ANY);
667 }
668
669 wxSocketError GAddress_INET_SetHostAddress(GAddress *address,
670 unsigned long hostaddr)
671 {
672 struct in_addr *addr;
673
674 CHECK_ADDRESS(address, INET);
675
676 addr = &(((struct sockaddr_in *)address->m_addr)->sin_addr);
677 addr->s_addr = htonl(hostaddr);
678
679 return wxSOCKET_NOERROR;
680 }
681
682 wxSocketError GAddress_INET_SetPortName(GAddress *address, const char *port,
683 const char *protocol)
684 {
685 struct servent *se;
686 struct sockaddr_in *addr;
687
688 CHECK_ADDRESS(address, INET);
689
690 if (!port)
691 {
692 address->m_error = wxSOCKET_INVPORT;
693 return wxSOCKET_INVPORT;
694 }
695
696 se = getservbyname(port, protocol);
697 if (!se)
698 {
699 if (isdigit(port[0]))
700 {
701 int port_int;
702
703 port_int = atoi(port);
704 addr = (struct sockaddr_in *)address->m_addr;
705 addr->sin_port = htons((u_short) port_int);
706 return wxSOCKET_NOERROR;
707 }
708
709 address->m_error = wxSOCKET_INVPORT;
710 return wxSOCKET_INVPORT;
711 }
712
713 addr = (struct sockaddr_in *)address->m_addr;
714 addr->sin_port = se->s_port;
715
716 return wxSOCKET_NOERROR;
717 }
718
719 wxSocketError GAddress_INET_SetPort(GAddress *address, unsigned short port)
720 {
721 struct sockaddr_in *addr;
722
723 CHECK_ADDRESS(address, INET);
724
725 addr = (struct sockaddr_in *)address->m_addr;
726 addr->sin_port = htons(port);
727
728 return wxSOCKET_NOERROR;
729 }
730
731 wxSocketError GAddress_INET_GetHostName(GAddress *address, char *hostname, size_t sbuf)
732 {
733 struct hostent *he;
734 char *addr_buf;
735 struct sockaddr_in *addr;
736
737 CHECK_ADDRESS(address, INET);
738
739 addr = (struct sockaddr_in *)address->m_addr;
740 addr_buf = (char *)&(addr->sin_addr);
741
742 he = gethostbyaddr(addr_buf, sizeof(addr->sin_addr), AF_INET);
743 if (he == NULL)
744 {
745 address->m_error = wxSOCKET_NOHOST;
746 return wxSOCKET_NOHOST;
747 }
748
749 strncpy(hostname, he->h_name, sbuf);
750
751 return wxSOCKET_NOERROR;
752 }
753
754 unsigned long GAddress_INET_GetHostAddress(GAddress *address)
755 {
756 struct sockaddr_in *addr;
757
758 CHECK_ADDRESS_RETVAL(address, INET, 0);
759
760 addr = (struct sockaddr_in *)address->m_addr;
761
762 return ntohl(addr->sin_addr.s_addr);
763 }
764
765 unsigned short GAddress_INET_GetPort(GAddress *address)
766 {
767 struct sockaddr_in *addr;
768
769 CHECK_ADDRESS_RETVAL(address, INET, 0);
770
771 addr = (struct sockaddr_in *)address->m_addr;
772 return ntohs(addr->sin_port);
773 }
774
775
776 #if wxUSE_IPV6
777 /*
778 * -------------------------------------------------------------------------
779 * Internet IPv6 address family
780 * -------------------------------------------------------------------------
781 */
782 #include "ws2tcpip.h"
783
784 #ifdef __VISUALC__
785 #pragma comment(lib,"ws2_32")
786 #endif // __VISUALC__
787
788 wxSocketError _GAddress_Init_INET6(GAddress *address)
789 {
790 struct in6_addr any_address = IN6ADDR_ANY_INIT;
791 address->m_len = sizeof(struct sockaddr_in6);
792 address->m_addr = (struct sockaddr *) malloc(address->m_len);
793 if (address->m_addr == NULL)
794 {
795 address->m_error = wxSOCKET_MEMERR;
796 return wxSOCKET_MEMERR;
797 }
798 memset(address->m_addr,0,address->m_len);
799
800 address->m_family = wxSOCKET_INET6;
801 address->m_realfamily = AF_INET6;
802 ((struct sockaddr_in6 *)address->m_addr)->sin6_family = AF_INET6;
803 ((struct sockaddr_in6 *)address->m_addr)->sin6_addr = any_address;
804
805 return wxSOCKET_NOERROR;
806 }
807
808 wxSocketError GAddress_INET6_SetHostName(GAddress *address, const char *hostname)
809 {
810 CHECK_ADDRESS(address, INET6);
811
812 addrinfo hints;
813 memset( & hints, 0, sizeof( hints ) );
814 hints.ai_family = AF_INET6;
815 addrinfo * info = 0;
816 if ( getaddrinfo( hostname, "0", & hints, & info ) || ! info )
817 {
818 address->m_error = wxSOCKET_NOHOST;
819 return wxSOCKET_NOHOST;
820 }
821
822 memcpy( address->m_addr, info->ai_addr, info->ai_addrlen );
823 freeaddrinfo( info );
824 return wxSOCKET_NOERROR;
825 }
826
827 wxSocketError GAddress_INET6_SetAnyAddress(GAddress *address)
828 {
829 CHECK_ADDRESS(address, INET6);
830
831 struct in6_addr addr;
832 memset( & addr, 0, sizeof( addr ) );
833 return GAddress_INET6_SetHostAddress(address, addr);
834 }
835 wxSocketError GAddress_INET6_SetHostAddress(GAddress *address,
836 struct in6_addr hostaddr)
837 {
838 CHECK_ADDRESS(address, INET6);
839
840 ((struct sockaddr_in6 *)address->m_addr)->sin6_addr = hostaddr;
841
842 return wxSOCKET_NOERROR;
843 }
844
845 wxSocketError GAddress_INET6_SetPortName(GAddress *address, const char *port,
846 const char *protocol)
847 {
848 struct servent *se;
849 struct sockaddr_in6 *addr;
850
851 CHECK_ADDRESS(address, INET6);
852
853 if (!port)
854 {
855 address->m_error = wxSOCKET_INVPORT;
856 return wxSOCKET_INVPORT;
857 }
858
859 se = getservbyname(port, protocol);
860 if (!se)
861 {
862 if (isdigit((unsigned char) port[0]))
863 {
864 int port_int;
865
866 port_int = atoi(port);
867 addr = (struct sockaddr_in6 *)address->m_addr;
868 addr->sin6_port = htons((u_short) port_int);
869 return wxSOCKET_NOERROR;
870 }
871
872 address->m_error = wxSOCKET_INVPORT;
873 return wxSOCKET_INVPORT;
874 }
875
876 addr = (struct sockaddr_in6 *)address->m_addr;
877 addr->sin6_port = se->s_port;
878
879 return wxSOCKET_NOERROR;
880 }
881
882 wxSocketError GAddress_INET6_SetPort(GAddress *address, unsigned short port)
883 {
884 struct sockaddr_in6 *addr;
885
886 CHECK_ADDRESS(address, INET6);
887
888 addr = (struct sockaddr_in6 *)address->m_addr;
889 addr->sin6_port = htons(port);
890
891 return wxSOCKET_NOERROR;
892 }
893
894 wxSocketError GAddress_INET6_GetHostName(GAddress *address, char *hostname, size_t sbuf)
895 {
896 struct hostent *he;
897 char *addr_buf;
898 struct sockaddr_in6 *addr;
899
900 CHECK_ADDRESS(address, INET6);
901
902 addr = (struct sockaddr_in6 *)address->m_addr;
903 addr_buf = (char *)&(addr->sin6_addr);
904
905 he = gethostbyaddr(addr_buf, sizeof(addr->sin6_addr), AF_INET6);
906 if (he == NULL)
907 {
908 address->m_error = wxSOCKET_NOHOST;
909 return wxSOCKET_NOHOST;
910 }
911
912 strncpy(hostname, he->h_name, sbuf);
913
914 return wxSOCKET_NOERROR;
915 }
916
917 wxSocketError GAddress_INET6_GetHostAddress(GAddress *address,struct in6_addr *hostaddr)
918 {
919 CHECK_ADDRESS_RETVAL(address, INET6, wxSOCKET_INVADDR);
920 *hostaddr = ( (struct sockaddr_in6 *)address->m_addr )->sin6_addr;
921 return wxSOCKET_NOERROR;
922 }
923
924 unsigned short GAddress_INET6_GetPort(GAddress *address)
925 {
926 CHECK_ADDRESS_RETVAL(address, INET6, 0);
927
928 return ntohs( ((struct sockaddr_in6 *)address->m_addr)->sin6_port );
929 }
930
931 #endif // wxUSE_IPV6
932
933 /*
934 * -------------------------------------------------------------------------
935 * Unix address family
936 * -------------------------------------------------------------------------
937 */
938
939 wxSocketError _GAddress_Init_UNIX(GAddress *address)
940 {
941 address->m_error = wxSOCKET_INVADDR;
942 return wxSOCKET_INVADDR;
943 }
944
945 wxSocketError GAddress_UNIX_SetPath(GAddress *address, const char *WXUNUSED(path))
946 {
947 address->m_error = wxSOCKET_INVADDR;
948 return wxSOCKET_INVADDR;
949 }
950
951 wxSocketError GAddress_UNIX_GetPath(GAddress *address, char *WXUNUSED(path), size_t WXUNUSED(sbuf))
952 {
953 address->m_error = wxSOCKET_INVADDR;
954 return wxSOCKET_INVADDR;
955 }
956
957 #endif // wxUSE_SOCKETS