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'
version = '1.1.0'
version = '1.2.0'
repositories {
mavenCentral()

View File

@ -4,33 +4,64 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
public class Connection implements Runnable {
private Socket s;
private InputStream is;
private OutputStream os;
private MessageDistributer md;
private String username;
public Connection(Socket s, MessageDistributer md) throws IOException {
this.s = s;
this.is = s.getInputStream();
this.os = s.getOutputStream();
this.md = md;
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;
}
username = buf;
username = buf.replace("\r", "").replace("\n", "").trim();
}
@Override
public void run() {
md.registerStream(this);
byte[] buf = new byte[1024];
try {
md.registerStream(this);
is.transferTo(md);
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);
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");
System.out.println("Connection disconnected unexpectedly");
MessageDistributer.closeUserConnection(this);
}
MessageDistributer.closeUserConnection(this);
}
public String getUsername() {
@ -44,4 +75,14 @@ public class Connection implements Runnable {
public void updateUsername(String 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,40 +5,85 @@ import java.io.OutputStream;
import java.nio.charset.StandardCharsets;
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 {
private static List<Connection> userStreams = new ArrayList<>();
private static MessageDistributer instance;
private String buf = "";
private byte[] buf = new byte[1024];
private short bufPointer = 0;
public MessageDistributer() {
instance = this;
}
@Override
public void write(int b) throws IOException {
buf += (char) b;
if (((char) b) == '\n') this.flush();
public void write(int b) {
buf[bufPointer] = ((byte) b);
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
public void flush() {
for (Connection conn : userStreams) {
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) {
e.printStackTrace();
}
}
buf = "";
bufPointer = 0;
}
private void writeSystem(String message) {
for (Connection conn : userStreams) {
try {
conn.getOutputStream().write(("SERVER> " + message + "\n").getBytes(StandardCharsets.UTF_8));
} catch (IOException e) {
e.printStackTrace();
}
public void sendUserConnect(String user) {
try {
this.write(0x1);
this.write((user + "\r\n").getBytes(StandardCharsets.UTF_8));
this.write(0xf);
this.flush();
} catch (IOException e) {
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();
}
}
@ -49,8 +94,18 @@ public class MessageDistributer extends OutputStream {
i++;
}
conn.updateUsername(username);
sendUserConnect(username);
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) {
@ -66,6 +121,7 @@ public class MessageDistributer extends OutputStream {
public static void closeUserConnection(Connection conn) {
userStreams.remove(conn);
getInstance().writeSystem(("Goodbye, " + conn.getUsername() + "!"));
getInstance().sendUserDisconnect(conn.getUsername());
getInstance().sendMessage("SERVER", ("Goodbye, " + conn.getUsername() + "!\r\n"));
}
}