1 module hio.common; 2 3 import std.exception; 4 import std.conv; 5 import core.stdc.string: strerror; 6 import std.experimental.logger; 7 8 import core.sys.posix.sys.socket; 9 import core.stdc.string; 10 import core.stdc.errno; 11 import core.sys.posix.unistd; 12 13 auto s_strerror(T)(T e) @trusted { 14 return to!string(strerror(e)); 15 } 16 17 SocketPair makeSocketPair() @safe { 18 import core.sys.posix.fcntl; 19 int[2] pair; 20 auto r = (() @trusted => socketpair(AF_UNIX, SOCK_DGRAM, 0, pair))(); 21 if ( r == -1 ) { 22 throw new Exception(s_strerror(errno())); 23 } 24 auto flags = (() @trusted => fcntl(pair[0], F_GETFL, 0) | O_NONBLOCK)(); 25 (() @trusted => fcntl(pair[0], F_SETFL, flags))(); 26 flags = (() @trusted => fcntl(pair[1], F_GETFL, 0) | O_NONBLOCK)(); 27 (() @trusted => fcntl(pair[1], F_SETFL, flags))(); 28 SocketPair result; 29 result._pair = pair; 30 return result; 31 } 32 33 34 struct SocketPair { 35 int[2] _pair = [-1, -1]; 36 ~this() @safe { 37 (() @trusted => close())(); 38 } 39 public void close() { 40 if ( _pair[0] >= 0 ) { 41 core.sys.posix.unistd.close(_pair[0]); 42 } 43 if ( _pair[1] >= 0 ) { 44 core.sys.posix.unistd.close(_pair[1]); 45 } 46 _pair = [-1, -1]; 47 } 48 auto opIndex(size_t i) const { 49 return _pair[i]; 50 } 51 auto read(uint i, size_t len) @safe 52 { 53 enforce!Exception(i <= 1, "Index in socketpair must be 0 or 1"); 54 if ( len <= 0 ) { 55 throw new Exception("read length must be > 0"); 56 } 57 ubyte[] b = new ubyte[](len); 58 auto s = (() @trusted => core.sys.posix.unistd.read(_pair[i], b.ptr, len))(); 59 enforce!Exception(s > 0, "failed to read from socketpair"); 60 return b; 61 } 62 auto write(uint i, ubyte[] b) @safe { 63 return (() @trusted => core.sys.posix.unistd.write(_pair[i], b.ptr, b.length))(); 64 } 65 } 66 67 68 //class NotificationChannel { 69 // import containers; 70 71 // private enum NotificationType {Signal, Broadcast} 72 // 73 // private NotificationType _type = NotificationType.Signal; 74 // 75 // private SList!(void delegate() @safe) _subscribers; 76 // 77 // SocketPair _pipe; 78 // 79 // auto readEnd() const @safe @nogc { 80 // return _pipe[0]; 81 // } 82 // 83 // auto writeEnd() const @safe @nogc { 84 // return _pipe[1]; 85 // } 86 // 87 // void handler() @safe { 88 // with (NotificationType) final switch(_type) { 89 // case Signal: 90 // auto s = _subscribers.front; 91 // s(); 92 // break; 93 // case Broadcast: 94 // foreach(s; _subscribers) { 95 // s(); 96 // } 97 // break; 98 // } 99 // } 100 // 101 // this() @safe { 102 // _pipe = makeSocketPair(); 103 // } 104 // shared this() @safe { 105 // //_pipe = makeSocketPair(); 106 // } 107 // void subscribe(void delegate() @safe h) @safe { 108 // _subscribers ~= h; 109 // } 110 // void unsubscribe(void delegate() @safe h) @safe { 111 // _subscribers.remove(h); 112 // } 113 // 114 // auto signal() @property @safe @nogc { 115 // _type = NotificationType.Signal; 116 // ubyte[1] b = [0]; 117 // auto s = _pipe.write(1, b); 118 // return this; 119 // } 120 // auto broadcast() @property @safe @nogc { 121 // _type = NotificationType.Broadcast; 122 // ubyte[1] b = [0]; 123 // auto s = _pipe.write(1, b); 124 // return this; 125 // } 126 //} 127