diff --git a/source/eventcore/driver.d b/source/eventcore/driver.d index efb914f..594af4f 100644 --- a/source/eventcore/driver.d +++ b/source/eventcore/driver.d @@ -83,6 +83,7 @@ interface EventDriverSockets { StreamListenSocketFD listenStream(scope Address bind_address, AcceptCallback on_accept); void waitForConnections(StreamListenSocketFD sock, AcceptCallback on_accept); ConnectionState getConnectionState(StreamSocketFD sock); + bool getLocalAddress(StreamSocketFD sock, scope RefAddress dst); void setTCPNoDelay(StreamSocketFD socket, bool enable); void setKeepAlive(StreamSocketFD socket, bool enable); void read(StreamSocketFD socket, ubyte[] buffer, IOMode mode, IOCallback on_read_finish); @@ -232,12 +233,37 @@ interface EventDriverWatchers { bool releaseRef(WatcherID descriptor); } +final class RefAddress : Address { + version (Posix) import core.sys.posix.sys.socket : sockaddr, socklen_t; + version (Windows) import core.sys.windows.winsock2 : sockaddr, socklen_t; + + private { + sockaddr* m_addr; + socklen_t m_addrLen; + } + + this() @safe nothrow {} + this(sockaddr* addr, socklen_t addr_len) @safe nothrow { set(addr, addr_len); } + + override @property sockaddr* name() { return m_addr; } + override @property const(sockaddr)* name() const { return m_addr; } + override @property socklen_t nameLen() const { return m_addrLen; } + + void set(sockaddr* addr, socklen_t addr_len) @safe nothrow { m_addr = addr; m_addrLen = addr_len; } + + void cap(socklen_t new_len) + @safe nothrow { + assert(new_len <= m_addrLen, "Cannot grow size of a RefAddress."); + m_addrLen = new_len; + } +} + alias ConnectCallback = void delegate(StreamSocketFD, ConnectStatus); -alias AcceptCallback = void delegate(StreamListenSocketFD, StreamSocketFD); +alias AcceptCallback = void delegate(StreamListenSocketFD, StreamSocketFD, scope RefAddress remote_address); alias IOCallback = void delegate(StreamSocketFD, IOStatus, size_t); -alias DatagramIOCallback = void delegate(DatagramSocketFD, IOStatus, size_t, /*scope*/ Address); -alias DNSLookupCallback = void delegate(DNSLookupID, DNSStatus, /*scope*/ Address[]); +alias DatagramIOCallback = void delegate(DatagramSocketFD, IOStatus, size_t, scope RefAddress); +alias DNSLookupCallback = void delegate(DNSLookupID, DNSStatus, scope RefAddress[]); alias FileIOCallback = void delegate(FileFD, IOStatus, size_t); alias EventCallback = void delegate(EventID); alias SignalCallback = void delegate(SignalListenID, SignalStatus, int); diff --git a/source/eventcore/drivers/libasync.d b/source/eventcore/drivers/libasync.d index 69f2a3c..4b04b4f 100644 --- a/source/eventcore/drivers/libasync.d +++ b/source/eventcore/drivers/libasync.d @@ -99,6 +99,11 @@ final class LibasyncEventDriverSockets : EventDriverSockets { assert(false, "TODO!"); } + override bool getLocalAddress(StreamSocketFD sock, scope RefAddress dst) + { + assert(false, "TODO!"); + } + override void setTCPNoDelay(StreamSocketFD socket, bool enable) { assert(false, "TODO!"); diff --git a/source/eventcore/drivers/posix.d b/source/eventcore/drivers/posix.d index f1b5b2d..f9f98e9 100644 --- a/source/eventcore/drivers/posix.d +++ b/source/eventcore/drivers/posix.d @@ -324,8 +324,7 @@ final class PosixEventDriverSockets(Loop : PosixEventLoop) : EventDriverSockets foreach (i; 0 .. 20) { int sockfd; sockaddr_storage addr; - version (Windows) int addr_len = addr.sizeof; - else uint addr_len = addr.sizeof; + socklen_t addr_len = addr.sizeof; () @trusted { sockfd = accept(listenfd, () @trusted { return cast(sockaddr*)&addr; } (), &addr_len); } (); if (sockfd == -1) break; @@ -335,7 +334,8 @@ final class PosixEventDriverSockets(Loop : PosixEventLoop) : EventDriverSockets m_loop.m_fds[fd].specific = StreamSocketSlot.init; m_loop.registerFD(fd, EventMask.read|EventMask.write|EventMask.status); //print("accept %d", sockfd); - m_loop.m_fds[listenfd].streamListen.acceptCallback(cast(StreamListenSocketFD)listenfd, fd); + scope RefAddress addrc = new RefAddress(() @trusted { return cast(sockaddr*)&addr; } (), addr_len); + m_loop.m_fds[listenfd].streamListen.acceptCallback(cast(StreamListenSocketFD)listenfd, fd, addrc); } } @@ -344,6 +344,16 @@ final class PosixEventDriverSockets(Loop : PosixEventLoop) : EventDriverSockets return m_loop.m_fds[sock].streamSocket.state; } + bool getLocalAddress(StreamSocketFD sock, scope RefAddress dst) + { + socklen_t addr_len = dst.nameLen; + if (() @trusted { return getsockname(sock, dst.name, &addr_len); } () != 0) + return false; + dst.cap(addr_len); + return true; + } + + final override void setTCPNoDelay(StreamSocketFD socket, bool enable) { int opt = enable; @@ -643,9 +653,9 @@ final class PosixEventDriverSockets(Loop : PosixEventLoop) : EventDriverSockets assert(mode != IOMode.all, "Only IOMode.immediate and IOMode.once allowed for datagram sockets."); sizediff_t ret; - scope src_addr = new UnknownAddress(); - socklen_t src_addr_len = src_addr.nameLen; - () @trusted { ret = .recvfrom(socket, buffer.ptr, buffer.length, 0, src_addr.name, &src_addr_len); } (); + sockaddr_storage src_addr; + socklen_t src_addr_len = src_addr.sizeof; + () @trusted { ret = .recvfrom(socket, buffer.ptr, buffer.length, 0, cast(sockaddr*)&src_addr, &src_addr_len); } (); if (ret < 0) { auto err = getSocketError(); @@ -670,7 +680,8 @@ final class PosixEventDriverSockets(Loop : PosixEventLoop) : EventDriverSockets return; } - on_receive_finish(socket, IOStatus.ok, ret, src_addr); + scope src_addrc = new RefAddress(() @trusted { return cast(sockaddr*)&src_addr; } (), src_addr_len); + on_receive_finish(socket, IOStatus.ok, ret, src_addrc); } void cancelReceive(DatagramSocketFD socket) @@ -686,9 +697,9 @@ final class PosixEventDriverSockets(Loop : PosixEventLoop) : EventDriverSockets auto socket = cast(DatagramSocketFD)fd; sizediff_t ret; - scope src_addr = new UnknownAddress; - socklen_t src_addr_len = src_addr.nameLen; - () @trusted { ret = .recvfrom(socket, slot.readBuffer.ptr, slot.readBuffer.length, 0, src_addr.name, &src_addr_len); } (); + sockaddr_storage src_addr; + socklen_t src_addr_len = src_addr.sizeof; + () @trusted { ret = .recvfrom(socket, slot.readBuffer.ptr, slot.readBuffer.length, 0, cast(sockaddr*)&src_addr, &src_addr_len); } (); if (ret < 0) { auto err = getSocketError(); @@ -700,7 +711,8 @@ final class PosixEventDriverSockets(Loop : PosixEventLoop) : EventDriverSockets } m_loop.setNotifyCallback!(EventType.read)(socket, null); - () @trusted { return cast(DatagramIOCallback)slot.readCallback; } ()(socket, IOStatus.ok, ret, src_addr); + scope src_addrc = new RefAddress(() @trusted { return cast(sockaddr*)&src_addr; } (), src_addr.sizeof); + () @trusted { return cast(DatagramIOCallback)slot.readCallback; } ()(socket, IOStatus.ok, ret, src_addrc); } void send(DatagramSocketFD socket, const(ubyte)[] buffer, IOMode mode, Address target_address, DatagramIOCallback on_send_finish) @@ -1012,29 +1024,20 @@ private void passToDNSCallback(DNSLookupID id, scope DNSLookupCallback cb, DNSSt { import std.typecons : scoped; - static final class RefAddr : Address { - sockaddr* sa; - socklen_t len; - override @property sockaddr* name() { return sa; } - override @property const(sockaddr)* name() const { return sa; } - override @property socklen_t nameLen() const { return len; } - } - try { - typeof(scoped!RefAddr())[16] addrs_prealloc = [ - scoped!RefAddr(), scoped!RefAddr(), scoped!RefAddr(), scoped!RefAddr(), - scoped!RefAddr(), scoped!RefAddr(), scoped!RefAddr(), scoped!RefAddr(), - scoped!RefAddr(), scoped!RefAddr(), scoped!RefAddr(), scoped!RefAddr(), - scoped!RefAddr(), scoped!RefAddr(), scoped!RefAddr(), scoped!RefAddr() + typeof(scoped!RefAddress())[16] addrs_prealloc = [ + scoped!RefAddress(), scoped!RefAddress(), scoped!RefAddress(), scoped!RefAddress(), + scoped!RefAddress(), scoped!RefAddress(), scoped!RefAddress(), scoped!RefAddress(), + scoped!RefAddress(), scoped!RefAddress(), scoped!RefAddress(), scoped!RefAddress(), + scoped!RefAddress(), scoped!RefAddress(), scoped!RefAddress(), scoped!RefAddress() ]; //Address[16] addrs; - auto addrs = new Address[16]; // FIXME: avoid heap allocation + RefAddress[16] addrs; auto ai = ai_orig; size_t addr_count = 0; while (ai !is null && addr_count < addrs.length) { - RefAddr ua = new RefAddr;//addrs_prealloc[addr_count]; // FIXME: avoid heap allocation - ua.sa = ai.ai_addr; - ua.len = ai.ai_addrlen; + RefAddress ua = addrs_prealloc[addr_count]; // FIXME: avoid heap allocation + ua.set(ai.ai_addr, ai.ai_addrlen); addrs[addr_count] = ua; addr_count++; ai = ai.ai_next; @@ -1044,7 +1047,6 @@ private void passToDNSCallback(DNSLookupID id, scope DNSLookupCallback cb, DNSSt } catch (Exception e) assert(false, e.msg); } - final class PosixEventDriverEvents(Loop : PosixEventLoop) : EventDriverEvents { @safe: /*@nogc:*/ nothrow: private Loop m_loop; diff --git a/source/eventcore/drivers/winapi.d b/source/eventcore/drivers/winapi.d index 8389f6c..7808813 100644 --- a/source/eventcore/drivers/winapi.d +++ b/source/eventcore/drivers/winapi.d @@ -106,6 +106,11 @@ final class WinAPIEventDriverSockets : EventDriverSockets { assert(false, "TODO!"); } + override bool getLocalAddress(StreamSocketFD sock, scope RefAddress dst) + { + assert(false, "TODO!"); + } + override void setTCPNoDelay(StreamSocketFD socket, bool enable) { assert(false, "TODO!");