1 module database.mysql.socket; 2 3 import core.stdc.errno; 4 5 import std.socket; 6 import std.exception; 7 import std.datetime; 8 9 import database.mysql.exception; 10 11 struct Socket 12 { 13 void connect(const(char)[] host, ushort port) 14 { 15 socket_ = new TcpSocket(); 16 socket_.connect(new InternetAddress(host, port)); 17 socket_.setOption(SocketOptionLevel.SOCKET, SocketOption.KEEPALIVE, true); 18 socket_.setOption(SocketOptionLevel.TCP, SocketOption.TCP_NODELAY, true); 19 socket_.setOption(SocketOptionLevel.SOCKET, SocketOption.SNDTIMEO, 30.seconds); 20 socket_.setOption(SocketOptionLevel.SOCKET, SocketOption.RCVTIMEO, 30.seconds); 21 } 22 23 bool connected() inout 24 { 25 return socket_ && socket_.isAlive(); 26 } 27 28 void close() 29 { 30 if (socket_) 31 { 32 socket_.shutdown(SocketShutdown.BOTH); 33 socket_.close(); 34 socket_ = null; 35 } 36 } 37 38 void read(ubyte[] buffer) 39 { 40 long len; 41 42 for (size_t off; off < buffer.length; off += len) 43 { 44 len = socket_.receive(buffer[off..$]); 45 46 if (len > 0) 47 { 48 continue; 49 } 50 else if (len == 0) 51 { 52 throw new MySQLConnectionException("Server closed the connection"); 53 } 54 else 55 { 56 if ((errno == EINTR) || (errno == EAGAIN)/* || (errno == EWOULDBLOCK)*/) 57 { 58 len = 0; 59 continue; 60 } 61 62 throw new MySQLConnectionException("Received std.socket.Socket.ERROR: " ~ formatSocketError(errno)); 63 } 64 } 65 } 66 67 void write(in ubyte[] buffer) 68 { 69 long len; 70 71 for (size_t off; off < buffer.length; off += len) 72 { 73 len = socket_.send(buffer[off..$]); 74 75 if (len > 0) 76 { 77 continue; 78 } 79 else if (len == 0) 80 { 81 throw new MySQLConnectionException("Server closed the connection"); 82 } 83 else 84 { 85 if ((errno == EINTR) || (errno == EAGAIN)/* || (errno == EWOULDBLOCK)*/) 86 { 87 len = 0; 88 continue; 89 } 90 91 throw new MySQLConnectionException("Sent std.socket.Socket.ERROR: " ~ formatSocketError(errno)); 92 } 93 } 94 } 95 96 private: 97 98 TcpSocket socket_; 99 }