HelpWriting a proxy server

Posts 1–2 of 2 · Page 1 of 1
Writing a proxy server
Hello MPGH. I'm a hobby programmer and I've been playing with Java, C++ and some other languages for a few years. I have been playing this game for over 7 years and only recently wanted to start playing with the game after looking at NRelay. I decided I wanted to write a relay (proxy server). My language of choice is Java, I was going to go with TypeScript and Node but I don't have much experience with either.

I ran into a problem: no matter what I do, I can't send data between the client and the server. I started by creating a ServerSocket on port 2050 that waits and accepts a socket (new connection from a client), opens a connection to one of the game servers and just starts relaying. What I was doing was just read()-ing bytes and sending them to the opposite (client -> server, server -> client) but it just didn't work. I've looked at other projects but the code is just messy. I would appreciate it if someone could guide me or provide some tips. Thanks
Heres an implementation for a client only listener I made, just copy paste everything one more time and have the buffers for server/client sockets be written to eachother.
Code:
public class ClientListener implements Runnable {
    private Socket socket;
    private DataInputStream in;
    private DataOutputStream out;
    private boolean connected;

    private static final String RC4_OUTGOING_KEY = "c79332b197f92ba85ed281a023";
    private static final String RC4_INCOMING_KEY = "6a39570cc9de4ec71d64821894";
    private RC4 inRC4;
    private RC4 outRC4;

    public ClientListener(Socket socket) {
        this.socket = socket;
    }

     @override
    public void run() {
        try {
            System.out.println(" *** Connection from: " + this.socket.getInetAddress().getHostName() + " ***");

            this.in = new DataInputStream(this.socket.getInputStream());
            this.out = new DataOutputStream(this.socket.getOutputStream());

            this.connected = true;

            int bufferSize = -1;
            byte bufferId = -1;
            long lastData = System.currentTimeMillis();

            this.inRC4 = new RC4(RC4_INCOMING_KEY);
            this.outRC4 = new RC4(RC4_OUTGOING_KEY);

            while (this.connected) {
                try {
                    if (lastData > System.currentTimeMillis() + (1000 * 15)) this.disconnect(); // Exit loop after data timeout
                    if (this.in.available() >= 5 && bufferSize == -1) {
                        lastData = System.currentTimeMillis();

                        bufferSize = this.in.readInt() - 5;
                        bufferId = this.in.readByte();
                    } else if (this.in.available() >= bufferSize && bufferSize != -1) {
                        lastData = System.currentTimeMillis();

                        PacketType type = PacketType.fromId(bufferId);

                        byte[] buf = new byte[bufferSize];
                        this.in.readFully(buf);
                        bufferSize = -1;

                        if (type == PacketType.UNKNOWN) continue; // Dont bother if the packet is of an unknown type

                        buf = this.inRC4.cypher(buf);

                        ByteArrayInputStream bis = new ByteArrayInputStream(buf);
                        DataInputStream dis = new DataInputStream(bis);
                        try {
                            Packet p = type.create();
                            p.read(dis);
                            this.invokeOnPacket(p);
                        } catch (IOException e) {
                            e.printStackTrace();
                        } finally {
                            bis.close();
                            dis.close();
                        }
                    }
                    Thread.sleep(100); // Only check socket for connections 10 times / second to prevent cpu hogging
                } catch (Exception e) {
                    e.printStackTrace(); // debug
                    break;
                }
            }
        } catch (Exception e) {
            e.printStackTrace(); // debug
            this.disconnect();
        }
        this.disconnect();
    }

    private void sendPacket(Packet p) {
        if (!this.socket.isConnected()) return;

        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        DataOutputStream out = new DataOutputStream(baos);

        try {
            p.write(out);
        } catch (IOException e) {
            e.printStackTrace();
            return;
        } finally {
            try {
                baos.close();
                out.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        byte[] buf = this.outRC4.cypher(baos.toByteArray());
        try {
            this.out.writeInt(buf.length + 5);
            this.out.writeByte(p.getType().id);
            this.out.write(buf);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private void invokeOnPacket(Packet p) {}

    private void disconnect() {
        if (!this.connected) return;
        try {
            System.out.println(" *** Disconnected from: " + this.socket.getInetAddress().getHostName() + " ***");
            this.connected = false;
            this.socket.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
if you need help feel free to add me on discord: Ark Died#7316

also check out ruuseys jrelay on github
Posts 1–2 of 2 · Page 1 of 1

Post a Reply

Similar Threads

Tags for this Thread

None

Need help?