1 /** 2 Default socket type for Connection. 3 4 Copyright: Copyright Boris-Barboris 2017. 5 License: MIT 6 Authors: Boris-Barboris 7 */ 8 9 module dpeq.socket; 10 11 import core.time: Duration; 12 import std.socket; 13 14 import dpeq.exceptions; 15 16 17 18 /** 19 $(D std.socket.Socket) wrapper wich is compatible with PSQLConnection. 20 If you want to use custom socket type (vibe-d or any other), make it 21 duck-type and exception-compatible with this one. 22 */ 23 final class StdSocket 24 { 25 private Socket m_socket; 26 27 /// Underlying socket instance. 28 @property Socket socket() @safe pure { return m_socket; } 29 30 /// Establish connection to backend. Constructor is expected to throw Exception 31 /// if anything goes wrong. 32 this(string host, ushort port, Duration timeout) @trusted 33 { 34 if (host[0] == '/') 35 { 36 // Unix socket 37 version(Posix) 38 { 39 Address addr = new UnixAddress(host); 40 m_socket = new Socket(AddressFamily.UNIX, SocketType.STREAM); 41 m_socket.connect(addr); 42 } 43 else 44 assert(0, "Cannot connect using UNIX sockets on non-Posix OS"); 45 } 46 else 47 { 48 m_socket = new TcpSocket(); 49 // 20 minutes for both tcp_keepalive_time and tcp_keepalive_intvl 50 m_socket.setKeepAlive(1200, 1200); 51 // example of receive timeout: 52 // m_socket.setOption(SocketOptionLevel.SOCKET, SocketOption.RCVTIMEO, seconds(120)); 53 m_socket.connect(new InternetAddress(host, port)); 54 } 55 } 56 57 void close() nothrow @nogc @trusted 58 { 59 m_socket.shutdown(SocketShutdown.BOTH); 60 m_socket.close(); 61 } 62 63 /// Send whole byte buffer or throw. Throws: $(D PsqlSocketException). 64 auto send(const(ubyte)[] buf) @trusted 65 { 66 auto r = m_socket.send(buf); 67 if (r == Socket.ERROR) 68 throw new PsqlSocketException("Socket.ERROR on send"); 69 return r; 70 } 71 72 /// Fill byte buffer from the socket completely or throw. 73 /// Throws: $(D PsqlSocketException). 74 auto receive(ubyte[] buf) @trusted 75 { 76 auto r = m_socket.receive(buf); 77 if (r == 0 && buf.length > 0) 78 throw new PsqlSocketException("Connection closed"); 79 if (r == Socket.ERROR) 80 throw new PsqlSocketException("Socket.ERROR on receive: " ~ m_socket.getErrorText()); 81 return r; 82 } 83 }