Overhaul protocol

This commit is contained in:
Steven Tracey 2024-01-16 10:19:22 -06:00
parent 795f020a98
commit 734505066f
3 changed files with 119 additions and 22 deletions

View File

@ -4,7 +4,7 @@ plugins {
} }
group = 'tech.nevets' group = 'tech.nevets'
version = '1.1.0' version = '1.2.0'
repositories { repositories {
mavenCentral() mavenCentral()

View File

@ -4,33 +4,64 @@ import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
import java.net.Socket; import java.net.Socket;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
public class Connection implements Runnable { public class Connection implements Runnable {
private Socket s;
private InputStream is; private InputStream is;
private OutputStream os; private OutputStream os;
private MessageDistributer md; private MessageDistributer md;
private String username; private String username;
public Connection(Socket s, MessageDistributer md) throws IOException { public Connection(Socket s, MessageDistributer md) throws IOException {
this.s = s;
this.is = s.getInputStream(); this.is = s.getInputStream();
this.os = s.getOutputStream(); this.os = s.getOutputStream();
this.md = md; this.md = md;
String buf = ""; String buf = "";
for (int i = is.read(); (char) i != '\n' && i != -1; i = is.read()) { if (is.read() != 0x1) throw new IOException("Unexpected Command");
for (int i = is.read(); i != 0xf && i != -1; i = is.read()) {
buf += (char) i; buf += (char) i;
} }
username = buf; username = buf.replace("\r", "").replace("\n", "").trim();
} }
@Override @Override
public void run() { public void run() {
try {
md.registerStream(this); md.registerStream(this);
is.transferTo(md); byte[] buf = new byte[1024];
} catch (IOException e) {
System.out.println("Connection Disconnected"); try {
loop: while (!s.isClosed()) {
byte cmd = (byte) is.read();
int i = 0;
for (byte b = (byte) is.read(); b != 0xf && i < 1023; b = (byte) is.read()) {
buf[i] = b;
i++;
} }
switch (cmd) {
case 0x1 -> md.sendUserConnect(new String(Arrays.copyOfRange(buf, 0, i))); // User Connect
case 0x2 -> {
MessageDistributer.closeUserConnection(this); MessageDistributer.closeUserConnection(this);
md.sendUserDisconnect(new String(Arrays.copyOfRange(buf, 0, i))); // User Disconnect
break loop;
}
case 0x3 -> md.sendMessage(username, new String(Arrays.copyOfRange(buf, 0, i))); // Send Message
}
}
if (!s.isClosed()) {
try {
s.close();
} catch (IOException e) {
e.printStackTrace();
}
}
} catch (IOException e) {
System.out.println("Connection disconnected unexpectedly");
MessageDistributer.closeUserConnection(this);
}
} }
public String getUsername() { public String getUsername() {
@ -44,4 +75,14 @@ public class Connection implements Runnable {
public void updateUsername(String username) { public void updateUsername(String username) {
this.username = username; this.username = username;
} }
public void sendOnline(String onlineList) {
try {
os.write(0x4);
os.write(onlineList.getBytes(StandardCharsets.UTF_8));
os.write(0xf);
} catch (IOException e) {
e.printStackTrace();
}
}
} }

View File

@ -5,41 +5,86 @@ import java.io.OutputStream;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.util.*; import java.util.*;
/*
Commands:
- 0x1: User connect
- 0x2: User disconnect
- 0x3: Message
- 0x4: Online List
- 0xff: End of PDU
Usable: 00 - 1f, 80 - ff
*/
public class MessageDistributer extends OutputStream { public class MessageDistributer extends OutputStream {
private static List<Connection> userStreams = new ArrayList<>(); private static List<Connection> userStreams = new ArrayList<>();
private static MessageDistributer instance; private static MessageDistributer instance;
private String buf = ""; private byte[] buf = new byte[1024];
private short bufPointer = 0;
public MessageDistributer() { public MessageDistributer() {
instance = this; instance = this;
} }
@Override @Override
public void write(int b) throws IOException { public void write(int b) {
buf += (char) b; buf[bufPointer] = ((byte) b);
if (((char) b) == '\n') this.flush(); bufPointer++;
}
public void write(byte[] b, int off, int len) throws IOException {
for (int i = 0 ; i < len; i++) {
write(b[off + i]);
}
flush();
} }
@Override @Override
public void flush() { public void flush() {
for (Connection conn : userStreams) { for (Connection conn : userStreams) {
try { try {
conn.getOutputStream().write((conn.getUsername() + "> " + buf).getBytes(StandardCharsets.UTF_8)); System.out.println("Sending to: " + conn.getUsername());
conn.getOutputStream().write(Arrays.copyOfRange(buf, 0, bufPointer));
conn.getOutputStream().flush();
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(); e.printStackTrace();
} }
} }
buf = ""; bufPointer = 0;
} }
private void writeSystem(String message) { public void sendUserConnect(String user) {
for (Connection conn : userStreams) {
try { try {
conn.getOutputStream().write(("SERVER> " + message + "\n").getBytes(StandardCharsets.UTF_8)); this.write(0x1);
this.write((user + "\r\n").getBytes(StandardCharsets.UTF_8));
this.write(0xf);
this.flush();
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(); e.printStackTrace();
} }
} }
public void sendUserDisconnect(String user) {
try {
this.write(0x2);
this.write((user + "\r\n").getBytes(StandardCharsets.UTF_8));
this.write(0xf);
this.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
public void sendMessage(String user, String message) {
try {
this.write(0x3);
this.write((user + "> " + message).getBytes(StandardCharsets.UTF_8));
this.write(0xf);
this.flush();
} catch (IOException e) {
e.printStackTrace();
}
} }
public void registerStream(Connection conn) { public void registerStream(Connection conn) {
@ -49,8 +94,18 @@ public class MessageDistributer extends OutputStream {
i++; i++;
} }
conn.updateUsername(username); conn.updateUsername(username);
sendUserConnect(username);
userStreams.add(conn); userStreams.add(conn);
writeSystem("Welcome " + username + "!"); conn.sendOnline(getOnlineList());
sendMessage("SERVER", "Welcome " + username + "!\r\n");
}
private String getOnlineList() {
StringBuilder sb = new StringBuilder();
for (Connection c : userStreams) {
sb.append(c.getUsername()).append("\n");
}
return sb.toString();
} }
private boolean existingUsername(String username) { private boolean existingUsername(String username) {
@ -66,6 +121,7 @@ public class MessageDistributer extends OutputStream {
public static void closeUserConnection(Connection conn) { public static void closeUserConnection(Connection conn) {
userStreams.remove(conn); userStreams.remove(conn);
getInstance().writeSystem(("Goodbye, " + conn.getUsername() + "!")); getInstance().sendUserDisconnect(conn.getUsername());
getInstance().sendMessage("SERVER", ("Goodbye, " + conn.getUsername() + "!\r\n"));
} }
} }