1 module tango.net.device.Berkeley; 2 3 private import tango.sys.Common; 4 5 private import tango.core.Exception; 6 7 import consts=tango.sys.consts.socket; 8 9 private import tango.stdc.string : strlen; 10 private import tango.stdc.stringz; 11 12 /******************************************************************************* 13 14 *******************************************************************************/ 15 16 enum {SOCKET_ERROR = consts.SOCKET_ERROR} 17 18 /******************************************************************************* 19 20 *******************************************************************************/ 21 22 enum SocketOption 23 { 24 DEBUG = consts.SO_DEBUG , /* turn on debugging info recording */ 25 BROADCAST = consts.SO_BROADCAST , /* permit sending of broadcast msgs */ 26 REUSEADDR = consts.SO_REUSEADDR , /* allow local address reuse */ 27 LINGER = consts.SO_LINGER , /* linger on close if data present */ 28 DONTLINGER = ~(consts.SO_LINGER), 29 30 OOBINLINE = consts.SO_OOBINLINE , /* leave received OOB data in line */ 31 ACCEPTCONN = consts.SO_ACCEPTCONN, /* socket has had listen() */ 32 KEEPALIVE = consts.SO_KEEPALIVE , /* keep connections alive */ 33 DONTROUTE = consts.SO_DONTROUTE , /* just use interface addresses */ 34 TYPE = consts.SO_TYPE , /* get socket type */ 35 36 /* 37 * Additional options, not kept in so_options. 38 */ 39 SNDBUF = consts.SO_SNDBUF, /* send buffer size */ 40 RCVBUF = consts.SO_RCVBUF, /* receive buffer size */ 41 ERROR = consts.SO_ERROR , /* get error status and clear */ 42 43 // OptionLevel.IP settings 44 MULTICAST_TTL = consts.IP_MULTICAST_TTL , 45 MULTICAST_LOOP = consts.IP_MULTICAST_LOOP , 46 ADD_MEMBERSHIP = consts.IP_ADD_MEMBERSHIP , 47 DROP_MEMBERSHIP = consts.IP_DROP_MEMBERSHIP, 48 49 // OptionLevel.TCP settings 50 TCP_NODELAY = consts.TCP_NODELAY , 51 52 // Windows specifics 53 WIN_UPDATE_ACCEPT_CONTEXT = 0x700B, 54 WIN_CONNECT_TIME = 0x700C, 55 WIN_UPDATE_CONNECT_CONTEXT = 0x7010, 56 } 57 58 /******************************************************************************* 59 60 *******************************************************************************/ 61 62 enum SocketOptionLevel 63 { 64 SOCKET = consts.SOL_SOCKET , 65 IP = consts.IPPROTO_IP , 66 TCP = consts.IPPROTO_TCP , 67 UDP = consts.IPPROTO_UDP , 68 } 69 70 /******************************************************************************* 71 72 *******************************************************************************/ 73 74 enum SocketType 75 { 76 STREAM = consts.SOCK_STREAM , /++ sequential, reliable +/ 77 DGRAM = consts.SOCK_DGRAM , /++ connectionless unreliable, max length +/ 78 SEQPACKET = consts.SOCK_SEQPACKET, /++ sequential, reliable, max length +/ 79 } 80 81 /******************************************************************************* 82 83 *******************************************************************************/ 84 85 enum ProtocolType 86 { 87 IP = consts.IPPROTO_IP , /// default internet protocol (probably 4 for compatibility) 88 IPV4 = consts.IPPROTO_IP , /// internet protocol version 4 89 IPV6 = consts.IPPROTO_IPV6 , /// internet protocol version 6 90 ICMP = consts.IPPROTO_ICMP , /// internet control message protocol 91 IGMP = consts.IPPROTO_IGMP , /// internet group management protocol 92 TCP = consts.IPPROTO_TCP , /// transmission control protocol 93 PUP = consts.IPPROTO_PUP , /// PARC universal packet protocol 94 UDP = consts.IPPROTO_UDP , /// user datagram protocol 95 IDP = consts.IPPROTO_IDP , /// Xerox NS protocol 96 } 97 98 /******************************************************************************* 99 100 *******************************************************************************/ 101 102 enum AddressFamily 103 { 104 UNSPEC = consts.AF_UNSPEC , 105 UNIX = consts.AF_UNIX , 106 INET = consts.AF_INET , 107 IPX = consts.AF_IPX , 108 APPLETALK = consts.AF_APPLETALK, 109 INET6 = consts.AF_INET6 , 110 } 111 112 /******************************************************************************* 113 114 *******************************************************************************/ 115 116 enum SocketShutdown 117 { 118 RECEIVE = consts.SHUT_RD, 119 SEND = consts.SHUT_WR, 120 BOTH = consts.SHUT_RDWR, 121 } 122 123 /******************************************************************************* 124 125 *******************************************************************************/ 126 127 enum SocketFlags 128 { 129 NONE = 0, 130 OOB = consts.MSG_OOB, /// out of band 131 PEEK = consts.MSG_PEEK, /// only for receiving 132 DONTROUTE = consts.MSG_DONTROUTE, /// only for sending 133 NOSIGNAL = 0x4000, /// inhibit signals 134 } 135 136 enum AIFlags: int 137 { 138 PASSIVE = consts.AI_PASSIVE, /// get address to use bind() 139 CANONNAME = consts.AI_CANONNAME, /// fill ai_canonname 140 NUMERICHOST = consts.AI_NUMERICHOST, /// prevent host name resolution 141 NUMERICSERV = consts.AI_NUMERICSERV, /// prevent service name resolution valid 142 /// flags for addrinfo (not a standard def, 143 /// apps should not use it) 144 ALL = consts.AI_ALL, /// IPv6 and IPv4-mapped (with AI_V4MAPPED) 145 ADDRCONFIG = consts.AI_ADDRCONFIG, /// only if any address is assigned 146 V4MAPPED = consts.AI_V4MAPPED, /// accept IPv4-mapped IPv6 address special 147 /// recommended flags for getipnodebyname 148 MASK = consts.AI_MASK, 149 DEFAULT = consts.AI_DEFAULT, 150 } 151 152 enum AIError 153 { 154 BADFLAGS = consts.EAI_BADFLAGS, /// Invalid value for `ai_flags' field. 155 NONAME = consts.EAI_NONAME, /// NAME or SERVICE is unknown. 156 AGAIN = consts.EAI_AGAIN, /// Temporary failure in name resolution. 157 FAIL = consts.EAI_FAIL, /// Non-recoverable failure in name res. 158 NODATA = consts.EAI_NODATA, /// No address associated with NAME. 159 FAMILY = consts.EAI_FAMILY, /// `ai_family' not supported. 160 SOCKTYPE = consts.EAI_SOCKTYPE, /// `ai_socktype' not supported. 161 SERVICE = consts.EAI_SERVICE, /// SERVICE not supported for `ai_socktype'. 162 MEMORY = consts.EAI_MEMORY, /// Memory allocation failure. 163 } 164 165 166 enum NIFlags: int 167 { 168 MAXHOST = consts.NI_MAXHOST, 169 MAXSERV = consts.NI_MAXSERV, 170 NUMERICHOST = consts.NI_NUMERICHOST, /// Don't try to look up hostname. 171 NUMERICSERV = consts.NI_NUMERICSERV, /// Don't convert port number to name. 172 NOFQDN = consts.NI_NOFQDN, /// Only return nodename portion. 173 NAMEREQD = consts.NI_NAMEREQD, /// Don't return numeric addresses. 174 DGRAM = consts.NI_DGRAM, /// Look up UDP service rather than TCP. 175 } 176 177 178 /******************************************************************************* 179 180 conversions for network byte-order 181 182 *******************************************************************************/ 183 184 version(BigEndian) 185 { 186 private ushort htons (ushort x) 187 { 188 return x; 189 } 190 191 private uint htonl (uint x) 192 { 193 return x; 194 } 195 } 196 else 197 { 198 private import tango.core.BitManip; 199 200 private ushort htons (ushort x) 201 { 202 return cast(ushort) ((x >> 8) | (x << 8)); 203 } 204 205 private uint htonl (uint x) 206 { 207 return bswap(x); 208 } 209 } 210 211 /******************************************************************************* 212 213 214 *******************************************************************************/ 215 216 version (Win32) 217 { 218 pragma (lib, "ws2_32.lib"); 219 220 private import tango.sys.win32.WsaSock; 221 222 enum socket_t: int 223 { 224 init = ~0 225 } 226 227 package extern (Windows) 228 { 229 alias closesocket close; 230 231 socket_t socket(int af, int type, int protocol); 232 int ioctlsocket(socket_t s, int cmd, uint* argp); 233 uint inet_addr(const(char)* cp); 234 int bind(socket_t s, Address.sockaddr* name, int namelen); 235 int connect(socket_t s, Address.sockaddr* name, int namelen); 236 int listen(socket_t s, int backlog); 237 socket_t accept(socket_t s, Address.sockaddr* addr, int* addrlen); 238 int closesocket(socket_t s); 239 int shutdown(socket_t s, int how); 240 int getpeername(socket_t s, Address.sockaddr* name, int* namelen); 241 int getsockname(socket_t s, Address.sockaddr* name, int* namelen); 242 int send(socket_t s, const(void)* buf, int len, int flags); 243 int sendto(socket_t s, const(void)* buf, int len, int flags, Address.sockaddr* to, int tolen); 244 int recv(socket_t s, void* buf, int len, int flags); 245 int recvfrom(socket_t s, void* buf, int len, int flags, Address.sockaddr* from, int* fromlen); 246 int select(int nfds, SocketSet.fd* readfds, SocketSet.fd* writefds, SocketSet.fd* errorfds, SocketSet.timeval* timeout); 247 int getsockopt(socket_t s, int level, int optname, void* optval, int* optlen); 248 int setsockopt(socket_t s, int level, int optname, const(void)* optval, int optlen); 249 int gethostname(void* namebuffer, int buflen); 250 char* inet_ntoa(uint ina); 251 NetHost.hostent* gethostbyname(const(char)* name); 252 NetHost.hostent* gethostbyaddr(const(void)* addr, int len, int type); 253 /** 254 The gai_strerror function translates error codes of getaddrinfo, 255 freeaddrinfo and getnameinfo to a human readable string, suitable 256 for error reporting. (C) MAN 257 */ 258 //char* gai_strerror(int errcode); 259 260 /** 261 Given node and service, which identify an Internet host and a service, 262 getaddrinfo() returns one or more addrinfo structures, each of which 263 contains an Internet address that can be specified in a call to bind 264 or connect. The getaddrinfo() function combines the functionality 265 provided by the getservbyname and getservbyport functions into a single 266 interface, but unlike the latter functions, getaddrinfo() is reentrant 267 and allows programs to eliminate IPv4-versus-IPv6 dependencies.(C) MAN 268 */ 269 int function(const(char)* node, const(char)* service, Address.addrinfo* hints, Address.addrinfo** res) getaddrinfo; 270 271 /** 272 The freeaddrinfo() function frees the memory that was allocated for the 273 dynamically allocated linked list res. (C) MAN 274 */ 275 void function(Address.addrinfo *res) freeaddrinfo; 276 277 /** 278 The getnameinfo() function is the inverse of getaddrinfo: it converts 279 a socket address to a corresponding host and service, in a protocol- 280 independent manner. It combines the functionality of gethostbyaddr and 281 getservbyport, but unlike those functions, getaddrinfo is reentrant and 282 allows programs to eliminate IPv4-versus-IPv6 dependencies. (C) MAN 283 */ 284 int function(Address.sockaddr* sa, int salen, char* host, int hostlen, char* serv, int servlen, int flags) getnameinfo; 285 286 bool function (socket_t, uint, void*, DWORD, DWORD, DWORD, DWORD*, OVERLAPPED*) AcceptEx; 287 bool function (socket_t, HANDLE, DWORD, DWORD, OVERLAPPED*, void*, DWORD) TransmitFile; 288 bool function (socket_t, void*, int, void*, DWORD, DWORD*, OVERLAPPED*) ConnectEx; 289 290 //char* inet_ntop(int af, void *src, char *dst, int len); 291 } 292 293 private __gshared HMODULE lib; 294 295 shared static this() 296 { 297 lib = LoadLibraryA ("Ws2_32.dll"); 298 getnameinfo = cast(typeof(getnameinfo)) GetProcAddress(lib, "getnameinfo"); 299 if (!getnameinfo) 300 { 301 FreeLibrary (lib); 302 lib = LoadLibraryA ("Wship6.dll"); 303 } 304 getnameinfo = cast(typeof(getnameinfo)) GetProcAddress(lib, "getnameinfo"); 305 getaddrinfo = cast(typeof(getaddrinfo)) GetProcAddress(lib, "getaddrinfo"); 306 freeaddrinfo = cast(typeof(freeaddrinfo)) GetProcAddress(lib, "freeaddrinfo"); 307 if (!getnameinfo) 308 { 309 FreeLibrary (lib); 310 lib = null; 311 } 312 313 WSADATA wd = void; 314 if (WSAStartup (0x0202, &wd)) 315 throw new SocketException("version of socket library is too old"); 316 317 DWORD result; 318 Guid acceptG = {0xb5367df1, 0xcbac, 0x11cf, [0x95,0xca,0x00,0x80,0x5f,0x48,0xa1,0x92]}; 319 Guid connectG = {0x25a207b9, 0xddf3, 0x4660, [0x8e,0xe9,0x76,0xe5,0x8c,0x74,0x06,0x3e]}; 320 Guid transmitG = {0xb5367df0, 0xcbac, 0x11cf, [0x95,0xca,0x00,0x80,0x5f,0x48,0xa1,0x92]}; 321 322 auto s = cast(HANDLE) socket (AddressFamily.INET, SocketType.STREAM, ProtocolType.TCP); 323 assert (s != cast(HANDLE) -1); 324 325 WSAIoctl (s, SIO_GET_EXTENSION_FUNCTION_POINTER, 326 &connectG, connectG.sizeof, &ConnectEx, 327 ConnectEx.sizeof, &result, null, null); 328 329 WSAIoctl (s, SIO_GET_EXTENSION_FUNCTION_POINTER, 330 &acceptG, acceptG.sizeof, &AcceptEx, 331 AcceptEx.sizeof, &result, null, null); 332 333 WSAIoctl (s, SIO_GET_EXTENSION_FUNCTION_POINTER, 334 &transmitG, transmitG.sizeof, &TransmitFile, 335 TransmitFile.sizeof, &result, null, null); 336 closesocket (cast(socket_t)(cast(int)s)); 337 } 338 339 shared static ~this() 340 { 341 if (lib) 342 FreeLibrary (lib); 343 WSACleanup(); 344 } 345 } 346 else 347 { 348 private import tango.stdc.errno; 349 350 //private alias int socket_t = -1; 351 enum socket_t: int 352 { 353 init = -1 354 } 355 356 package extern (C) 357 { 358 socket_t socket(int af, int type, int protocol); 359 int fcntl(socket_t s, int f, ...); 360 uint inet_addr(const(char)* cp); 361 int bind(socket_t s, const(Address.sockaddr)* name, int namelen); 362 int connect(socket_t s, const(Address.sockaddr)* name, int namelen); 363 int listen(socket_t s, int backlog); 364 socket_t accept(socket_t s, Address.sockaddr* addr, int* addrlen); 365 int close(socket_t s); 366 int shutdown(socket_t s, int how); 367 int getpeername(socket_t s, Address.sockaddr* name, int* namelen); 368 int getsockname(socket_t s, Address.sockaddr* name, int* namelen); 369 int send(socket_t s, const(void)* buf, size_t len, int flags); 370 int sendto(socket_t s, const(void)* buf, size_t len, int flags, Address.sockaddr* to, int tolen); 371 int recv(socket_t s, void* buf, size_t len, int flags); 372 int recvfrom(socket_t s, void* buf, size_t len, int flags, Address.sockaddr* from, int* fromlen); 373 int select(int nfds, SocketSet.fd* readfds, SocketSet.fd* writefds, SocketSet.fd* errorfds, SocketSet.timeval* timeout); 374 int getsockopt(socket_t s, int level, int optname, void* optval, int* optlen); 375 int setsockopt(socket_t s, int level, int optname, const(void)* optval, int optlen); 376 int gethostname(void* namebuffer, int buflen); 377 char* inet_ntoa(uint ina); 378 NetHost.hostent* gethostbyname(const(char)* name); 379 NetHost.hostent* gethostbyaddr(const(void)* addr, int len, int type); 380 381 /** 382 Given node and service, which identify an Internet host and a service, 383 getaddrinfo() returns one or more addrinfo structures, each of which 384 contains an Internet address that can be specified in a call to bind or 385 connect. The getaddrinfo() function combines the functionality provided 386 by the getservbyname and getservbyport functions into a single interface, 387 but unlike the latter functions, getaddrinfo() is reentrant and allows 388 programs to eliminate IPv4-versus-IPv6 dependencies. (C) MAN 389 */ 390 int getaddrinfo(const(char)* node, const(char)* service, Address.addrinfo* hints, Address.addrinfo** res); 391 392 /** 393 The freeaddrinfo() function frees the memory that was allocated for the 394 dynamically allocated linked list res. (C) MAN 395 */ 396 void freeaddrinfo(Address.addrinfo *res); 397 398 /** 399 The getnameinfo() function is the inverse of getaddrinfo: it converts a socket 400 address to a corresponding host and service, in a protocol-independent manner. 401 It combines the functionality of gethostbyaddr and getservbyport, but unlike 402 those functions, getaddrinfo is reentrant and allows programs to eliminate 403 IPv4-versus-IPv6 dependencies. (C) MAN 404 */ 405 int getnameinfo(Address.sockaddr* sa, int salen, char* host, int hostlen, char* serv, int servlen, int flags); 406 407 /** 408 The gai_strerror function translates error codes of getaddrinfo, freeaddrinfo 409 and getnameinfo to a human readable string, suitable for error reporting. (C) MAN 410 */ 411 const(char)* gai_strerror(int errcode); 412 413 const(char)* inet_ntop(int af, const(void) *src, char *dst, int len); 414 } 415 } 416 417 418 /******************************************************************************* 419 420 *******************************************************************************/ 421 422 public struct Berkeley 423 { 424 socket_t sock; 425 SocketType type; 426 AddressFamily family; 427 ProtocolType protocol; 428 version (Windows) 429 bool synchronous; 430 431 enum INVALID_SOCKET = socket_t.init; 432 433 enum 434 { 435 Error = -1 436 } 437 438 alias Error ERROR; // backward compatibility 439 alias noDelay setNoDelay; // backward compatibility 440 alias addressReuse setAddressReuse; // backward compatibility 441 442 443 /*********************************************************************** 444 445 Configure this instance 446 447 ***********************************************************************/ 448 449 void open (AddressFamily family, SocketType type, ProtocolType protocol, bool create=true) 450 { 451 this.type = type; 452 this.family = family; 453 this.protocol = protocol; 454 if (create) 455 reopen(); 456 } 457 458 /*********************************************************************** 459 460 Open/reopen a native socket for this instance 461 462 ***********************************************************************/ 463 464 void reopen (socket_t sock = sock.init) 465 { 466 if (this.sock != sock.init) 467 this.detach(); 468 469 if (sock is sock.init) 470 { 471 sock = cast(socket_t) socket (family, type, protocol); 472 if (sock is sock.init) 473 exception ("Unable to create socket: "); 474 } 475 476 this.sock = sock; 477 } 478 479 /*********************************************************************** 480 481 calling shutdown() before this is recommended for connection- 482 oriented sockets 483 484 ***********************************************************************/ 485 486 void detach () 487 { 488 if (sock != sock.init) 489 .close (sock); 490 sock = sock.init; 491 } 492 493 /*********************************************************************** 494 495 Return the underlying OS handle of this Conduit 496 497 ***********************************************************************/ 498 499 @property const socket_t handle () 500 { 501 return sock; 502 } 503 504 /*********************************************************************** 505 506 Return socket error status 507 508 ***********************************************************************/ 509 510 @property const int error () 511 { 512 int errcode; 513 getOption (SocketOptionLevel.SOCKET, SocketOption.ERROR, (&errcode)[0..1]); 514 return errcode; 515 } 516 517 /*********************************************************************** 518 519 Return the last error 520 521 ***********************************************************************/ 522 523 @property static int lastError () 524 { 525 version (Win32) 526 return WSAGetLastError(); 527 else 528 return errno; 529 } 530 531 /*********************************************************************** 532 533 Is this socket still alive? A closed socket is considered to 534 be dead, but a shutdown socket is still alive. 535 536 ***********************************************************************/ 537 538 @property const bool isAlive () 539 { 540 int type, typesize = type.sizeof; 541 return getsockopt (sock, SocketOptionLevel.SOCKET, 542 SocketOption.TYPE, cast(char*) &type, 543 &typesize) != Error; 544 } 545 546 /*********************************************************************** 547 548 ***********************************************************************/ 549 550 @property AddressFamily addressFamily () 551 { 552 return family; 553 } 554 555 /*********************************************************************** 556 557 ***********************************************************************/ 558 559 Berkeley* bind (Address addr) 560 { 561 if(Error == .bind (sock, addr.name, addr.nameLen)) 562 exception ("Unable to bind socket: "); 563 return &this; 564 } 565 566 /*********************************************************************** 567 568 ***********************************************************************/ 569 570 Berkeley* connect (Address to) 571 { 572 if (Error == .connect (sock, to.name, to.nameLen)) 573 { 574 if (! blocking) 575 { 576 auto err = lastError; 577 version (Windows) 578 { 579 if (err is WSAEWOULDBLOCK) 580 return &this; 581 } 582 else 583 { 584 if (err is EINPROGRESS) 585 return &this; 586 } 587 } 588 exception ("Unable to connect socket: "); 589 } 590 return &this; 591 } 592 593 /*********************************************************************** 594 595 need to bind() first 596 597 ***********************************************************************/ 598 599 Berkeley* listen (int backlog) 600 { 601 if (Error == .listen (sock, backlog)) 602 exception ("Unable to listen on socket: "); 603 return &this; 604 } 605 606 /*********************************************************************** 607 608 need to bind() first 609 610 ***********************************************************************/ 611 612 void accept (ref Berkeley target) 613 { 614 auto newsock = .accept (sock, null, null); 615 if (socket_t.init is newsock) 616 exception ("Unable to accept socket connection: "); 617 618 target.reopen (newsock); 619 target.protocol = protocol; //same protocol 620 target.family = family; //same family 621 target.type = type; //same type 622 } 623 624 /*********************************************************************** 625 626 The shutdown function shuts down the connection of the socket. 627 Depending on the argument value, it will: 628 629 - stop receiving data for this socket. If further data 630 arrives, it is rejected. 631 632 - stop trying to transmit data from this socket. Also 633 discards any data waiting to be sent. Stop looking for 634 acknowledgement of data already sent; don't retransmit 635 if any data is lost. 636 637 ***********************************************************************/ 638 639 Berkeley* shutdown (SocketShutdown how) 640 { 641 .shutdown (sock, how); 642 return &this; 643 } 644 645 /*********************************************************************** 646 647 set linger timeout 648 649 ***********************************************************************/ 650 651 @property Berkeley* linger (int period) 652 { 653 version (Win32) 654 alias ushort attr; 655 else 656 alias uint attr; 657 658 union linger 659 { 660 struct { 661 attr l_onoff; // option on/off 662 attr l_linger; // linger time 663 }; 664 attr[2] array; // combined 665 } 666 667 linger l; 668 l.l_onoff = 1; // option on/off 669 l.l_linger = cast(ushort) period; // linger time 670 671 return setOption (SocketOptionLevel.SOCKET, SocketOption.LINGER, l.array); 672 } 673 674 /*********************************************************************** 675 676 enable/disable address reuse 677 678 ***********************************************************************/ 679 680 @property Berkeley* addressReuse (bool enabled) 681 { 682 int[1] x = enabled; 683 return setOption (SocketOptionLevel.SOCKET, SocketOption.REUSEADDR, x); 684 } 685 686 /*********************************************************************** 687 688 enable/disable noDelay option (nagle) 689 690 ***********************************************************************/ 691 692 @property Berkeley* noDelay (bool enabled) 693 { 694 int[1] x = enabled; 695 return setOption (SocketOptionLevel.TCP, SocketOption.TCP_NODELAY, x); 696 } 697 698 /*********************************************************************** 699 700 Helper function to handle the adding and dropping of group 701 membership. 702 703 ***********************************************************************/ 704 705 void joinGroup (IPv4Address address, bool onOff) 706 { 707 assert (address, "Socket.joinGroup :: invalid null address"); 708 709 struct ip_mreq 710 { 711 uint imr_multiaddr; /* IP multicast address of group */ 712 uint imr_interface; /* local IP address of interface */ 713 } 714 715 ip_mreq mrq; 716 717 auto option = (onOff) ? SocketOption.ADD_MEMBERSHIP : SocketOption.DROP_MEMBERSHIP; 718 mrq.imr_interface = 0; 719 mrq.imr_multiaddr = address.sin.sin_addr; 720 721 if (.setsockopt(sock, SocketOptionLevel.IP, option, &mrq, mrq.sizeof) == Error) 722 exception ("Unable to perform multicast join: "); 723 } 724 725 /*********************************************************************** 726 727 ***********************************************************************/ 728 729 const Address newFamilyObject () 730 { 731 if (family is AddressFamily.INET) 732 return new IPv4Address; 733 if (family is AddressFamily.INET6) 734 return new IPv6Address; 735 return new UnknownAddress; 736 } 737 738 /*********************************************************************** 739 740 return the hostname 741 742 ***********************************************************************/ 743 744 @property static char[] hostName () 745 { 746 char[64] name; 747 748 if(Error == .gethostname (name.ptr, name.length)) 749 exception ("Unable to obtain host name: "); 750 return name [0 .. strlen(name.ptr)].dup; 751 } 752 753 /*********************************************************************** 754 755 return the default host address (IPv4) 756 757 ***********************************************************************/ 758 759 @property static uint hostAddress () 760 { 761 auto ih = new NetHost; 762 ih.getHostByName (hostName); 763 assert (ih.addrList.length); 764 return ih.addrList[0]; 765 } 766 767 /*********************************************************************** 768 769 return the remote address of the current connection (IPv4) 770 771 ***********************************************************************/ 772 773 @property const Address remoteAddress () 774 { 775 auto addr = newFamilyObject(); 776 auto nameLen = addr.nameLen; 777 if(Error == .getpeername (sock, addr.name, &nameLen)) 778 exception ("Unable to obtain remote socket address: "); 779 assert (addr.addressFamily is family); 780 return addr; 781 } 782 783 /*********************************************************************** 784 785 return the local address of the current connection (IPv4) 786 787 ***********************************************************************/ 788 789 @property const Address localAddress () 790 { 791 auto addr = newFamilyObject(); 792 auto nameLen = addr.nameLen; 793 if(Error == .getsockname (sock, addr.name, &nameLen)) 794 exception ("Unable to obtain local socket address: "); 795 assert (addr.addressFamily is family); 796 return addr; 797 } 798 799 /*********************************************************************** 800 801 Send data on the connection. Returns the number of bytes 802 actually sent, or ERROR on failure. If the socket is blocking 803 and there is no buffer space left, send waits. 804 805 Returns number of bytes actually sent, or -1 on error 806 807 ***********************************************************************/ 808 809 const int send (const(void)[] buf, SocketFlags flags=SocketFlags.NONE) 810 { 811 if (buf.length is 0) 812 return 0; 813 814 version (Posix) 815 { 816 auto ret = .send (sock, buf.ptr, buf.length, 817 SocketFlags.NOSIGNAL + cast(int) flags); 818 if (errno is EPIPE) 819 ret = -1; 820 return ret; 821 } 822 else 823 return .send (sock, buf.ptr, buf.length, cast(int) flags); 824 } 825 826 /*********************************************************************** 827 828 Send data to a specific destination Address. If the 829 destination address is not specified, a connection 830 must have been made and that address is used. If the 831 socket is blocking and there is no buffer space left, 832 sendTo waits. 833 834 ***********************************************************************/ 835 836 const int sendTo (const(void)[] buf, SocketFlags flags, Address to) 837 { 838 return sendTo (buf, cast(int) flags, to.name, to.nameLen); 839 } 840 841 /*********************************************************************** 842 843 ditto 844 845 ***********************************************************************/ 846 847 const int sendTo (const(void)[] buf, Address to) 848 { 849 return sendTo (buf, SocketFlags.NONE, to); 850 } 851 852 /*********************************************************************** 853 854 ditto - assumes you connect()ed 855 856 ***********************************************************************/ 857 858 const int sendTo (const(void)[] buf, SocketFlags flags=SocketFlags.NONE) 859 { 860 return sendTo (buf, cast(int) flags, null, 0); 861 } 862 863 /*********************************************************************** 864 865 Send data to a specific destination Address. If the 866 destination address is not specified, a connection 867 must have been made and that address is used. If the 868 socket is blocking and there is no buffer space left, 869 sendTo waits. 870 871 ***********************************************************************/ 872 873 private const int sendTo (const(void)[] buf, int flags, Address.sockaddr* to, int len) 874 { 875 if (buf.length is 0) 876 return 0; 877 878 version (Posix) 879 { 880 auto ret = .sendto (sock, buf.ptr, buf.length, 881 flags | SocketFlags.NOSIGNAL, to, len); 882 if (errno is EPIPE) 883 ret = -1; 884 return ret; 885 } 886 else 887 return .sendto (sock, buf.ptr, buf.length, flags, to, len); 888 } 889 890 /*********************************************************************** 891 Receive data on the connection. Returns the number of 892 bytes actually received, 0 if the remote side has closed 893 the connection, or ERROR on failure. If the socket is blocking, 894 receive waits until there is data to be received. 895 896 Returns number of bytes actually received, 0 on connection 897 closure, or -1 on error 898 899 ***********************************************************************/ 900 901 const int receive (void[] buf, SocketFlags flags=SocketFlags.NONE) 902 { 903 if (!buf.length) 904 badArg ("Socket.receive :: target buffer has 0 length"); 905 906 return .recv(sock, buf.ptr, buf.length, cast(int)flags); 907 } 908 909 /*********************************************************************** 910 911 Receive data and get the remote endpoint Address. Returns 912 the number of bytes actually received, 0 if the remote side 913 has closed the connection, or ERROR on failure. If the socket 914 is blocking, receiveFrom waits until there is data to be 915 received. 916 917 ***********************************************************************/ 918 919 const int receiveFrom (void[] buf, SocketFlags flags, Address from) 920 { 921 if (!buf.length) 922 badArg ("Socket.receiveFrom :: target buffer has 0 length"); 923 924 assert(from.addressFamily() == family); 925 int nameLen = from.nameLen(); 926 return .recvfrom(sock, buf.ptr, buf.length, cast(int)flags, from.name(), &nameLen); 927 } 928 929 /*********************************************************************** 930 931 ditto 932 933 ***********************************************************************/ 934 935 const int receiveFrom (void[] buf, Address from) 936 { 937 return receiveFrom(buf, SocketFlags.NONE, from); 938 } 939 940 /*********************************************************************** 941 942 ditto - assumes you connect()ed 943 944 ***********************************************************************/ 945 946 const int receiveFrom (void[] buf, SocketFlags flags = SocketFlags.NONE) 947 { 948 if (!buf.length) 949 badArg ("Socket.receiveFrom :: target buffer has 0 length"); 950 951 return .recvfrom(sock, buf.ptr, buf.length, cast(int)flags, null, null); 952 } 953 954 /*********************************************************************** 955 956 returns the length, in bytes, of the actual result - very 957 different from getsockopt() 958 959 ***********************************************************************/ 960 961 const int getOption (SocketOptionLevel level, SocketOption option, void[] result) 962 { 963 int len = cast(int) result.length; 964 if(Error == .getsockopt (sock, cast(int)level, cast(int)option, result.ptr, &len)) 965 exception ("Unable to get socket option: "); 966 return len; 967 } 968 969 /*********************************************************************** 970 971 ***********************************************************************/ 972 973 Berkeley* setOption (SocketOptionLevel level, SocketOption option, const(void)[] value) 974 { 975 if(Error == .setsockopt (sock, cast(int)level, cast(int)option, value.ptr, cast(int) value.length)) 976 exception ("Unable to set socket option: "); 977 return &this; 978 } 979 980 /*********************************************************************** 981 982 getter 983 984 ***********************************************************************/ 985 986 @property const bool blocking() 987 { 988 version (Windows) 989 return synchronous; 990 else 991 return !(fcntl(sock, F_GETFL, 0) & O_NONBLOCK); 992 } 993 994 /*********************************************************************** 995 996 setter 997 998 ***********************************************************************/ 999 1000 @property void blocking(bool yes) 1001 { 1002 version (Windows) 1003 { 1004 uint num = !yes; 1005 if(ioctlsocket(sock, consts.FIONBIO, &num) is ERROR) 1006 exception("Unable to set socket blocking: "); 1007 synchronous = yes; 1008 } 1009 else 1010 { 1011 int x = fcntl(sock, F_GETFL, 0); 1012 if(yes) 1013 x &= ~O_NONBLOCK; 1014 else 1015 x |= O_NONBLOCK; 1016 if(fcntl(sock, F_SETFL, x) is ERROR) 1017 exception("Unable to set socket blocking: "); 1018 } 1019 return; 1020 } 1021 1022 /*********************************************************************** 1023 1024 ***********************************************************************/ 1025 1026 static void exception (immutable(char)[] msg) 1027 { 1028 throw new SocketException (msg ~ SysError.lookup(lastError).idup); 1029 } 1030 1031 /*********************************************************************** 1032 1033 ***********************************************************************/ 1034 1035 protected static void badArg (immutable(char)[] msg) 1036 { 1037 throw new IllegalArgumentException (msg); 1038 } 1039 } 1040 1041 1042 1043 /******************************************************************************* 1044 1045 1046 *******************************************************************************/ 1047 1048 public abstract class Address 1049 { 1050 public struct sockaddr 1051 { 1052 ushort sa_family; 1053 char[14] sa_data = 0; 1054 } 1055 1056 struct addrinfo 1057 { 1058 int ai_flags; 1059 int ai_family; 1060 int ai_socktype; 1061 int ai_protocol; 1062 uint ai_addrlen; 1063 version (FreeBSD) 1064 { 1065 char* ai_canonname; 1066 sockaddr* ai_addr; 1067 } 1068 else 1069 { 1070 sockaddr* ai_addr; 1071 char* ai_canonname; 1072 } 1073 addrinfo* ai_next; 1074 } 1075 1076 @property abstract sockaddr* name(); 1077 @property abstract const int nameLen(); 1078 1079 /*********************************************************************** 1080 1081 Internal usage 1082 1083 ***********************************************************************/ 1084 1085 private static ushort ntohs (ushort x) 1086 { 1087 return htons(x); 1088 } 1089 1090 /*********************************************************************** 1091 1092 Internal usage 1093 1094 ***********************************************************************/ 1095 1096 private static uint ntohl (uint x) 1097 { 1098 return htonl(x); 1099 } 1100 1101 /*********************************************************************** 1102 1103 Internal usage 1104 1105 ***********************************************************************/ 1106 1107 private static char[] fromInt (char[] tmp, int i) 1108 { 1109 size_t j = tmp.length; 1110 do { 1111 tmp[--j] = cast(char)(i % 10 + '0'); 1112 } while (i /= 10); 1113 return tmp [j .. $]; 1114 } 1115 1116 /*********************************************************************** 1117 1118 Internal usage 1119 1120 ***********************************************************************/ 1121 1122 private static int toInt (const(char)[] s) 1123 { 1124 uint value; 1125 1126 foreach (c; s) 1127 if (c >= '0' && c <= '9') 1128 value = value * 10 + (c - '0'); 1129 else 1130 break; 1131 return value; 1132 } 1133 1134 /*********************************************************************** 1135 1136 Tango: added this common function 1137 1138 ***********************************************************************/ 1139 1140 static void exception (immutable(char)[] msg) 1141 { 1142 throw new SocketException (msg); 1143 } 1144 1145 /*********************************************************************** 1146 1147 Address factory 1148 1149 ***********************************************************************/ 1150 1151 static Address create (sockaddr* sa) 1152 { 1153 switch (sa.sa_family) 1154 { 1155 case AddressFamily.INET: 1156 return new IPv4Address(sa); 1157 case AddressFamily.INET6: 1158 return new IPv6Address(sa); 1159 default: 1160 return null; 1161 } 1162 } 1163 1164 /*********************************************************************** 1165 1166 ***********************************************************************/ 1167 1168 static Address resolve (const(char)[] host, const(char)[] service = null, 1169 AddressFamily af = AddressFamily.UNSPEC, 1170 AIFlags flags = cast(AIFlags)0) 1171 { 1172 return resolveAll (host, service, af, flags)[0]; 1173 } 1174 1175 /*********************************************************************** 1176 1177 ***********************************************************************/ 1178 1179 static Address resolve (const(char)[] host, ushort port, 1180 AddressFamily af = AddressFamily.UNSPEC, 1181 AIFlags flags = cast(AIFlags)0) 1182 { 1183 return resolveAll (host, port, af, flags)[0]; 1184 } 1185 1186 /*********************************************************************** 1187 1188 ***********************************************************************/ 1189 1190 static Address[] resolveAll (const(char)[] host, const(char)[] service = null, 1191 AddressFamily af = AddressFamily.UNSPEC, 1192 AIFlags flags = cast(AIFlags)0) 1193 { 1194 Address[] retVal; 1195 version (Win32) 1196 { 1197 if (!getaddrinfo) 1198 { // *old* windows, let's fall back to NetHost 1199 uint port = toInt(service); 1200 if (flags & AIFlags.PASSIVE && host is null) 1201 return [new IPv4Address(0, cast(ushort)port)]; 1202 1203 auto nh = new NetHost; 1204 if (!nh.getHostByName(host)) 1205 throw new AddressException("couldn't resolve " ~ host.idup); 1206 1207 retVal.length = nh.addrList.length; 1208 foreach (i, addr; nh.addrList) 1209 retVal[i] = new IPv4Address(addr, cast(ushort)port); 1210 return retVal; 1211 } 1212 } 1213 1214 addrinfo* info; 1215 addrinfo hints; 1216 hints.ai_flags = flags; 1217 hints.ai_family = (flags & AIFlags.PASSIVE && af == AddressFamily.UNSPEC) ? AddressFamily.INET6 : af; 1218 hints.ai_socktype = SocketType.STREAM; 1219 int error = getaddrinfo(toStringz(host), service.length == 0 ? null : toStringz(service), &hints, &info); 1220 if (error != 0) 1221 throw new AddressException("couldn't resolve " ~ host.idup); 1222 1223 retVal.length = 16; 1224 retVal.length = 0; 1225 while (info) 1226 { 1227 if (auto addr = create(info.ai_addr)) 1228 retVal ~= addr; 1229 info = info.ai_next; 1230 } 1231 freeaddrinfo (info); 1232 return retVal; 1233 } 1234 1235 /*********************************************************************** 1236 1237 ***********************************************************************/ 1238 1239 static Address[] resolveAll (const(char)[] host, ushort port, 1240 AddressFamily af = AddressFamily.UNSPEC, 1241 AIFlags flags = cast(AIFlags)0) 1242 { 1243 char[16] buf; 1244 return resolveAll (host, fromInt(buf, port), af, flags); 1245 } 1246 1247 /*********************************************************************** 1248 1249 ***********************************************************************/ 1250 1251 static Address passive (const(char)[] service, 1252 AddressFamily af = AddressFamily.UNSPEC, 1253 AIFlags flags = cast(AIFlags)0) 1254 { 1255 return resolve (null, service, af, flags | AIFlags.PASSIVE); 1256 } 1257 1258 /*********************************************************************** 1259 1260 ***********************************************************************/ 1261 1262 static Address passive (ushort port, AddressFamily af = AddressFamily.UNSPEC, 1263 AIFlags flags = cast(AIFlags)0) 1264 { 1265 return resolve (null, port, af, flags | AIFlags.PASSIVE); 1266 } 1267 1268 /*********************************************************************** 1269 1270 ***********************************************************************/ 1271 1272 @property char[] toAddrString() 1273 { 1274 char[1025] host = void; 1275 // Getting name info. Don't look up hostname, returns 1276 // numeric name. (NIFlags.NUMERICHOST) 1277 getnameinfo (name, nameLen, host.ptr, host.length, null, 0, NIFlags.NUMERICHOST); 1278 return fromStringz (host.ptr).dup; 1279 } 1280 1281 /*********************************************************************** 1282 1283 ***********************************************************************/ 1284 1285 @property char[] toPortString() 1286 { 1287 char[32] service = void; 1288 // Getting name info. Returns port number, not 1289 // service name. (NIFlags.NUMERICSERV) 1290 getnameinfo (name, nameLen, null, 0, service.ptr, service.length, NIFlags.NUMERICSERV); 1291 foreach (i, c; service) 1292 if (c == '\0') 1293 return service[0..i].dup; 1294 return null; 1295 } 1296 1297 /*********************************************************************** 1298 1299 ***********************************************************************/ 1300 1301 override string toString() 1302 { 1303 return toAddrString.idup ~ ":" ~ toPortString.idup; 1304 } 1305 1306 /*********************************************************************** 1307 1308 ***********************************************************************/ 1309 1310 @property AddressFamily addressFamily() 1311 { 1312 return cast(AddressFamily)name.sa_family; 1313 } 1314 } 1315 1316 1317 /******************************************************************************* 1318 1319 *******************************************************************************/ 1320 1321 public class UnknownAddress : Address 1322 { 1323 sockaddr sa; 1324 1325 /*********************************************************************** 1326 1327 ***********************************************************************/ 1328 1329 @property override sockaddr* name() 1330 { 1331 return &sa; 1332 } 1333 1334 /*********************************************************************** 1335 1336 ***********************************************************************/ 1337 1338 @property override const int nameLen() 1339 { 1340 return sa.sizeof; 1341 } 1342 1343 /*********************************************************************** 1344 1345 ***********************************************************************/ 1346 1347 @property override AddressFamily addressFamily() 1348 { 1349 return cast(AddressFamily) sa.sa_family; 1350 } 1351 1352 /*********************************************************************** 1353 1354 ***********************************************************************/ 1355 1356 override string toString() 1357 { 1358 return "Unknown"; 1359 } 1360 } 1361 1362 1363 /******************************************************************************* 1364 1365 1366 *******************************************************************************/ 1367 1368 public class IPv4Address : Address 1369 { 1370 /*********************************************************************** 1371 1372 ***********************************************************************/ 1373 1374 enum 1375 { 1376 ADDR_ANY = 0, 1377 ADDR_NONE = cast(uint)-1, 1378 PORT_ANY = 0 1379 } 1380 1381 /*********************************************************************** 1382 1383 ***********************************************************************/ 1384 1385 struct sockaddr_in 1386 { 1387 version (FreeBSD) 1388 { 1389 ubyte sin_len; 1390 ubyte sinfamily = AddressFamily.INET; 1391 } 1392 else 1393 { 1394 ushort sinfamily = AddressFamily.INET; 1395 } 1396 ushort sin_port; 1397 uint sin_addr; //in_addr 1398 char[8] sin_zero = 0; 1399 } 1400 1401 static assert(sockaddr_in.sizeof is 16); 1402 1403 private sockaddr_in sin; 1404 1405 /*********************************************************************** 1406 1407 ***********************************************************************/ 1408 1409 protected this () 1410 { 1411 } 1412 1413 /*********************************************************************** 1414 1415 ***********************************************************************/ 1416 1417 this (ushort port) 1418 { 1419 sin.sin_addr = 0; //any, "0.0.0.0" 1420 sin.sin_port = htons(port); 1421 } 1422 1423 /*********************************************************************** 1424 1425 ***********************************************************************/ 1426 1427 this (uint addr, ushort port) 1428 { 1429 sin.sin_addr = htonl(addr); 1430 sin.sin_port = htons(port); 1431 } 1432 1433 /*********************************************************************** 1434 1435 -port- can be PORT_ANY 1436 -addr- is an IP address or host name 1437 1438 ***********************************************************************/ 1439 1440 this (const(char)[] addr, ushort port = PORT_ANY) 1441 { 1442 uint uiaddr = parse(addr); 1443 if (ADDR_NONE == uiaddr) 1444 { 1445 auto ih = new NetHost; 1446 if (!ih.getHostByName(addr)) 1447 { 1448 char[16] tmp = void; 1449 exception ("Unable to resolve "~addr.idup~":"~fromInt(tmp, port).idup); 1450 } 1451 uiaddr = ih.addrList[0]; 1452 } 1453 sin.sin_addr = htonl(uiaddr); 1454 sin.sin_port = htons(port); 1455 } 1456 1457 /*********************************************************************** 1458 1459 ***********************************************************************/ 1460 1461 this (sockaddr* addr) 1462 { 1463 sin = *(cast(sockaddr_in*)addr); 1464 } 1465 1466 /*********************************************************************** 1467 1468 ***********************************************************************/ 1469 1470 @property override sockaddr* name() 1471 { 1472 return cast(sockaddr*)&sin; 1473 } 1474 1475 /*********************************************************************** 1476 1477 ***********************************************************************/ 1478 1479 @property override const int nameLen() 1480 { 1481 return cast(int)sin.sizeof; 1482 } 1483 1484 /*********************************************************************** 1485 1486 ***********************************************************************/ 1487 1488 @property override AddressFamily addressFamily() 1489 { 1490 return AddressFamily.INET; 1491 } 1492 1493 /*********************************************************************** 1494 1495 ***********************************************************************/ 1496 1497 @property const ushort port() 1498 { 1499 return ntohs(sin.sin_port); 1500 } 1501 1502 /*********************************************************************** 1503 1504 ***********************************************************************/ 1505 1506 @property const uint addr() 1507 { 1508 return ntohl(sin.sin_addr); 1509 } 1510 1511 /*********************************************************************** 1512 1513 ***********************************************************************/ 1514 1515 @property override const char[] toAddrString() 1516 { 1517 char[16] buff = 0; 1518 version (Windows) 1519 return fromStringz(inet_ntoa(sin.sin_addr)).dup; 1520 else 1521 return fromStringz(inet_ntop(AddressFamily.INET, &sin.sin_addr, buff.ptr, 16)).dup; 1522 } 1523 1524 /*********************************************************************** 1525 1526 ***********************************************************************/ 1527 1528 @property override const char[] toPortString() 1529 { 1530 char[8] _port; 1531 return fromInt (_port, port()).dup; 1532 } 1533 1534 /*********************************************************************** 1535 1536 ***********************************************************************/ 1537 1538 override string toString() 1539 { 1540 return toAddrString().idup ~ ":" ~ toPortString().idup; 1541 } 1542 1543 /*********************************************************************** 1544 1545 -addr- is an IP address in the format "a.b.c.d" 1546 returns ADDR_NONE on failure 1547 1548 ***********************************************************************/ 1549 1550 static uint parse(const(char)[] addr) 1551 { 1552 char[64] tmp; 1553 1554 synchronized (IPv4Address.classinfo) 1555 return ntohl(inet_addr(toStringz(addr, tmp))); 1556 } 1557 } 1558 1559 /******************************************************************************* 1560 1561 *******************************************************************************/ 1562 1563 debug(UnitTest) 1564 { 1565 unittest 1566 { 1567 IPv4Address ia = new IPv4Address("63.105.9.61", 80); 1568 assert(ia.toString() == "63.105.9.61:80"); 1569 } 1570 } 1571 1572 /******************************************************************************* 1573 1574 IPv6 is the next-generation Internet Protocol version 1575 designated as the successor to IPv4, the first 1576 implementation used in the Internet that is still in 1577 dominant use currently. 1578 1579 More information: http://ipv6.com/ 1580 1581 IPv6 supports 128-bit address space as opposed to 32-bit 1582 address space of IPv4. 1583 1584 IPv6 is written as 8 blocks of 4 octal digits (16 bit) 1585 separated by a colon (":"). Zero block can be replaced by "::". 1586 1587 For example: 1588 --- 1589 0000:0000:0000:0000:0000:0000:0000:0001 1590 is equal 1591 ::0001 1592 is equal 1593 ::1 1594 is analogue IPv4 127.0.0.1 1595 1596 0000:0000:0000:0000:0000:0000:0000:0000 1597 is equal 1598 :: 1599 is analogue IPv4 0.0.0.0 1600 1601 2001:cdba:0000:0000:0000:0000:3257:9652 1602 is equal 1603 2001:cdba::3257:9652 1604 1605 IPv4 address can be submitted through IPv6 as ::ffff:xx.xx.xx.xx, 1606 where xx.xx.xx.xx 32-bit IPv4 addresses. 1607 1608 ::ffff:51b0:ec6d 1609 is equal 1610 ::ffff:81.176.236.109 1611 is analogue IPv4 81.176.236.109 1612 1613 The URL for the IPv6 address will be of the form: 1614 http://[2001:cdba:0000:0000:0000:0000:3257:9652]/ 1615 1616 If needed to specify a port, it will be listed after the 1617 closing square bracket followed by a colon. 1618 1619 http://[2001:cdba:0000:0000:0000:0000:3257:9652]:8080/ 1620 address: "2001:cdba:0000:0000:0000:0000:3257:9652" 1621 port: 8080 1622 1623 IPv6Address can be used as well as IPv4Address. 1624 1625 scope addr = new IPv6Address(8080); 1626 address: "::" 1627 port: 8080 1628 1629 scope addr_2 = new IPv6Address("::1", 8081); 1630 address: "::1" 1631 port: 8081 1632 1633 scope addr_3 = new IPv6Address("::1"); 1634 address: "::1" 1635 port: PORT_ANY 1636 1637 Also in the IPv6Address constructor can specify the service name 1638 or port as string 1639 1640 scope addr_3 = new IPv6Address("::", "ssh"); 1641 address: "::" 1642 port: 22 (ssh service port) 1643 1644 scope addr_4 = new IPv6Address("::", "8080"); 1645 address: "::" 1646 port: 8080 1647 --- 1648 1649 *******************************************************************************/ 1650 1651 class IPv6Address : Address 1652 { 1653 protected: 1654 /*********************************************************************** 1655 1656 ***********************************************************************/ 1657 1658 struct sockaddr_in6 1659 { 1660 ushort sin_family; 1661 ushort sin_port; 1662 1663 uint sin6_flowinfo; 1664 ubyte[16] sin6_addr; 1665 uint sin6_scope_id; 1666 } 1667 1668 sockaddr_in6 sin; 1669 1670 /*********************************************************************** 1671 1672 ***********************************************************************/ 1673 1674 this () 1675 { 1676 } 1677 1678 /*********************************************************************** 1679 1680 ***********************************************************************/ 1681 1682 this (sockaddr* sa) 1683 { 1684 sin = *cast(sockaddr_in6*)sa; 1685 } 1686 1687 /*********************************************************************** 1688 1689 ***********************************************************************/ 1690 1691 @property override sockaddr* name() 1692 { 1693 return cast(sockaddr*)&sin; 1694 } 1695 1696 /*********************************************************************** 1697 1698 ***********************************************************************/ 1699 1700 @property override const int nameLen() 1701 { 1702 return cast(int)sin.sizeof; 1703 } 1704 1705 public: 1706 1707 /*********************************************************************** 1708 1709 ***********************************************************************/ 1710 1711 @property override AddressFamily addressFamily() 1712 { 1713 return AddressFamily.INET6; 1714 } 1715 1716 1717 enum ushort PORT_ANY = 0; 1718 1719 /*********************************************************************** 1720 1721 ***********************************************************************/ 1722 1723 @property const ushort port() 1724 { 1725 return ntohs(sin.sin_port); 1726 } 1727 1728 /*********************************************************************** 1729 1730 Create IPv6Address with zero address 1731 1732 ***********************************************************************/ 1733 1734 this (int port) 1735 { 1736 this ("::", port); 1737 } 1738 1739 /*********************************************************************** 1740 1741 -port- can be PORT_ANY 1742 -addr- is an IP address or host name 1743 1744 ***********************************************************************/ 1745 1746 this (const(char)[] addr, int port = PORT_ANY) 1747 { 1748 version (Win32) 1749 { 1750 if (!getaddrinfo) 1751 exception ("This platform does not support IPv6."); 1752 } 1753 addrinfo* info; 1754 addrinfo hints; 1755 hints.ai_family = AddressFamily.INET6; 1756 int error = getaddrinfo((addr ~ '\0').ptr, null, &hints, &info); 1757 if (error != 0) 1758 exception("failed to create IPv6Address: "); 1759 1760 sin = *cast(sockaddr_in6*)(info.ai_addr); 1761 sin.sin_port = htons(cast(ushort) port); 1762 } 1763 1764 /*********************************************************************** 1765 1766 -service- can be a port number or service name 1767 -addr- is an IP address or host name 1768 1769 ***********************************************************************/ 1770 1771 this (const(char)[] addr, const(char)[] service) 1772 { 1773 version (Win32) 1774 { 1775 if(! getaddrinfo) 1776 exception ("This platform does not support IPv6."); 1777 } 1778 addrinfo* info; 1779 addrinfo hints; 1780 hints.ai_family = AddressFamily.INET6; 1781 int error = getaddrinfo((addr ~ '\0').ptr, (service ~ '\0').ptr, &hints, &info); 1782 if (error != 0) 1783 exception ("failed to create IPv6Address: "); 1784 sin = *cast(sockaddr_in6*)(info.ai_addr); 1785 } 1786 1787 /*********************************************************************** 1788 1789 ***********************************************************************/ 1790 1791 @property ubyte[] addr() 1792 { 1793 return sin.sin6_addr; 1794 } 1795 1796 /*********************************************************************** 1797 1798 ***********************************************************************/ 1799 1800 version (Posix) 1801 @property override const char[] toAddrString() 1802 { 1803 1804 char[100] buff = 0; 1805 return fromStringz(inet_ntop(AddressFamily.INET6, &sin.sin6_addr, buff.ptr, 100)).dup; 1806 } 1807 1808 /*********************************************************************** 1809 1810 ***********************************************************************/ 1811 1812 @property override const char[] toPortString() 1813 { 1814 char[8] _port; 1815 return fromInt (_port, port()).dup; 1816 } 1817 1818 /*********************************************************************** 1819 1820 ***********************************************************************/ 1821 1822 override string toString() 1823 { 1824 return "[" ~ toAddrString.idup ~ "]:" ~ toPortString.idup; 1825 } 1826 } 1827 1828 /******************************************************************************* 1829 1830 *******************************************************************************/ 1831 1832 debug(UnitTest) 1833 { 1834 unittest 1835 { 1836 IPv6Address ia = new IPv6Address("7628:0d18:11a3:09d7:1f34:8a2e:07a0:765d", 8080); 1837 assert(ia.toString() == "[7628:d18:11a3:9d7:1f34:8a2e:7a0:765d]:8080"); 1838 //assert(ia.toString() == "[7628:0d18:11a3:09d7:1f34:8a2e:07a0:765d]:8080"); 1839 } 1840 } 1841 1842 1843 /******************************************************************************* 1844 1845 1846 *******************************************************************************/ 1847 1848 public class NetHost 1849 { 1850 const(char)[] name; 1851 const(char)[][] aliases; 1852 uint[] addrList; 1853 1854 /*********************************************************************** 1855 1856 ***********************************************************************/ 1857 1858 struct hostent 1859 { 1860 const(char)* h_name; 1861 const(char)** h_aliases; 1862 version (Win32) 1863 { 1864 short h_addrtype; 1865 short h_length; 1866 } 1867 else 1868 { 1869 int h_addrtype; 1870 int h_length; 1871 } 1872 const(char)** h_addr_list; 1873 1874 const(char)* h_addr() 1875 { 1876 return h_addr_list[0]; 1877 } 1878 } 1879 1880 /*********************************************************************** 1881 1882 ***********************************************************************/ 1883 1884 protected void validHostent(hostent* he) 1885 { 1886 if (he.h_addrtype != AddressFamily.INET || he.h_length != 4) 1887 throw new SocketException("Address family mismatch."); 1888 } 1889 1890 /*********************************************************************** 1891 1892 ***********************************************************************/ 1893 1894 void populate (hostent* he) 1895 { 1896 int i; 1897 const(char)* p; 1898 1899 name = fromStringz(he.h_name); 1900 1901 for (i = 0;; i++) 1902 { 1903 p = he.h_aliases[i]; 1904 if(!p) 1905 break; 1906 } 1907 1908 if (i) 1909 { 1910 aliases = new const(char)[][i]; 1911 for (i = 0; i != aliases.length; i++) 1912 aliases[i] = fromStringz(he.h_aliases[i]); 1913 } 1914 else 1915 aliases = null; 1916 1917 for (i = 0;; i++) 1918 { 1919 p = he.h_addr_list[i]; 1920 if(!p) 1921 break; 1922 } 1923 1924 if (i) 1925 { 1926 addrList = new uint[i]; 1927 for (i = 0; i != addrList.length; i++) 1928 addrList[i] = Address.ntohl(*(cast(uint*)he.h_addr_list[i])); 1929 } 1930 else 1931 addrList = null; 1932 } 1933 1934 /*********************************************************************** 1935 1936 ***********************************************************************/ 1937 1938 bool getHostByName(const(char)[] name) 1939 { 1940 char[1024] tmp; 1941 1942 synchronized (NetHost.classinfo) 1943 { 1944 auto he = gethostbyname(toStringz(name, tmp)); 1945 if(!he) 1946 return false; 1947 validHostent(he); 1948 populate(he); 1949 } 1950 return true; 1951 } 1952 1953 /*********************************************************************** 1954 1955 ***********************************************************************/ 1956 1957 bool getHostByAddr(uint addr) 1958 { 1959 uint x = htonl(addr); 1960 synchronized (NetHost.classinfo) 1961 { 1962 auto he = gethostbyaddr(&x, 4, cast(int)AddressFamily.INET); 1963 if(!he) 1964 return false; 1965 validHostent(he); 1966 populate(he); 1967 } 1968 return true; 1969 } 1970 1971 /*********************************************************************** 1972 1973 ***********************************************************************/ 1974 1975 //shortcut 1976 bool getHostByAddr(const(char)[] addr) 1977 { 1978 char[64] tmp; 1979 1980 synchronized (NetHost.classinfo) 1981 { 1982 uint x = inet_addr(toStringz(addr, tmp)); 1983 auto he = gethostbyaddr(&x, 4, cast(int)AddressFamily.INET); 1984 if(!he) 1985 return false; 1986 validHostent(he); 1987 populate(he); 1988 } 1989 return true; 1990 } 1991 } 1992 1993 1994 /******************************************************************************* 1995 1996 *******************************************************************************/ 1997 1998 debug (UnitTest) 1999 { 2000 import tango.io.Stdout; 2001 unittest 2002 { 2003 NetHost ih = new NetHost; 2004 ih.getHostByName(Berkeley.hostName()); 2005 assert(ih.addrList.length > 0); 2006 IPv4Address ia = new IPv4Address(ih.addrList[0], IPv4Address.PORT_ANY); 2007 Stdout.formatln("addrses: {} {}\n", ia.toAddrString, ih.name); 2008 Stdout.formatln("IP address = {}\nname = {}\n", ia.toAddrString(), ih.name); 2009 foreach(int i, const(char)[] s; ih.aliases) 2010 { 2011 Stdout.formatln("aliases[%d] = {}\n", i, s); 2012 } 2013 2014 Stdout("---\n"); 2015 2016 assert(ih.getHostByAddr(ih.addrList[0])); 2017 Stdout.formatln("name = {}\n", ih.name); 2018 foreach(int i, const(char)[] s; ih.aliases) 2019 { 2020 Stdout.formatln("aliases[{}] = {}\n", i, s); 2021 } 2022 } 2023 } 2024 2025 2026 /******************************************************************************* 2027 2028 a set of sockets for Berkeley.select() 2029 2030 *******************************************************************************/ 2031 2032 public class SocketSet 2033 { 2034 import tango.stdc.config; 2035 2036 struct timeval 2037 { 2038 c_long seconds, microseconds; 2039 } 2040 2041 private size_t nbytes; //Win32: excludes uint.size "count" 2042 private byte* buf; 2043 2044 struct fd {} 2045 2046 version(Windows) 2047 { 2048 @property uint count() 2049 { 2050 return *(cast(uint*)buf); 2051 } 2052 2053 @property void count(int setter) 2054 { 2055 *(cast(uint*)buf) = setter; 2056 } 2057 2058 2059 @property socket_t* first() 2060 { 2061 return cast(socket_t*)(buf + uint.sizeof); 2062 } 2063 } 2064 else version (Posix) 2065 { 2066 import tango.core.BitManip; 2067 2068 size_t nfdbits; 2069 socket_t _maxfd = cast(socket_t)0; 2070 2071 const uint fdelt(socket_t s) 2072 { 2073 return cast(uint)(s / nfdbits); 2074 } 2075 2076 2077 const uint fdmask(socket_t s) 2078 { 2079 return 1 << cast(uint)(s % nfdbits); 2080 } 2081 2082 2083 @property uint* first() 2084 { 2085 return cast(uint*)buf; 2086 } 2087 2088 @property public socket_t maxfd() 2089 { 2090 return _maxfd; 2091 } 2092 } 2093 2094 2095 public: 2096 2097 this (uint max) 2098 { 2099 version(Win32) 2100 { 2101 nbytes = max * socket_t.sizeof; 2102 buf = (new byte[nbytes + uint.sizeof]).ptr; 2103 count = 0; 2104 } 2105 else version (Posix) 2106 { 2107 if (max <= 32) 2108 nbytes = 32 * uint.sizeof; 2109 else 2110 nbytes = max * uint.sizeof; 2111 2112 buf = (new byte[nbytes]).ptr; 2113 nfdbits = nbytes * 8; 2114 //clear(); //new initializes to 0 2115 } 2116 else 2117 { 2118 static assert(0); 2119 } 2120 } 2121 2122 this (SocketSet o) 2123 { 2124 nbytes = o.nbytes; 2125 auto size = nbytes; 2126 version (Win32) 2127 size += uint.sizeof; 2128 2129 version (Posix) 2130 { 2131 nfdbits = o.nfdbits; 2132 _maxfd = o._maxfd; 2133 } 2134 2135 auto b = new byte[size]; 2136 b[] = o.buf[0..size]; 2137 buf = b.ptr; 2138 } 2139 2140 this() 2141 { 2142 version(Win32) 2143 { 2144 this(64); 2145 } 2146 else version (Posix) 2147 { 2148 this(32); 2149 } 2150 else 2151 { 2152 static assert(0); 2153 } 2154 } 2155 2156 SocketSet dup() 2157 { 2158 return new SocketSet (this); 2159 } 2160 2161 SocketSet reset() 2162 { 2163 version(Win32) 2164 { 2165 count = 0; 2166 } 2167 else version (Posix) 2168 { 2169 buf[0 .. nbytes] = 0; 2170 _maxfd = cast(socket_t)0; 2171 } 2172 else 2173 { 2174 static assert(0); 2175 } 2176 return this; 2177 } 2178 2179 void add(socket_t s) 2180 in 2181 { 2182 version(Win32) 2183 { 2184 assert(count < max); //added too many sockets; specify a higher max in the constructor 2185 } 2186 } 2187 body 2188 { 2189 version(Win32) 2190 { 2191 uint c = count; 2192 first[c] = s; 2193 count = c + 1; 2194 } 2195 else version (Posix) 2196 { 2197 if (s > _maxfd) 2198 _maxfd = s; 2199 2200 bts(cast(size_t*)&first[fdelt(s)], cast(size_t)s % nfdbits); 2201 } 2202 else 2203 { 2204 static assert(0); 2205 } 2206 } 2207 2208 void add(Berkeley* s) 2209 { 2210 add(s.handle); 2211 } 2212 2213 void remove(socket_t s) 2214 { 2215 version(Win32) 2216 { 2217 uint c = count; 2218 socket_t* start = first; 2219 socket_t* stop = start + c; 2220 2221 for(; start != stop; start++) 2222 { 2223 if(*start == s) 2224 goto found; 2225 } 2226 return; //not found 2227 2228 found: 2229 for(++start; start != stop; start++) 2230 { 2231 *(start - 1) = *start; 2232 } 2233 2234 count = c - 1; 2235 } 2236 else version (Posix) 2237 { 2238 btr(cast(size_t*)&first[fdelt(s)], cast(size_t)s % nfdbits); 2239 2240 // If we're removing the biggest file descriptor we've 2241 // entered so far we need to recalculate this value 2242 // for the socket set. 2243 if (s == _maxfd) 2244 { 2245 while (--_maxfd >= 0) 2246 { 2247 if (isSet(_maxfd)) 2248 { 2249 break; 2250 } 2251 } 2252 } 2253 } 2254 else 2255 { 2256 static assert(0); 2257 } 2258 } 2259 2260 void remove(Berkeley* s) 2261 { 2262 remove(s.handle); 2263 } 2264 2265 int isSet(socket_t s) 2266 { 2267 version(Win32) 2268 { 2269 socket_t* start = first; 2270 socket_t* stop = start + count; 2271 2272 for(; start != stop; start++) 2273 { 2274 if(*start == s) 2275 return true; 2276 } 2277 return false; 2278 } 2279 else version (Posix) 2280 { 2281 //return bt(cast(uint*)&first[fdelt(s)], cast(uint)s % nfdbits); 2282 int index = cast(int)(cast(uint)s % nfdbits); 2283 return (cast(uint*)&first[fdelt(s)])[index / (uint.sizeof*8)] & (1 << (index & ((uint.sizeof*8) - 1))); 2284 } 2285 else 2286 { 2287 static assert(0); 2288 } 2289 } 2290 2291 int isSet(Berkeley* s) 2292 { 2293 return isSet(s.handle); 2294 } 2295 2296 @property const size_t max() 2297 { 2298 return nbytes / socket_t.sizeof; 2299 } 2300 2301 fd* toFd_set() 2302 { 2303 return cast(fd*)buf; 2304 } 2305 2306 /*********************************************************************** 2307 2308 SocketSet's are updated to include only those sockets which an 2309 event occured. 2310 2311 Returns the number of events, 0 on timeout, or -1 on error 2312 2313 for a connect()ing socket, writeability means connected 2314 for a listen()ing socket, readability means listening 2315 2316 Winsock: possibly internally limited to 64 sockets per set 2317 2318 ***********************************************************************/ 2319 2320 static int select (SocketSet checkRead, SocketSet checkWrite, SocketSet checkError, timeval* tv) 2321 { 2322 fd* fr, fw, fe; 2323 2324 //make sure none of the SocketSet's are the same object 2325 if (checkRead) 2326 { 2327 assert(checkRead !is checkWrite); 2328 assert(checkRead !is checkError); 2329 } 2330 2331 if (checkWrite) 2332 assert(checkWrite !is checkError); 2333 2334 version(Win32) 2335 { 2336 //Windows has a problem with empty fd_set's that aren't null 2337 fr = (checkRead && checkRead.count()) ? checkRead.toFd_set() : null; 2338 fw = (checkWrite && checkWrite.count()) ? checkWrite.toFd_set() : null; 2339 fe = (checkError && checkError.count()) ? checkError.toFd_set() : null; 2340 } 2341 else 2342 { 2343 fr = checkRead ? checkRead.toFd_set() : null; 2344 fw = checkWrite ? checkWrite.toFd_set() : null; 2345 fe = checkError ? checkError.toFd_set() : null; 2346 } 2347 2348 int result; 2349 2350 version(Win32) 2351 { 2352 while ((result = .select (socket_t.max - 1, fr, fw, fe, tv)) == -1) 2353 { 2354 if(WSAGetLastError() != WSAEINTR) 2355 break; 2356 } 2357 } 2358 else version (Posix) 2359 { 2360 socket_t maxfd = cast(socket_t)0; 2361 2362 if (checkRead) 2363 maxfd = checkRead.maxfd; 2364 2365 if (checkWrite && checkWrite.maxfd > maxfd) 2366 maxfd = checkWrite.maxfd; 2367 2368 if (checkError && checkError.maxfd > maxfd) 2369 maxfd = checkError.maxfd; 2370 2371 while ((result = .select (maxfd + 1, fr, fw, fe, tv)) == -1) 2372 { 2373 if(errno() != EINTR) 2374 break; 2375 } 2376 } 2377 else 2378 { 2379 static assert(0); 2380 } 2381 2382 return result; 2383 } 2384 2385 /*********************************************************************** 2386 2387 select with specified timeout 2388 2389 ***********************************************************************/ 2390 2391 static int select (SocketSet checkRead, SocketSet checkWrite, SocketSet checkError, long microseconds) 2392 { 2393 timeval tv = { 2394 cast(typeof(timeval.seconds)) (microseconds / 1000000), 2395 cast(typeof(timeval.microseconds)) (microseconds % 1000000) 2396 }; 2397 return select (checkRead, checkWrite, checkError, &tv); 2398 } 2399 2400 /*********************************************************************** 2401 2402 select with maximum timeout 2403 2404 ***********************************************************************/ 2405 2406 static int select (SocketSet checkRead, SocketSet checkWrite, SocketSet checkError) 2407 { 2408 return select (checkRead, checkWrite, checkError, null); 2409 } 2410 } 2411 2412