PageRenderTime 60ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 1ms

/socket.d

https://bitbucket.org/repeatedly/scrap
D | 2692 lines | 1609 code | 504 blank | 579 comment | 217 complexity | 429721dd73b4366c5bc5c43bf1f63ec5 MD5 | raw file

Large files files are truncated, but you can click here to view the full file

  1. // Written in the D programming language
  2. /**
  3. * Authors: Masahiro Nakagawa
  4. *
  5. * Macros:
  6. * WIKI=Phobos/StdSocket
  7. */
  8. module scrap.socket;
  9. import core.memory; // GC
  10. import core.stdc.errno; // errno
  11. import core.stdc.stdlib; // alloca
  12. //import std.contracts; // enforce, enforceEx
  13. import std.exception; // enforce, enforceEx
  14. import std.conv; // to
  15. import std.string; // cmp, toStringz
  16. import std.c.string; // strlen, strerror, strerror_r, memset
  17. version(unittest)
  18. {
  19. import std.stdio;
  20. }
  21. version(Posix)
  22. {
  23. version = BsdSockets;
  24. }
  25. version(Windows)
  26. {
  27. // Need for using Socket functions.
  28. pragma(lib, "ws2_32.lib");
  29. // pragma(lib, "wsock32.lib");
  30. import std.c.windows.windows;
  31. import std.c.windows.winsock;
  32. typedef SOCKET socket_t = INVALID_SOCKET;
  33. private
  34. {
  35. enum _SocketError = SOCKET_ERROR; /// Send or receive error code(SOCKET_ERROR).
  36. extern(Windows)
  37. {
  38. // compatible for Posix environment(from MSDN)
  39. enum _SS_PAD1SIZE = long.sizeof - short.sizeof;
  40. enum _SS_PAD2SIZE = 128 - short.sizeof - _SS_PAD1SIZE - long.sizeof;
  41. struct sockaddr_storage
  42. {
  43. short ss_family;
  44. byte[_SS_PAD1SIZE] __ss_pad1;
  45. long __ss_align;
  46. byte[_SS_PAD2SIZE] __ss_pad2;
  47. }
  48. union _inet_sock
  49. {
  50. sockaddr base;
  51. sockaddr_in v4;
  52. sockaddr_in6 v6;
  53. sockaddr_storage storage;
  54. }
  55. // placeholder for WSAStringToAddressA and WSAAddressToStringA
  56. struct WSAPROTOCOL_INFO { }
  57. alias WSAPROTOCOL_INFO* LPWSAPROTOCOL_INFO;
  58. int WSAStringToAddressA(const char*, int, LPWSAPROTOCOL_INFO, sockaddr*, int*);
  59. int WSAAddressToStringA(sockaddr*, int, LPWSAPROTOCOL_INFO, const char*, int*);
  60. alias int function(const char*, const char*, const addrinfo*, addrinfo**) getaddrinfo_t;
  61. alias void function(addrinfo*) freeaddrinfo_t;
  62. }
  63. enum EAFNOSUPPORT = 10047; // WSAEAFNOSUPPORT
  64. int lastError()
  65. {
  66. return WSAGetLastError();
  67. }
  68. // compatible for Posix environment
  69. int inet_pton(int af, const char* src, void* dst)
  70. {
  71. if (af != AF_INET && af != AF_INET6) {
  72. // unsupported address family
  73. setErrno(EAFNOSUPPORT);
  74. return -1;
  75. }
  76. _inet_sock addr;
  77. int size = addr.sizeof;
  78. auto error = WSAStringToAddressA(src, af, null, &addr.base, &size);
  79. if (error)
  80. return 0; // src is invalid notation.
  81. if (af == AF_INET) {
  82. *cast(in_addr*)dst = addr.v4.sin_addr;
  83. } else {
  84. *cast(in6_addr*)dst = addr.v6.sin6_addr;
  85. }
  86. return 1;
  87. }
  88. // ditto
  89. char* inet_ntop(int af, const void* src, char* dst, int length)
  90. {
  91. if (af != AF_INET && af != AF_INET6) {
  92. // unsupported address family
  93. setErrno(EAFNOSUPPORT);
  94. return null;
  95. }
  96. _inet_sock addr;
  97. int size;
  98. if (af == AF_INET) {
  99. size = addr.v4.sizeof;
  100. addr.v4.sin_family = AF_INET;
  101. addr.v4.sin_addr = *cast(typeof(addr.v4.sin_addr)*)src;
  102. } else {
  103. size = addr.v6.sizeof;
  104. addr.v6.sin6_family = AF_INET6;
  105. addr.v6.sin6_addr = *cast(typeof(addr.v6.sin6_addr)*)src;
  106. }
  107. auto error = WSAAddressToStringA(&addr.base, size, null, dst, &length);
  108. if (error)
  109. return null; // src is invalid notation.
  110. return dst;
  111. }
  112. }
  113. }
  114. else version(BsdSockets)
  115. {
  116. version(Posix)
  117. {
  118. version(linux)
  119. {
  120. import std.c.linux.socket;
  121. }
  122. else version(OSX)
  123. {
  124. import std.c.osx.socket;
  125. }
  126. else version(FreeBSD)
  127. {
  128. import std.c.freebsd.socket;
  129. import core.sys.posix.sys.select;
  130. import core.sys.posix.netinet.tcp;
  131. import core.sys.posix.netinet.in_;
  132. import core.sys.posix.sys.socket;
  133. private
  134. {
  135. enum SD_RECEIVE = SHUT_RD;
  136. enum SD_SEND = SHUT_WR;
  137. enum SD_BOTH = SHUT_RDWR;
  138. }
  139. }
  140. import core.sys.posix.fcntl;
  141. import core.sys.posix.unistd;
  142. import core.sys.posix.sys.time;
  143. }
  144. typedef int socket_t = -1; // -1 means INVALID_SOCKET
  145. private
  146. {
  147. enum _SocketError = -1; /// Send or receive error code(-1).
  148. // Why undefined?
  149. extern(C)
  150. {
  151. struct addrinfo
  152. {
  153. int ai_flags;
  154. int ai_family;
  155. int ai_socktype;
  156. int ai_protocol;
  157. socklen_t ai_addrlen;
  158. version (linux)
  159. {
  160. sockaddr* ai_addr;
  161. char* ai_canonname;
  162. }
  163. else
  164. {
  165. char* ai_canonname;
  166. sockaddr* ai_addr;
  167. }
  168. addrinfo* ai_next;
  169. }
  170. int getaddrinfo(const char* node, const char* service, const addrinfo* hints, addrinfo** res);
  171. void freeaddrinfo(addrinfo* ai);
  172. alias typeof(&getaddrinfo) getaddrinfo_t;
  173. alias typeof(&freeaddrinfo) freeaddrinfo_t;
  174. }
  175. int lastError()
  176. {
  177. return errno;
  178. }
  179. }
  180. }
  181. else
  182. {
  183. static assert(false, "Non support environment");
  184. }
  185. private __gshared
  186. {
  187. getaddrinfo_t getaddrinfo_func;
  188. freeaddrinfo_t freeaddrinfo_func;
  189. }
  190. shared static this()
  191. {
  192. version(Windows)
  193. {
  194. WSADATA wd;
  195. // Winsock will still load if an older version is present.
  196. // The version is just a request.
  197. int val = WSAStartup(0x2020, &wd);
  198. if (val) // Request Winsock 2.2 for IPv6.
  199. throw new SocketException("Unable to initialize socket library", val);
  200. // workaround for AddressInfo. dmd's lib doesn't have getaddrinfo functions.
  201. if (auto handle = GetModuleHandleA("ws2_32.dll")) {
  202. getaddrinfo_func = cast(getaddrinfo_t) GetProcAddress(handle, "getaddrinfo");
  203. freeaddrinfo_func = cast(freeaddrinfo_t)GetProcAddress(handle, "freeaddrinfo");
  204. }
  205. }
  206. else
  207. {
  208. getaddrinfo_func = &getaddrinfo;
  209. freeaddrinfo_func = &freeaddrinfo;
  210. }
  211. }
  212. shared static ~this()
  213. {
  214. // Avoids FinalizeError. D's GC may call the destructor of objects after static destructors.
  215. GC.collect();
  216. version(Windows)
  217. {
  218. WSACleanup();
  219. }
  220. }
  221. /**
  222. * The communication domain used to resolve an address
  223. */
  224. enum AddressFamily : int
  225. {
  226. UNSPEC = AF_UNSPEC, ///
  227. UNIX = AF_UNIX, /// local communication
  228. INET = AF_INET, /// internet protocol version 4
  229. IPX = AF_IPX, /// novell IPX
  230. APPLETALK = AF_APPLETALK, /// appletalk
  231. INET6 = AF_INET6, /// internet protocol version 6
  232. }
  233. /**
  234. * Communication semantics
  235. */
  236. enum SocketType : int
  237. {
  238. ANY, /// emulates the Posix behavior of null
  239. STREAM = SOCK_STREAM, /// sequenced, reliable, two-way communication-based byte streams
  240. DGRAM = SOCK_DGRAM, /// connectionless, unreliable datagrams with a fixed maximum length; data may be lost or arrive out of order
  241. RAW = SOCK_RAW, /// raw protocol access
  242. RDM = SOCK_RDM, /// reliably-delivered message datagrams
  243. SEQPACKET = SOCK_SEQPACKET, /// sequenced, reliable, two-way connection-based datagrams with a fixed maximum length
  244. }
  245. /**
  246. * Protocol
  247. */
  248. enum ProtocolType : int
  249. {
  250. ANY, /// emulates the Posix behavior of null
  251. IP = IPPROTO_IP, /// internet protocol version 4
  252. ICMP = IPPROTO_ICMP, /// internet control message protocol
  253. IGMP = IPPROTO_IGMP, /// internet group management protocol
  254. GGP = IPPROTO_GGP, /// gateway to gateway protocol
  255. TCP = IPPROTO_TCP, /// transmission control protocol
  256. PUP = IPPROTO_PUP, /// PARC universal packet protocol
  257. UDP = IPPROTO_UDP, /// user datagram protocol
  258. IDP = IPPROTO_IDP, /// Xerox NS protocol
  259. IPV6 = IPPROTO_IPV6, /// internet protocol version 6
  260. }
  261. /**
  262. * Hint option for resolving IP address
  263. */
  264. enum AddressInfoFlags : int
  265. {
  266. // Common options
  267. ANY, /// emulates the Posix behavior of null
  268. PASSIVE = 0x00000001, /// AI_PASSIVE : gets address for bind()
  269. CANONNAME = 0x00000002, /// AI_CANONNAME : returns ai_canonname
  270. NUMERICHOST = 0x00000004, /// AI_NUMERICHOST : prevent host-name resolution
  271. // std.c.windows.winsock doesn't define following options
  272. // NUMERICSERV = 0x00000008, /// AI_NUMERICSERV : prevent service-name resolution
  273. // AI_ALL, AI_V4MAPPED, AI_ADDRCONFIG
  274. }
  275. class AddressException : Exception
  276. {
  277. this(string msg)
  278. {
  279. super(msg);
  280. }
  281. }
  282. /**
  283. * AddressInfo is a class for resolving Address.
  284. */
  285. class AddressInfo
  286. {
  287. AddressInfoFlags flags;
  288. AddressFamily family;
  289. SocketType socketType;
  290. ProtocolType protocolType;
  291. string canonicalName;
  292. private:
  293. sockaddr_storage storage; // for C API, mainly getnameinfo
  294. size_t length;
  295. public:
  296. /**
  297. * for hint.
  298. */
  299. @safe
  300. this(AddressInfoFlags ai_flags = AddressInfoFlags.ANY, AddressFamily ai_family = AddressFamily.UNSPEC,
  301. SocketType ai_socktype = SocketType.ANY, ProtocolType ai_protocol = ProtocolType.ANY)
  302. {
  303. flags = ai_flags;
  304. family = ai_family;
  305. socketType = ai_socktype;
  306. protocolType = ai_protocol;
  307. }
  308. /// ditto
  309. @safe
  310. this(AddressFamily ai_family, SocketType ai_socktype = SocketType.ANY,
  311. ProtocolType ai_protocol = ProtocolType.ANY, AddressInfoFlags ai_flags = AddressInfoFlags.ANY)
  312. {
  313. this(ai_flags, ai_family, ai_socktype, ai_protocol);
  314. }
  315. /// ditto
  316. @safe
  317. this(SocketType ai_socktype, ProtocolType ai_protocol = ProtocolType.ANY,
  318. AddressInfoFlags ai_flags = AddressInfoFlags.ANY, AddressFamily ai_family = AddressFamily.UNSPEC)
  319. {
  320. this(ai_flags, ai_family, ai_socktype, ai_protocol);
  321. }
  322. /// ditto
  323. @safe
  324. this(ProtocolType ai_protocol, AddressInfoFlags ai_flags = AddressInfoFlags.ANY,
  325. AddressFamily ai_family = AddressFamily.UNSPEC, SocketType ai_socktype = SocketType.ANY)
  326. {
  327. this(ai_flags, ai_family, ai_socktype, ai_protocol);
  328. }
  329. /**
  330. * called by static methods.
  331. */
  332. @trusted
  333. this(addrinfo* ai)
  334. in
  335. {
  336. assert(ai, "ai is null");
  337. }
  338. body
  339. {
  340. with (*ai) {
  341. family = cast(AddressFamily)ai_family;
  342. socketType = cast(SocketType)ai_socktype;
  343. protocolType = cast(ProtocolType)ai_protocol;
  344. length = ai_addrlen;
  345. storage = *cast(sockaddr_storage*)ai_addr;
  346. if (ai_canonname)
  347. canonicalName = to!string(ai_canonname);
  348. }
  349. }
  350. /**
  351. * Returns:
  352. * the IP address associated with family.
  353. */
  354. @property @trusted
  355. IPAddress ipAddress() const
  356. {
  357. switch (family) {
  358. case AddressFamily.INET:
  359. return IPAddress(IPv4Address(ntohl((*cast(sockaddr_in*)&storage).sin_addr.s_addr)));
  360. case AddressFamily.INET6:
  361. return IPAddress(IPv6Address((*cast(sockaddr_in6*)&storage).sin6_addr.s6_addr,
  362. (*cast(sockaddr_in6*)&storage).sin6_scope_id));
  363. default:
  364. throw new AddressException(to!string(family) ~ " is not a IP address");
  365. }
  366. }
  367. /**
  368. * Returns:
  369. * the port associated with family.
  370. */
  371. @property @trusted
  372. ushort port() const
  373. {
  374. switch (family) {
  375. case AddressFamily.INET:
  376. return ntohs((*cast(sockaddr_in*)&storage).sin_port);
  377. case AddressFamily.INET6:
  378. return ntohs((*cast(sockaddr_in6*)&storage).sin6_port);
  379. default:
  380. throw new AddressException(to!string(family) ~ " is not a IP address");
  381. }
  382. }
  383. /**
  384. * Returns:
  385. * the local address associated with family.
  386. */
  387. @property @trusted
  388. LocalAddress localAddress() const
  389. {
  390. switch (family) {
  391. case AddressFamily.UNIX:
  392. return LocalAddress(to!string((*cast(sockaddr_un*)&storage).sun_path.ptr));
  393. default:
  394. throw new AddressException(to!string(family) ~ " is not a local address");
  395. }
  396. }
  397. /**
  398. * Returns:
  399. * the path associated with family.
  400. */
  401. @property @trusted
  402. string path()
  403. {
  404. switch (family) {
  405. case AddressFamily.UNIX:
  406. return to!string((*cast(sockaddr_un*)&storage).sun_path.ptr);
  407. default:
  408. throw new AddressException(to!string(family) ~ " is not a local address");
  409. }
  410. }
  411. /**
  412. * Resolves address information.
  413. *
  414. * Returns:
  415. * null if unable to resolve.
  416. */
  417. static AddressInfo[] getByNode(string node, string service = null, AddressInfo hint = null)
  418. in
  419. {
  420. assert(!(node is null && service is null));
  421. }
  422. body
  423. {
  424. /*
  425. * Supports AF_UNIX
  426. */
  427. AddressInfo createLocalAddress(AddressInfo info)
  428. in
  429. {
  430. assert(node, "UNIX family requires node");
  431. }
  432. body
  433. {
  434. auto sun = sockaddr_un(cast(short)AddressFamily.UNIX);
  435. auto addr = new AddressInfo(AddressFamily.UNIX, (info.socketType == SocketType.DGRAM)
  436. ? SocketType.DGRAM : SocketType.STREAM);
  437. sun.sun_path[0..node.length] = node;
  438. sun.sun_path[node.length] = '\0';
  439. addr.length = sockaddr_un.sizeof;
  440. *cast(sockaddr_un*)&addr.storage = sun;
  441. return addr;
  442. }
  443. enforce(getaddrinfo_func, "Your environment can't use getaddrinfo functions");
  444. addrinfo* res, hints;
  445. if (hint !is null) {
  446. // Local address support
  447. if (hint.family == AddressFamily.UNIX)
  448. return [createLocalAddress(hint)];
  449. hints = cast(addrinfo*)alloca(addrinfo.sizeof);
  450. memset(hints, 0, addrinfo.sizeof);
  451. with (*hints) {
  452. ai_flags = cast(int)hint.flags;
  453. ai_family = cast(int)hint.family;
  454. ai_socktype = cast(int)hint.socketType;
  455. ai_protocol = cast(int)hint.protocolType;
  456. }
  457. }
  458. if (getaddrinfo_func(node ? node.toStringz() : null, service ? service.toStringz() : null, hints, &res))
  459. return null; // gai_strerror is better?
  460. AddressInfo[] addresses;
  461. for (auto p = res; p; p = p.ai_next)
  462. addresses ~= new AddressInfo(p);
  463. freeaddrinfo_func(res);
  464. return addresses;
  465. }
  466. /// ditto
  467. static AddressInfo[] getByService(string service, string node = null, AddressInfo hints = null)
  468. {
  469. return getByService(node, service, hints);
  470. }
  471. }
  472. unittest
  473. {
  474. auto ais = AddressInfo.getByNode("localhost");
  475. assert(ais.length, "getaddrinfo failure");
  476. auto ai = AddressInfo.getByNode("/tmp/sock", null, new AddressInfo(AddressFamily.UNIX))[0];
  477. assert(ai);
  478. assert(ai.path == "/tmp/sock");
  479. assert(ai.socketType == SocketType.STREAM);
  480. }
  481. /*
  482. * NI_* constants not found.
  483. class NameInfo { }
  484. */
  485. /**
  486. * IP address representation
  487. *
  488. * Currently, supports IP version 4 and 6.
  489. */
  490. struct IPAddress
  491. {
  492. private:
  493. enum Type { v4, v6 }
  494. union Impl
  495. {
  496. IPv4Address v4;
  497. IPv6Address v6;
  498. }
  499. Impl impl_;
  500. Type type_;
  501. public:
  502. /**
  503. * Constructs a IP address.
  504. *
  505. * Throws:
  506. * AddressException if address format isn't IPv4 or IPv6.
  507. */
  508. @safe
  509. this(IPv4Address ipv4)
  510. {
  511. type_ = Type.v4;
  512. impl_.v4 = ipv4;
  513. }
  514. /// ditto
  515. @safe
  516. this(IPv6Address ipv6)
  517. {
  518. type_ = Type.v6;
  519. impl_.v6 = ipv6;
  520. }
  521. /// ditto
  522. @trusted
  523. this(ubyte[] addr)
  524. {
  525. if (addr.length == 4) {
  526. type_ = Type.v4;
  527. impl_.v4 = IPv4Address(addr);
  528. } else if (addr.length == 16) {
  529. type_ = Type.v6;
  530. impl_.v6 = IPv6Address(addr);
  531. } else {
  532. throw new AddressException("Unknown address format - " ~ to!string(addr));
  533. }
  534. }
  535. /// ditto
  536. @safe
  537. this(string addr)
  538. {
  539. if (IPv4Address.tryParse(addr, this))
  540. return;
  541. if (IPv6Address.tryParse(addr, this))
  542. return;
  543. throw new AddressException("Unknown address format - " ~ addr);
  544. }
  545. /**
  546. * Returns:
  547. * the family of this address.
  548. */
  549. @property @safe
  550. nothrow AddressFamily family() const
  551. {
  552. return type_ == Type.v4 ? AddressFamily.INET : AddressFamily.INET6;
  553. }
  554. /**
  555. * Returns:
  556. * true if this address is IP version 4.
  557. */
  558. @property @safe
  559. nothrow bool isIPv4() const
  560. {
  561. return type_ == Type.v4;
  562. }
  563. /**
  564. * Returns:
  565. * true if this address is IP version 6.
  566. */
  567. @property @safe
  568. nothrow bool isIPv6() const
  569. {
  570. return type_ == Type.v6;
  571. }
  572. /**
  573. * Returns:
  574. * the address as an IPv4Address.
  575. */
  576. @safe
  577. IPv4Address toIPv4()
  578. {
  579. if (!isIPv4)
  580. throw new AddressException("This IP address is not a version 4");
  581. return impl_.v4;
  582. }
  583. /**
  584. * Returns:
  585. * the address as an IPv6Address.
  586. */
  587. @safe
  588. IPv6Address toIPv6()
  589. {
  590. if (!isIPv6)
  591. throw new AddressException("This IP address is not a version 6");
  592. return impl_.v6;
  593. }
  594. @safe
  595. bool opEquals(ref const IPAddress other) const
  596. {
  597. if (type_ != other.type_)
  598. return false;
  599. return type_ == Type.v4 ? impl_.v4 == other.impl_.v4 : impl_.v6 == other.impl_.v6;
  600. }
  601. @safe
  602. int opCmp(ref const IPAddress other) const
  603. {
  604. if (type_ < other.type_)
  605. return -1;
  606. else if (type_ > other.type_)
  607. return 1;
  608. else
  609. return type_ == Type.v4 ? impl_.v4 < other.impl_.v4 : impl_.v6 < other.impl_.v6;
  610. }
  611. @safe
  612. string toString() const
  613. {
  614. return type_ == Type.v4 ? impl_.v4.toString() : impl_.v6.toString();
  615. }
  616. }
  617. unittest
  618. {
  619. ubyte[] addr = [1, 2, 3, 4];
  620. { // IP version 4
  621. auto ip = IPAddress(addr);
  622. assert(ip.isIPv4);
  623. assert(!ip.isIPv6);
  624. assert(ip.family == AddressFamily.INET);
  625. assert(ip.toIPv4 == IPv4Address(addr));
  626. try {
  627. auto ipv6 = ip.toIPv6();
  628. assert(false);
  629. } catch (AddressException e) { }
  630. }
  631. addr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0];
  632. { // IP version 6
  633. auto ip = IPAddress(addr);
  634. assert(!ip.isIPv4);
  635. assert(ip.isIPv6);
  636. assert(ip.family == AddressFamily.INET6);
  637. assert(ip.toIPv6 == IPv6Address(addr));
  638. try {
  639. auto ipv4 = ip.toIPv4();
  640. assert(false);
  641. } catch (AddressException e) { }
  642. }
  643. }
  644. /**
  645. * IP version 4 representation for $(D IPAddress)
  646. *
  647. * Note:
  648. * String-conversion is a environment-dependent function. You should not be 0-fill format.
  649. *
  650. * Example:
  651. * -----
  652. * auto v4 = IPv4Address("063.105.9.61");
  653. * writeln(v4); // "63.105.9.61" on Mac, otherwise "51.105.9.61"
  654. * -----
  655. */
  656. struct IPv4Address
  657. {
  658. private:
  659. in_addr address_;
  660. public:
  661. /**
  662. * Tries to parse an IPv4 address string in the dotted-decimal form $(I a.b.c.d)
  663. * and returns the success and failure. Sets new object to $(D_PARAM ip) if succeeded.
  664. */
  665. @trusted
  666. static bool tryParse(string addr, ref IPAddress ip)
  667. {
  668. in_addr temp;
  669. if (inet_pton(AF_INET, addr.toStringz(), &temp) < 1) {
  670. return false;
  671. } else {
  672. ip = IPAddress(IPv4Address(ntohl(temp.s_addr)));
  673. return true;
  674. }
  675. }
  676. /**
  677. * Constructs a IPv4Address.
  678. *
  679. * Throws:
  680. * AddressException if ddress format is not IP version 4.
  681. */
  682. @trusted
  683. this(ubyte[] bytes)
  684. in
  685. {
  686. assert(bytes.length == 4, "IP version 4 is 4 bytes");
  687. }
  688. body
  689. {
  690. address_.s_addr = *cast(typeof(address_.s_addr)*)bytes.ptr;
  691. }
  692. /// ditto
  693. @trusted
  694. this(uint addr)
  695. {
  696. address_.s_addr = htonl(addr);
  697. }
  698. /// ditto
  699. @trusted
  700. this(string addr)
  701. {
  702. enforceEx!(AddressException)(inet_pton(AF_INET, addr.toStringz(), &address_) > 0,
  703. "Unable to translate address '" ~ addr ~ "'");
  704. }
  705. /**
  706. * Returns:
  707. * the address as an unsigned integer.
  708. *
  709. * Note:
  710. * host byte order.
  711. */
  712. @trusted
  713. uint toUInt() const
  714. {
  715. return ntohl(address_.s_addr);
  716. }
  717. /**
  718. * Returns:
  719. * the address as a byte representation.
  720. *
  721. * Note:
  722. * network byte order.
  723. */
  724. @trusted
  725. ubyte[4] toBytes() const
  726. {
  727. ubyte[4] bytes;
  728. *cast(typeof(address_.s_addr)*)bytes.ptr = address_.s_addr;
  729. return bytes;
  730. }
  731. @safe
  732. bool opEquals(ref const IPv4Address other) const
  733. {
  734. return address_.s_addr == other.address_.s_addr;
  735. }
  736. @safe
  737. int opCmp(ref const IPv4Address other) const
  738. {
  739. uint a = toUInt(), b = other.toUInt();
  740. if (a < b)
  741. return -1;
  742. else if (a == b)
  743. return 0;
  744. else
  745. return 1;
  746. }
  747. @trusted
  748. string toString() const
  749. {
  750. // enum ADDRSTRLEN = 16; // avoid compilation error with INET_ADDRSTRLEN
  751. enum ADDRSTRLEN = INET_ADDRSTRLEN; // avoid compilation error with INET_ADDRSTRLEN
  752. char[ADDRSTRLEN] buf;
  753. auto addr = inet_ntop(AF_INET, &address_, buf.ptr, ADDRSTRLEN);
  754. if (addr is null)
  755. return null;
  756. return to!string(addr);
  757. }
  758. }
  759. unittest
  760. {
  761. // [1, 2, 3, 4] literal becomes string at initialization?
  762. auto v4 = IPv4Address(cast(ubyte[])[1, 2, 3, 4]);
  763. assert(v4.toBytes == [1, 2, 3, 4]);
  764. assert(v4.toString() == "1.2.3.4");
  765. v4 = IPv4Address("63.105.9.61");
  766. assert(v4.toBytes() == [63, 105, 9, 61]);
  767. assert(v4.toString() == "63.105.9.61");
  768. }
  769. /**
  770. * IP version 6 representation for $(D IPAddress)
  771. *
  772. * Note:
  773. * If your environment disables(or can't use) IP version 6, some methods fail or raise Exception.
  774. */
  775. struct IPv6Address
  776. {
  777. private:
  778. in6_addr address_;
  779. uint scopeId_;
  780. public:
  781. /**
  782. * Tries to parse an IPv6 address string and returns the success and failure.
  783. * Sets new object to $(D_PARAM ip) if success.
  784. */
  785. @trusted
  786. static bool tryParse(string addr, ref IPAddress ip)
  787. {
  788. // In Linux, inet_pton can't parse scope-id.
  789. uint scopeId;
  790. auto i = addr.lastIndexOf('%', CaseSensitive.no);
  791. if (i >= 0) {
  792. scopeId = to!uint(addr[i + 1..$]);
  793. addr = addr[0..i];
  794. }
  795. in6_addr temp;
  796. if (inet_pton(AF_INET6, addr.toStringz(), &temp) < 1) {
  797. return false;
  798. } else {
  799. ip = IPAddress(IPv6Address(temp.s6_addr, scopeId));
  800. return true;
  801. }
  802. }
  803. /**
  804. * Constructs a IPv6Address.
  805. *
  806. * Throws:
  807. * AddressException if address format isn't IP version 6.
  808. */
  809. @safe
  810. this(ubyte[] bytes, uint id = 0)
  811. in
  812. {
  813. assert(bytes.length == 16, "IP version 6 is 16 bytes");
  814. }
  815. body
  816. {
  817. address_.s6_addr[] = bytes;
  818. scopeId_ = id;
  819. }
  820. /// ditto
  821. @trusted
  822. this(string addr)
  823. {
  824. // In Linux, inet_pton can't parse scope-id.
  825. auto i = addr.lastIndexOf('%', CaseSensitive.no);
  826. if (i >= 0) {
  827. scopeId_ = to!uint(addr[i + 1..$]);
  828. addr = addr[0..i];
  829. }
  830. enforceEx!(AddressException)(inet_pton(AF_INET6, addr.toStringz(), &address_) > 0,
  831. "Unable to translate IPv6 address '" ~ addr ~ "'");
  832. }
  833. /**
  834. * Property for scope id.
  835. */
  836. @property @safe nothrow
  837. {
  838. uint scopeId() const
  839. {
  840. return scopeId_;
  841. }
  842. void scopeId(uint id)
  843. {
  844. scopeId_ = id;
  845. }
  846. }
  847. /**
  848. * Returns:
  849. * the address as an unsigned integer.
  850. *
  851. * Throws:
  852. * AddressException always.
  853. */
  854. @safe
  855. uint toUInt() const
  856. {
  857. throw new AddressException("uint type can't represents IPv6");
  858. }
  859. /**
  860. * Returns:
  861. * the address as a byte representation.
  862. *
  863. * Note:
  864. * network byte order.
  865. */
  866. @safe
  867. ubyte[16] toBytes() const
  868. {
  869. ubyte[16] bytes;
  870. bytes[] = address_.s6_addr;
  871. return bytes;
  872. }
  873. @safe
  874. bool opEquals(ref const IPv6Address other) const
  875. {
  876. return (this < other) == 0;
  877. }
  878. @safe
  879. int opCmp(ref const IPv6Address other) const
  880. {
  881. auto a = address_.s6_addr, b = other.address_.s6_addr;
  882. if (a < b)
  883. return -1;
  884. else if (a > b)
  885. return 1;
  886. else
  887. return scopeId_ == other.scopeId_ ? 0 : scopeId_ < other.scopeId_ ? -1 : 1;
  888. }
  889. @trusted
  890. string toString() const
  891. {
  892. enum ADDRSTRLEN = 46;
  893. char[ADDRSTRLEN] buf;
  894. auto addr = inet_ntop(AF_INET6, &address_, buf.ptr, ADDRSTRLEN);
  895. if (addr is null)
  896. return null;
  897. auto result = to!string(addr);
  898. if (scopeId_)
  899. result ~= "%" ~ to!string(scopeId_);
  900. return result;
  901. }
  902. }
  903. unittest
  904. {
  905. IPAddress ipa;
  906. if (IPv6Address.tryParse("::", ipa)) {
  907. auto addr = new ubyte[](16);
  908. auto v6 = IPv6Address(addr, 1);
  909. assert(v6.toString() == "::%1");
  910. v6 = IPv6Address("2001:0db8:0000:0000:1234:0000:0000:9abc");
  911. assert(v6.toString() == "2001:db8::1234:0:0:9abc");
  912. try {
  913. v6.toUInt();
  914. assert(false);
  915. } catch (Exception e) { }
  916. } else {
  917. writeln(" --- IPv6Address test: Your environment seems to be IP version 6 disable");
  918. }
  919. }
  920. /**
  921. * Local address representation
  922. */
  923. struct LocalAddress
  924. {
  925. private:
  926. string path_;
  927. public:
  928. /**
  929. * Constructs a LocalAddress with argument.
  930. */
  931. @safe
  932. this(string path)
  933. {
  934. path_ = path;
  935. }
  936. /**
  937. * Returns:
  938. * the family of this address.
  939. */
  940. @property @safe
  941. AddressFamily family() const
  942. {
  943. return AddressFamily.UNIX;
  944. }
  945. /**
  946. * Returns:
  947. * the path.
  948. */
  949. @property @safe
  950. string path() const
  951. {
  952. return path_;
  953. }
  954. @trusted
  955. bool opEquals(ref const LocalAddress other) const
  956. {
  957. return path_.cmp(other.path_) == 0;
  958. }
  959. @trusted
  960. int opCmp(ref const LocalAddress other) const
  961. {
  962. return path_.cmp(other.path_);
  963. }
  964. @safe
  965. string toString() const
  966. {
  967. return path;
  968. }
  969. }
  970. unittest
  971. {
  972. auto ua1 = LocalAddress("path");
  973. assert(ua1.toString() == "path");
  974. auto ua2 = LocalAddress("root");
  975. assert(ua1 != ua2);
  976. assert(ua1 <= ua2);
  977. }
  978. /**
  979. * Detects whether T is a $(D Endpoint) type.
  980. *
  981. * Concept:
  982. * -----
  983. * Endpoint endpoint; // can define a Endpoint object
  984. * auto name = endpoint.name; // can return a pointer of sockaddr
  985. * auto size = endpoint.nameLen; // can return a size of sockaddr_*
  986. * auto addr = endpoint.address; // can return a corresponding Address object
  987. * -----
  988. */
  989. template isEndpoint(Endpoint)
  990. {
  991. enum isEndpoint = __traits(compiles,
  992. {
  993. Endpoint endpoint; // can define a Endpoint object
  994. auto name = endpoint.name; // can return a pointer of sockaddr
  995. auto size = endpoint.nameLen; // can return a length of sockaddr_*
  996. auto addr = endpoint.address; // can return a corresponding Address object
  997. });
  998. }
  999. /**
  1000. * Endpoint representation for IP socket
  1001. */
  1002. struct IPEndpoint
  1003. {
  1004. private:
  1005. extern(System) union SocketAddress
  1006. {
  1007. sockaddr base;
  1008. sockaddr_in v4;
  1009. sockaddr_in6 v6;
  1010. }
  1011. SocketAddress sa_;
  1012. public:
  1013. /**
  1014. * Constructs a IPEndpoint.
  1015. *
  1016. * Initializes an address as IPv4 if the argument is port only.
  1017. */
  1018. @trusted
  1019. this(IPAddress address, ushort portNumber)
  1020. {
  1021. if (address.isIPv4) {
  1022. auto v4 = address.toIPv4();
  1023. sa_.v4.sin_family = AF_INET;
  1024. sa_.v4.sin_port = htons(portNumber);
  1025. sa_.v4.sin_addr.s_addr = htonl(v4.toUInt());
  1026. } else {
  1027. auto v6 = address.toIPv6();
  1028. sa_.v6.sin6_family = AF_INET6;
  1029. sa_.v6.sin6_port = htons(portNumber);
  1030. sa_.v6.sin6_addr.s6_addr[] = v6.toBytes();
  1031. sa_.v6.sin6_scope_id = v6.scopeId;
  1032. }
  1033. }
  1034. /// ditto
  1035. @trusted
  1036. this(ushort portNumber)
  1037. {
  1038. sa_.v4.sin_family = AF_INET;
  1039. sa_.v4.sin_port = htons(portNumber);
  1040. sa_.v4.sin_addr.s_addr = INADDR_ANY;
  1041. }
  1042. /**
  1043. * Endpoint constraint needs these methods.
  1044. */
  1045. @property @safe nothrow
  1046. {
  1047. sockaddr* name()
  1048. {
  1049. return &sa_.base;
  1050. }
  1051. const(sockaddr)* name() const
  1052. {
  1053. return &sa_.base;
  1054. }
  1055. int nameLen() const
  1056. {
  1057. return isIPv4 ? sa_.v4.sizeof : sa_.v6.sizeof;
  1058. }
  1059. }
  1060. /**
  1061. * Property for Address object associated with this endpoint.
  1062. */
  1063. @property @trusted
  1064. {
  1065. IPAddress address() const
  1066. {
  1067. IPAddress addr;
  1068. if (isIPv4)
  1069. addr = IPAddress(IPv4Address(ntohl(sa_.v4.sin_addr.s_addr)));
  1070. else
  1071. addr = IPAddress(IPv6Address(cast(ubyte[])sa_.v6.sin6_addr.s6_addr, sa_.v6.sin6_scope_id));
  1072. return addr;
  1073. }
  1074. void address(IPAddress addr)
  1075. {
  1076. auto endpoint = IPEndpoint(addr, port);
  1077. sa_ = endpoint.sa_;
  1078. }
  1079. }
  1080. /**
  1081. * Property for port associated with this endpoint.
  1082. */
  1083. @property @trusted
  1084. {
  1085. ushort port() const
  1086. {
  1087. return ntohs(isIPv4 ? sa_.v4.sin_port : sa_.v6.sin6_port);
  1088. }
  1089. void port(ushort portNumber)
  1090. {
  1091. (isIPv4 ? sa_.v4.sin_port : sa_.v6.sin6_port) = htons(portNumber);
  1092. }
  1093. }
  1094. /**
  1095. * Returns:
  1096. * the family of this endpoint.
  1097. */
  1098. @property @safe
  1099. AddressFamily addressFamily() const
  1100. {
  1101. return isIPv4 ? AddressFamily.INET : AddressFamily.INET6;
  1102. }
  1103. @safe
  1104. bool opEquals(ref const IPEndpoint other) const
  1105. {
  1106. return (this < other) == 0;
  1107. }
  1108. @safe
  1109. int opCmp(ref const IPEndpoint other) const
  1110. {
  1111. auto lhs = address;
  1112. auto rhs = other.address;
  1113. if (lhs < rhs)
  1114. return -1;
  1115. else if (lhs > rhs)
  1116. return 1;
  1117. else
  1118. return port == other.port ? 0 : port < other.port ? -1 : 1;
  1119. }
  1120. @trusted
  1121. string toString() const
  1122. {
  1123. auto addr = address.toString;
  1124. return (isIPv4 ? addr : "[" ~ addr ~ "]") ~ ":" ~ to!string(port);
  1125. }
  1126. private:
  1127. @property @safe
  1128. nothrow bool isIPv4() const
  1129. {
  1130. return sa_.base.sa_family == AF_INET;
  1131. }
  1132. }
  1133. unittest
  1134. {
  1135. auto endpoint = IPEndpoint(IPAddress("127.0.0.1"), 80);
  1136. assert(endpoint.address.family == AddressFamily.INET);
  1137. assert(endpoint.port == 80);
  1138. assert(endpoint.nameLen == sockaddr_in.sizeof);
  1139. assert(endpoint.address == IPAddress("127.0.0.1"));
  1140. assert(endpoint.toString() == "127.0.0.1:80");
  1141. endpoint.address = IPAddress("::%10");
  1142. assert(endpoint.address.family == AddressFamily.INET6);
  1143. assert(endpoint.nameLen == sockaddr_in6.sizeof);
  1144. assert(endpoint.toString() == "[::%10]:80");
  1145. }
  1146. extern(System) private struct sockaddr_un
  1147. {
  1148. short sun_family;
  1149. char[108] sun_path;
  1150. }
  1151. /**
  1152. * Endpoint representation for UNIX socket
  1153. */
  1154. struct LocalEndpoint
  1155. {
  1156. private:
  1157. extern(System) union SocketAddress
  1158. {
  1159. sockaddr base;
  1160. sockaddr_un unix;
  1161. }
  1162. SocketAddress sa_;
  1163. public:
  1164. /**
  1165. * Constructs a LocalEndpoint.
  1166. */
  1167. @safe
  1168. this(LocalAddress addr)
  1169. in
  1170. {
  1171. assert(addr.path.length < sa_.unix.sun_path.sizeof, "path is too long.: " ~ addr.path);
  1172. }
  1173. body
  1174. {
  1175. sa_.unix.sun_family = AF_UNIX;
  1176. sa_.unix.sun_path[0..addr.path.length] = addr.path;
  1177. sa_.unix.sun_path[addr.path.length] = '\0';
  1178. }
  1179. /**
  1180. * Endpoint constraint needs these methods.
  1181. */
  1182. @property @safe nothrow
  1183. {
  1184. sockaddr* name()
  1185. {
  1186. return &sa_.base;
  1187. }
  1188. const(sockaddr)* name() const
  1189. {
  1190. return &sa_.base;
  1191. }
  1192. int nameLen() const
  1193. {
  1194. return sa_.unix.sizeof;
  1195. }
  1196. }
  1197. /**
  1198. * Property for Address object associated with this endpoint.
  1199. */
  1200. @property @trusted
  1201. {
  1202. LocalAddress address() const
  1203. {
  1204. return LocalAddress(to!string(sa_.unix.sun_path.ptr));
  1205. }
  1206. void address(LocalAddress addr)
  1207. {
  1208. auto endpoint = LocalEndpoint(addr);
  1209. sa_ = endpoint.sa_;
  1210. }
  1211. }
  1212. /**
  1213. * Property for path associated with this endpoint.
  1214. */
  1215. @property @trusted
  1216. {
  1217. string path() const
  1218. {
  1219. return to!string(sa_.unix.sun_path.ptr);
  1220. }
  1221. void path(string sunPath)
  1222. in
  1223. {
  1224. assert(sunPath.length < sa_.unix.sun_path.sizeof, "sunPath is too long.: " ~ sunPath);
  1225. }
  1226. body
  1227. {
  1228. sa_.unix.sun_path[0..sunPath.length] = sunPath;
  1229. sa_.unix.sun_path[sunPath.length] = '\0';
  1230. }
  1231. }
  1232. /**
  1233. * Returns:
  1234. * the family of this endpoint.
  1235. */
  1236. @property @safe
  1237. AddressFamily addressFamily() const
  1238. {
  1239. return AddressFamily.UNIX;
  1240. }
  1241. @safe
  1242. bool opEquals(ref const LocalEndpoint other) const
  1243. {
  1244. return (this < other) == 0;
  1245. }
  1246. @trusted
  1247. int opCmp(ref const LocalEndpoint other) const
  1248. {
  1249. auto lhs = sa_.unix.sun_path[0..sa_.unix.sun_path.indexOf('\0')];
  1250. auto rhs = other.sa_.unix.sun_path[0..other.sa_.unix.sun_path.indexOf('\0')];
  1251. return lhs.cmp(rhs);
  1252. }
  1253. @trusted
  1254. string toString() const
  1255. {
  1256. return cast(string)sa_.unix.sun_path[0..sa_.unix.sun_path.indexOf('\0')];
  1257. }
  1258. }
  1259. unittest
  1260. {
  1261. auto endpoint = LocalEndpoint(LocalAddress("path"));
  1262. assert(endpoint.address.family == AddressFamily.UNIX);
  1263. assert(endpoint.path == "path");
  1264. assert(endpoint.address == LocalAddress("path"));
  1265. endpoint.path = "root";
  1266. assert(endpoint.path == "root");
  1267. assert(endpoint.nameLen == sockaddr_un.sizeof);
  1268. assert(endpoint.toString() == "root");
  1269. }
  1270. /**
  1271. * Thrown on a Socket error.
  1272. */
  1273. class SocketException : Exception
  1274. {
  1275. int errorCode; /// platform-specific error code
  1276. /**
  1277. * $(D_PARAM err) is converted to string using strerror_r.
  1278. */
  1279. this(string msg, int err = 0)
  1280. {
  1281. errorCode = err;
  1282. version(Posix)
  1283. {
  1284. if (errorCode > 0) {
  1285. char[80] buf;
  1286. const(char)* cs;
  1287. version (linux)
  1288. {
  1289. cs = strerror_r(errorCode, buf.ptr, buf.length);
  1290. }
  1291. else version (OSX)
  1292. {
  1293. auto errs = strerror_r(errorCode, buf.ptr, buf.length);
  1294. if (errs == 0)
  1295. cs = buf.ptr;
  1296. else
  1297. cs = "Unknown error";
  1298. }
  1299. else version (FreeBSD)
  1300. {
  1301. auto errs = strerror_r(errorCode, buf.ptr, buf.length);
  1302. if (errs == 0)
  1303. cs = buf.ptr;
  1304. else
  1305. cs = "Unknown error";
  1306. }
  1307. else
  1308. {
  1309. static assert(false);
  1310. }
  1311. auto len = strlen(cs);
  1312. if (cs[len - 1] == '\n')
  1313. len--;
  1314. if (cs[len - 1] == '\r')
  1315. len--;
  1316. msg = cast(string)(msg ~ ": " ~ cs[0 .. len]);
  1317. }
  1318. }
  1319. super(msg);
  1320. }
  1321. }
  1322. /**
  1323. * for SocketOption.LINGER
  1324. */
  1325. extern(System) struct Linger
  1326. {
  1327. version(Windows)
  1328. {
  1329. ushort on;
  1330. ushort time;
  1331. }
  1332. else
  1333. {
  1334. int on;
  1335. int time;
  1336. }
  1337. }
  1338. /**
  1339. * Duration timeout value
  1340. */
  1341. extern(System) struct Timeout
  1342. {
  1343. int seconds; /// Number of seconds.
  1344. int microseconds; /// Number of additional microseconds.
  1345. }
  1346. /**
  1347. * How a socket is shutdown:
  1348. */
  1349. enum SocketShutdown : int
  1350. {
  1351. RECEIVE = SD_RECEIVE, /// socket receives are disallowed
  1352. SEND = SD_SEND, /// socket sends are disallowed
  1353. BOTH = SD_BOTH, /// both RECEIVE and SEND
  1354. }
  1355. /**
  1356. * Flags may be OR'ed together:
  1357. */
  1358. enum SocketFlags : int
  1359. {
  1360. NONE = 0, /// no flags specified
  1361. OOB = MSG_OOB, /// out-of-band stream data
  1362. PEEK = MSG_PEEK, /// peek at incoming data without removing it from the queue, only for receiving
  1363. DONTROUTE = MSG_DONTROUTE, /// data should not be subject to routing; this flag may be ignored. Only for sending
  1364. NOSIGNAL = MSG_NOSIGNAL, /// don't send SIGPIPE signal on socket write error and instead return EPIPE
  1365. }
  1366. /**
  1367. * The level at which a socket option is defined:
  1368. */
  1369. enum SocketOptionLevel: int
  1370. {
  1371. SOCKET = SOL_SOCKET, /// socket level
  1372. IP = ProtocolType.IP, /// internet protocol version 4 level
  1373. ICMP = ProtocolType.ICMP, ///
  1374. IGMP = ProtocolType.IGMP, ///
  1375. GGP = ProtocolType.GGP, ///
  1376. TCP = ProtocolType.TCP, /// transmission control protocol level
  1377. PUP = ProtocolType.PUP, ///
  1378. UDP = ProtocolType.UDP, /// user datagram protocol level
  1379. IDP = ProtocolType.IDP, ///
  1380. IPV6 = ProtocolType.IPV6, /// internet protocol version 6 level
  1381. }
  1382. /**
  1383. * Specifies a socket option:
  1384. */
  1385. enum SocketOption: int
  1386. {
  1387. DEBUG = SO_DEBUG, /// record debugging information
  1388. BROADCAST = SO_BROADCAST, /// allow transmission of broadcast messages
  1389. REUSEADDR = SO_REUSEADDR, /// allow local reuse of address
  1390. LINGER = SO_LINGER, /// Linger on close if unsent data is present
  1391. OOBINLINE = SO_OOBINLINE, /// receive out-of-band data in band
  1392. SNDBUF = SO_SNDBUF, /// send buffer size
  1393. RCVBUF = SO_RCVBUF, /// receive buffer size
  1394. DONTROUTE = SO_DONTROUTE, /// do not route
  1395. //TYPE = SO_TYPE, /// current socket type
  1396. // SocketOptionLevel.TCP:
  1397. TCP_NODELAY = .TCP_NODELAY, /// disable the Nagle algorithm for send coalescing
  1398. // SocketOptionLevel.IPV6:
  1399. IPV6_UNICAST_HOPS = .IPV6_UNICAST_HOPS, ///
  1400. IPV6_MULTICAST_IF = .IPV6_MULTICAST_IF, ///
  1401. IPV6_MULTICAST_LOOP = .IPV6_MULTICAST_LOOP, ///
  1402. IPV6_JOIN_GROUP = .IPV6_JOIN_GROUP, ///
  1403. IPV6_LEAVE_GROUP = .IPV6_LEAVE_GROUP, ///
  1404. }
  1405. /*
  1406. * Need?
  1407. struct SocketOption {}
  1408. */
  1409. /**
  1410. * Socket is a class that creates a communication endpoint using the Berkeley sockets interface.
  1411. *
  1412. * Socket's method raises SocketException when internal operation returns error.
  1413. * If you want to know error detail, please use errno.
  1414. *
  1415. * Example:
  1416. * -----
  1417. * alias Socket!IPEndpoint IPSocket;
  1418. *
  1419. * auto site = "www.digitalmars.com";
  1420. * auto hints = new AddressInfo(AddressInfoFlags.ANY, AddressFamily.INET,
  1421. * SocketType.STREAM, ProtocolType.TCP);
  1422. *
  1423. * if (auto addrInfo = AddressInfo.getByNode(site, "http", hints)) {
  1424. * auto addr = addrInfo[0];
  1425. * auto socket = new IPSocket(addr);
  1426. *
  1427. * socket.connect(IPEndpoint(addr.ipAddress, addr.port));
  1428. * socket.send("GET / HTTP/1.0\r\nHOST: " ~ site ~ ":" ~ to!string(addr.port) ~"\r\n\r\n");
  1429. *
  1430. * int n;
  1431. * char[] result, buffer = new char[](100);
  1432. *
  1433. * while ((n = socket.receive(buffer)) > 0)
  1434. * result ~= buffer[0..n];
  1435. *
  1436. * write(result);
  1437. *
  1438. * socket.shutdown(SocketShutdown.BOTH);
  1439. * socket.close();
  1440. * }
  1441. * -----
  1442. */
  1443. class Socket(Endpoint) if (isEndpoint!Endpoint)
  1444. {
  1445. private:
  1446. socket_t handle_;
  1447. AddressFamily family_;
  1448. version(Windows) bool blocking_ = false; // Property to get or set whether the socket is blocking or nonblocking.
  1449. public:
  1450. /**
  1451. * Returns:
  1452. * the local machine's host name. Idea from mango.
  1453. */
  1454. @property
  1455. static string hostName()
  1456. {
  1457. char[256] result; // Host names are limited to 255 chars.
  1458. if (.gethostname(result.ptr, result.length) == _SocketError)
  1459. throw new SocketException("Unable to obtain host name", lastError());
  1460. return to!string(result.ptr);
  1461. }
  1462. /**
  1463. * Constructs a blocking socket. If a single protocol type exists to support
  1464. * this socket type within the address family, the ProtocolType may be omitted.
  1465. */
  1466. this(AddressFamily af, SocketType type, ProtocolType protocol = ProtocolType.ANY)
  1467. {
  1468. handle_ = cast(socket_t).socket(af, type, protocol);
  1469. if (handle_ == socket_t.init)
  1470. throw new SocketException("Unable to create socket", lastError());
  1471. family_ = af;
  1472. }
  1473. /// ditto
  1474. this(AddressInfo addressInfo)
  1475. in
  1476. {
  1477. assert(addressInfo, "AddressInfo must be initialized");
  1478. }
  1479. body
  1480. {
  1481. this(addressInfo.family, addressInfo.socketType, addressInfo.protocolType);
  1482. }
  1483. ~this()
  1484. {
  1485. if (handle_ != socket_t.init)
  1486. closeSocket(handle_);
  1487. }
  1488. /**
  1489. * Returns:
  1490. * underlying socket handle.
  1491. */
  1492. @property @safe
  1493. nothrow socket_t handle() const
  1494. {
  1495. return handle_;
  1496. }
  1497. /**
  1498. * Returns:
  1499. * the socket's address family.
  1500. */
  1501. @property @safe
  1502. nothrow AddressFamily family() const
  1503. {
  1504. return family_;
  1505. }
  1506. /**
  1507. * Gets and sets socket's blocking flag.
  1508. *
  1509. * When a socket is blocking, calls to receive(), accept(), and send()
  1510. * will block and wait for data/action.
  1511. * A non-blocking socket will immediately return instead of blocking.
  1512. */
  1513. @property
  1514. {
  1515. bool blocking() const
  1516. {
  1517. version(Windows)
  1518. {
  1519. return blocking_;
  1520. }
  1521. else version(BsdSockets)
  1522. {
  1523. return !(.fcntl(handle, F_GETFL, 0) & O_NONBLOCK);
  1524. }
  1525. }
  1526. void blocking(bool byes)
  1527. {
  1528. version(Windows)
  1529. {
  1530. uint num = !byes;
  1531. if (.ioctlsocket(handle_, FIONBIO, &num) == _SocketError)
  1532. goto err;
  1533. blocking_ = byes;
  1534. }
  1535. else version(BsdSockets)
  1536. {
  1537. int x = .fcntl(handle_, F_GETFL, 0);
  1538. if (x == -1)
  1539. goto err;
  1540. if (byes)
  1541. x &= ~O_NONBLOCK;
  1542. else
  1543. x |= O_NONBLOCK;
  1544. if (.fcntl(handle_, F_SETFL, x) == -1)
  1545. goto err;
  1546. }
  1547. return; // Success.
  1548. err:
  1549. throw new SocketException("Unable to set socket blocking", lastError());
  1550. }
  1551. }
  1552. /**
  1553. * Property that indicates if this is a valid, alive socket.
  1554. */
  1555. @property
  1556. bool isAlive() const
  1557. {
  1558. int type;
  1559. auto typesize = cast(socklen_t)type.sizeof;
  1560. return !.getsockopt(handle_, SOL_SOCKET, SO_TYPE, cast(char*)&type, &typesize);
  1561. }
  1562. /**
  1563. * Returns:
  1564. * the remote endpoint of this socket.
  1565. */
  1566. @property
  1567. Endpoint remoteEndpoint()
  1568. {
  1569. Endpoint endpoint;
  1570. socklen_t nameLen = cast(socklen_t)endpoint.nameLen;
  1571. if (.getpeername(handle_, endpoint.name, &nameLen) == _SocketError)
  1572. throw new SocketException("Unable to obtain remote socket address", lastError());
  1573. // enforce(endpoint.address.family == family_, "Endpoint family is mismatched");
  1574. return endpoint;
  1575. }
  1576. /**
  1577. * Returns:
  1578. * the local endpoint of this socket.
  1579. */
  1580. @property
  1581. Endpoint localEndpoint()
  1582. {
  1583. Endpoint endpoint;
  1584. socklen_t nameLen = cast(socklen_t)endpoint.nameLen;
  1585. if (.getsockname(handle_, endpoint.name, &nameLen) == _SocketError)
  1586. throw new SocketException("Unable to obtain local socket address", lastError());
  1587. // enforce(endpoint.address.family == family_, "Endpoint family is mismatched");
  1588. return endpoint;
  1589. }
  1590. /**
  1591. * Associates a local address with this socket.
  1592. */
  1593. void bind(ref const Endpoint addr)
  1594. {
  1595. version(Windows) // std.c.windows.winsock(original bind apply const) must go!
  1596. auto result = .bind(handle_, cast(sockaddr*)addr.name, addr.nameLen);
  1597. else
  1598. auto result = .bind(handle_, addr.name, addr.nameLen);
  1599. if (result == _SocketError)
  1600. throw new SocketException("Unable to bind socket", lastError());
  1601. }
  1602. /**
  1603. * Establishes a connection. If the socket is blocking, connect waits for
  1604. * the connection to be made. If the socket is nonblocking, connect
  1605. * returns immediately and the connection attempt is still in progress.
  1606. */
  1607. void connect(ref const Endpoint addr)
  1608. {
  1609. version(Windows) // std.c.windows.winsock(original connect apply const) must go!
  1610. auto result = .connect(handle_, cast(sockaddr*)addr.name, addr.nameLen);
  1611. else
  1612. auto result = .connect(handle_, addr.name, addr.nameLen);
  1613. if (result == _SocketError) {
  1614. int err = lastError();
  1615. if (!blocking) {
  1616. version(Windows)
  1617. {
  1618. if (WSAEWOULDBLOCK == err)
  1619. return;
  1620. }
  1621. else version(Posix)
  1622. {
  1623. if (EINPROGRESS == err)
  1624. return;
  1625. }
  1626. else
  1627. {
  1628. static assert(false);
  1629. }
  1630. }
  1631. throw new SocketException("Unable to connect socket", err);
  1632. }
  1633. }
  1634. /**
  1635. * Listens for an incoming connection. bind must be called before you can
  1636. * listen. The backlog is a request of how many pending incoming
  1637. * connections are queued until accept'ed.
  1638. */
  1639. void listen(int backlog)
  1640. {
  1641. if (.listen(handle_, backlog) == _SocketError)
  1642. throw new SocketException("Unable to listen on socket", lastError());
  1643. }
  1644. /**
  1645. * Accepts an incoming connection. If the socket is blocking, accept
  1646. * waits for a connection request. Throws SocketException if unable
  1647. * to accept. See accepting for use with derived classes.
  1648. */
  1649. Socket accept()
  1650. {
  1651. socket_t newsock;
  1652. newsock = cast(socket_t).accept(handle_, null, null);
  1653. if (newsock == socket_t.init)
  1654. throw new SocketException("Unable to accept socket connection", lastError());
  1655. auto newSocket = accepting();
  1656. newSocket.handle_ = newsock;
  1657. newSocket.family_ = family_; //same family
  1658. version(Windows) newSocket.blocking_ = blocking_; //inherits blocking mode
  1659. return newSocket;
  1660. }
  1661. /**
  1662. * Disables send and/or receive.
  1663. *
  1664. * Note:
  1665. * On Mac OS X, sometimes shutdown function returns error despite the non-failure.
  1666. * I don't understand this behavior(Mac-specified bug?).
  1667. */
  1668. void shutdown(SocketShutdown how)
  1669. {
  1670. if (.shutdown(handle_, cast(int)how) == _SocketError)
  1671. throw new SocketException("Unable to shutdown socket", lastError());
  1672. }
  1673. /**
  1674. * Immediately drop any connections and release socket resources.
  1675. * Calling shutdown before close is recommended for connection-oriented
  1676. * sockets. The Socket object is no longer usable after close.
  1677. *
  1678. * Note:
  1679. * Calling shutdown() before this is recommended for connection-oriented sockets
  1680. */
  1681. void close()
  1682. {
  1683. closeSocket(handle_);
  1684. handle_ = socket_t.init;
  1685. }
  1686. /**
  1687. * Sends data on the connection. If the socket is blocking and
  1688. * there is no buffer space left, send waits.
  1689. *
  1690. * Returns:
  1691. * the number of bytes actually sent, or -1 on error.
  1692. *
  1693. * Note:
  1694. * This method assumes you connect()ed.
  1695. */
  1696. int send(const(void)[] buf, SocketFlags flags = SocketFlags.NOSIGNAL)
  1697. {
  1698. flags |= SocketFlags.NOSIGNAL;
  1699. auto result = .send(handle_, buf.ptr, buf.length, cast(int)flags);
  1700. if (result == _SocketError)
  1701. throw new SocketE

Large files files are truncated, but you can click here to view the full file