Browse Source

Added most functionality to protocol drivers

proto
Thomas Johnson 3 years ago
parent
commit
61c5b271de
  1. 10
      proto/ProtoHandler.java
  2. 7
      proto/ProtoID.java
  3. 67
      proto/ProtoIn.java
  4. 105
      proto/ProtoOut.java
  5. 105
      sample/Main.java

10
proto/ProtoHandler.java

@ -1,10 +1,16 @@
package proto;
import java.util.ArrayList;
public interface ProtoHandler
{
void handleError(String username, byte msg[]);
void handleJoin(String username);
void handlePart(String username);
void handleListing(String username, String names[]);
void handleListing(String username, ArrayList<String> names);
void handleListingRequest(String username);
void handleUnknownCommand(byte id);
void handleMessage(String username, String message);
void handleFile(String username, String filename, byte data[]);
void handleUnknownCommand(int length, byte id, String username);
void handleClose();
}

7
proto/ProtoID.java

@ -13,15 +13,10 @@ public enum ProtoID
FILE((byte) 5),
INFO((byte) 6);
private byte b;
public byte b;
ProtoID(byte b)
{
this.b = b;
}
public byte b()
{
return b;
}
}

67
proto/ProtoIn.java

@ -1,8 +1,10 @@
package proto;
import java.io.DataInputStream;
import java.io.EOFException;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.stream.IntStream;
public class ProtoIn
{
@ -10,6 +12,11 @@ public class ProtoIn
public boolean loop;
private ProtoHandler handler;
public void init()
{
this.loop = true;
new Thread(() -> mainLoop()).start();
}
public ProtoIn(DataInputStream dis, ProtoHandler handler)
{
@ -17,25 +24,38 @@ public class ProtoIn
this.handler = handler;
}
private String readname() throws java.io.IOException
private String readName() throws java.io.IOException
{
byte length = dis.readByte();
byte[] bytes = {};
int length = Byte.toUnsignedInt(dis.readByte());
byte bytes[] = new byte[length];
dis.read(bytes, 0, length);
return new String(bytes, Charset.forName("UTF-8"));
}
void mainLoop()
private void mainLoop()
{
while (this.loop)
{
try {
byte id = dis.readByte();
int length = dis.readInt();
String username = readName();
switch (id)
{
case 0:
byte msg[] = new byte[length];
dis.read(msg, 0, length);
new Thread(() -> handler.handleError(username, msg));
break;
case 1:
IntStream.range(0, length).forEach((x) -> { try { dis.read(); } catch (Exception e) {} } );
new Thread(() -> handler.handleJoin(username)).start();
break;
case 2:
IntStream.range(0, length).forEach((x) -> { try { dis.read(); } catch (Exception e) {} } );
new Thread(() -> handler.handlePart(username)).start();
break;
case 3:
String username = readname();
if (length == 0)
{
Thread t = new Thread(() -> handler.handleListingRequest(username));
@ -46,18 +66,43 @@ public class ProtoIn
int a = 0;
while (a < length)
{
String name = readname();
a += name.length();
names.add(name);
int nLength = Byte.toUnsignedInt(dis.readByte());
byte bytes[] = new byte[nLength];
dis.read(bytes, 0, nLength);
a += nLength;
names.add(new String(bytes, "UTF-8"));
}
handler.handleListing(username, (String[]) names.toArray());
handler.handleListing(username, names);
}
break;
case 4:
byte[] msgb = new byte[length];
dis.read(msgb, 0, length);
String message = new String(msgb, "UTF-8");
new Thread(() -> handler.handleMessage(username, message)).start();
break;
case 5:
int fnlength = Byte.toUnsignedInt(dis.readByte());
byte fnameb[] = new byte[fnlength];
dis.read(fnameb, 0, fnlength);
String fname = new String(fnameb, "UTF-8");
int flen = length - fnlength - 1;
byte data[] = new byte[flen];
dis.read(data, 0, flen);
new Thread(() -> handler.handleFile(username, fname, data)).start();
break;
case 6:
// TODO
break;
default:
Thread t = new Thread(() -> handler.handleUnknownCommand(id));
Thread t = new Thread(() -> handler.handleUnknownCommand(length, id, username));
t.start();
}
} catch (Exception e) {} // Not much we can do about this
} catch (EOFException e)
{
this.loop = false;
handler.handleClose();
} catch (Exception e) { e.printStackTrace(); } // Not much we can do about this
}
}
}

105
proto/ProtoOut.java

