1 module socks5d.client; 2 3 import socks5d.packets; 4 import socks5d.driver; 5 import socks5d.factory : f, logger, ConnectionImpl; 6 import socks5d.server; 7 import socks5d.auth; 8 9 class Client 10 { 11 package: 12 uint id; 13 14 protected: 15 Connection conn; 16 AuthManager authManager; 17 18 public: 19 this(Connection conn, uint id, AuthManager authManager) 20 { 21 assert(authManager !is null); 22 23 this.id = id; 24 this.authManager = authManager; 25 this.conn = conn; 26 } 27 28 final void run() 29 { 30 logger.diagnostic("[%d] New client accepted: %s", id, conn.remoteAddress); 31 scope (exit) conn.close(); 32 33 try { 34 if (authManager.authenticate(this)) { 35 Connection targetConn = handshake(); 36 scope (exit) { 37 targetConn.close(); 38 } 39 40 conn.duplexPipe(targetConn, id); 41 } 42 43 } catch (SocksException e) { 44 logger.error("Error: %s", e.msg); 45 } 46 47 logger.debugN("[%d] End of session", id); 48 } 49 50 package: 51 void send(P)(ref P packet) 52 if (isSocks5OutgoingPacket!P) 53 { 54 logger.debugV("[%d] send: %s", id, packet.printFields); 55 packet.send(conn); 56 } 57 58 void receive(P)(ref P packet) 59 if (isSocks5IncomingPacket!P) 60 { 61 packet.receive(conn); 62 logger.debugV("[%d] recv: %s", id, packet.printFields); 63 } 64 65 Connection handshake() 66 { 67 import std.socket : InternetAddress; 68 69 RequestPacket requestPacket = { connID: id }; 70 ResponsePacket responsePacket = { connID: id }; 71 72 try { 73 receive(requestPacket); 74 } catch (RequestException e) { 75 logger.warning("[%d] Error: %s", id, e.msg); 76 responsePacket.replyCode = e.replyCode; 77 send(responsePacket); 78 79 throw e; 80 } 81 82 logger.debugV("[%d] Connecting to %s:%d", id, requestPacket.getHost(), requestPacket.getPort()); 83 84 Connection targetConn = f.connection(); 85 targetConn.connect(new InternetAddress(requestPacket.getHost(), requestPacket.getPort())); 86 87 responsePacket.addressType = AddressType.IPV4; 88 responsePacket.setBindAddress( 89 targetConn.localAddress.addr, 90 targetConn.localAddress.port 91 ); 92 93 send(responsePacket); 94 95 return targetConn; 96 } 97 }