@ -1,25 +1,110 @@
package proto;
import java.io.DataOutputStream;
import java.io.IOException;
import javafx.scene.chart.XYChart;
import java.io.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.stream.Collector;
import java.util.stream.Collectors;
public class ProtoOut
{
private DataOutputStream out;
private DataOutputStream real_out;
private ByteArrayOutputStream buffer;
public ProtoOut(DataOutputStream out)
{
this.out = out;
this.real_out = out;
this.buffer = new ByteArrayOutputStream();
this.out = new DataOutputStream(buffer);
}
public void requestUserList(String username) throws IOException
private void commit() throws java.io.IOException
{
real_out.write(buffer.toByteArray());
real_out.flush();
buffer = new ByteArrayOutputStream();
this.out = new DataOutputStream(buffer);
}
private void checkName(String name) throws IOException
{
if (username.length() > 127)
if (name.length() > 255)
throw new IOException("Username too long");
out.writeByte(3);
out.writeShort(0);
out.writeByte((byte) username.length());
out.writeUTF(username);
out.flush();
}
private void writeUserName(String name) throws IOException
{
checkName(name);
byte nameBytes[] = name.getBytes("UTF-8");
out.writeByte(nameBytes.length);
out.write(nameBytes);
}
public void sendJoin(String username) throws IOException
{
out.writeByte(ProtoID.JOIN.b);
out.writeInt(0);
writeUserName(username);
commit();
}
public void sendPart(String username) throws IOException
{
out.writeByte(ProtoID.PART.b);
out.writeInt(0);
writeUserName(username);
commit();
}
public void requestUserList(String username) throws IOException
{
out.writeByte(ProtoID.LISTING.b); // type: listing
out.writeInt(0); // length
writeUserName(username); // username
commit(); // Make it so!
}
public void giveUserListing(String username, String names[]) throws IOException
{
out.writeByte(ProtoID.LISTING.b);
// I can recognize bad code when I write it, and this is bad code.
out.writeInt(Arrays.asList(names).stream().collect(Collectors.summingInt((s) -> s.getBytes().length)));
writeUserName(username);
for (String n : names)
{
writeUserName(n);
}
commit();
}
public void sendMessage(String username, String message) throws IOException
{
out.writeByte(ProtoID.MESSAGE.b);
byte msgb[] = message.getBytes("UTF-8");
out.writeInt(msgb.length);
writeUserName(username);
out.write(msgb);
}
public void sendFile(String username, String filename, byte data[]) throws IOException
{
out.writeByte(ProtoID.FILE.b);
byte fnb[] = filename.getBytes("UTF-8");
if (fnb.length > 255)
throw new IOException("File name too long");
out.writeInt(fnb.length + data.length + 1);
writeUserName(username);
out.writeByte(fnb.length);
out.write(fnb);
out.write(data);
}
public void sendInfo(String username) throws IOException
{
// TODO
throw new IOException("not implemented");
}
}

105
sample/Main.java

@ -1,23 +1,102 @@
package sample;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
import proto.ProtoHandler;
import proto.ProtoIn;
import proto.ProtoOut;
public class Main extends Application {
import java.awt.desktop.OpenURIEvent;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
public class Main
{
public static void main(String[] args) throws IOException {
ServerSocket ss = new ServerSocket(25519);
Socket o = new Socket("127.0.0.1", 25519);
Socket i = ss.accept();
OutputStream os = o.getOutputStream();
InputStream is = i.getInputStream();
ProtoOut po = new ProtoOut(new DataOutputStream(os));
ProtoIn pi = new ProtoIn(new DataInputStream(is), new TestHandler());
pi.init();
po.requestUserList("me");
po.sendJoin("ji");
po.sendMessage("ji", "yeet me off Snell");
po.sendFile("ji", "yeet.jpg", new byte[]{1,2,3,4,5});
po.sendPart("ji");
po.requestUserList("aaaa");
o.close();
while (true)
{
// System.out.println(is.read());
}
}
}
class TestHandler implements ProtoHandler
{
public TestHandler() {}
@Override
synchronized public void handleError(String username, byte[] msg)
{
System.out.println("error");
}
@Override
synchronized public void handleJoin(String username)
{
System.out.println("joined: " + username);
}
@Override
synchronized public void handlePart(String username)
{
System.out.println("parted: " + username);
}
@Override
public void start(Stage primaryStage) throws Exception{
Parent root = FXMLLoader.load(getClass().getResource("sample.fxml"));
primaryStage.setTitle("Hello World");
primaryStage.setScene(new Scene(root, 300, 275));
primaryStage.show();
synchronized public void handleListing(String username, ArrayList<String> names)
{
System.out.println("listing for " + username);
for (String n : names)
{
System.out.println(n);
}
System.out.println("end listing");
}
@Override
synchronized public void handleListingRequest(String username)
{
System.out.println("listing request from " + username);
}
public static void main(String[] args) {
launch(args);
@Override
synchronized public void handleMessage(String username, String message)
{
System.out.println(username + ": " + message);
}
@Override
synchronized public void handleFile(String username, String filename, byte data[])
{
System.out.println(username + " sent a file called " + filename);
}
@Override
synchronized public void handleUnknownCommand(int length, byte id, String username)
{
System.out.print("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHHHHHHHHHHHHHHHHHHHHHHH!!!!!!!!!!!!!!!!!!!!! ");
System.out.println("(" + id + ")");
}
@Override
synchronized public void handleClose()
{
System.out.println("closed");
}
}
Loading…
Cancel
Save