Overhaul Protocol

This commit is contained in:
Steven Tracey 2024-01-16 10:28:00 -06:00
parent d863712c57
commit 6f0de554ae
6 changed files with 170 additions and 30 deletions

View File

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

View File

@ -30,9 +30,9 @@ public class ChatWindow extends JPanel {
return instance; return instance;
} }
public void resetConnection() { public void resetConnection(boolean error) {
connected = false; connected = false;
connStatus.setText("Disconnected: Socket Reset"); connStatus.setText(error ? "Disconnected: Socket Reset" : "Disconnected");
connectBtn.setText("Connect"); connectBtn.setText("Connect");
} }
@ -53,7 +53,7 @@ public class ChatWindow extends JPanel {
return; return;
} }
chat.setText(""); chat.setText("");
conn.setComponents(chat); conn.setComponents(chat, onlineUsers);
connStatus.setText("Connected"); connStatus.setText("Connected");
connectBtn.setText("Disconnect"); connectBtn.setText("Disconnect");
connected = true; connected = true;
@ -115,6 +115,12 @@ public class ChatWindow extends JPanel {
} }
} }
private void usernameKeyTyped(KeyEvent e) {
if (username.getText().length() > 15) {
e.consume();
}
}
private void initComponents() { private void initComponents() {
// JFormDesigner - Component initialization - DO NOT MODIFY //GEN-BEGIN:initComponents @formatter:off // JFormDesigner - Component initialization - DO NOT MODIFY //GEN-BEGIN:initComponents @formatter:off
connStatus = new JLabel(); connStatus = new JLabel();
@ -122,9 +128,11 @@ public class ChatWindow extends JPanel {
username = new JTextField(); username = new JTextField();
connAddr = new JTextField(); connAddr = new JTextField();
connectBtn = new JButton(); connectBtn = new JButton();
scrollPane = new JScrollPane(); chatScrollPane = new JScrollPane();
chat = new JTextArea(); chat = new JTextArea();
new SmartScroller(scrollPane, SmartScroller.VERTICAL, SmartScroller.END); new SmartScroller(chatScrollPane, SmartScroller.VERTICAL, SmartScroller.END);
onlineScrollPane = new JScrollPane();
onlineUsers = new JTextArea();
messageBox = new JTextField(); messageBox = new JTextField();
sendBtn = new JButton(); sendBtn = new JButton();
@ -168,6 +176,12 @@ public class ChatWindow extends JPanel {
usernameFocusLost(e); usernameFocusLost(e);
} }
}); });
username.addKeyListener(new KeyAdapter() {
@Override
public void keyTyped(KeyEvent e) {
usernameKeyTyped(e);
}
});
add(username, "cell 0 1,growy"); add(username, "cell 0 1,growy");
//---- connAddr ---- //---- connAddr ----
@ -201,18 +215,29 @@ public class ChatWindow extends JPanel {
}); });
add(connectBtn, "cell 2 1,grow"); add(connectBtn, "cell 2 1,grow");
//======== scrollPane ======== //======== chatScrollPane ========
{ {
scrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); chatScrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
scrollPane.setAutoscrolls(true); chatScrollPane.setAutoscrolls(true);
//---- chat ---- //---- chat ----
chat.setEditable(false); chat.setEditable(false);
chat.setFont(new Font("Tahoma", Font.PLAIN, 11)); chat.setFont(new Font("Tahoma", Font.PLAIN, 11));
chat.setLineWrap(true); chat.setLineWrap(true);
scrollPane.setViewportView(chat); chatScrollPane.setViewportView(chat);
} }
add(scrollPane, "cell 0 2 3 1,grow"); add(chatScrollPane, "cell 0 2 2 1,grow");
//======== onlineScrollPane ========
{
onlineScrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
onlineScrollPane.setAutoscrolls(true);
//---- onlineUsers ----
onlineUsers.setEditable(false);
onlineScrollPane.setViewportView(onlineUsers);
}
add(onlineScrollPane, "cell 2 2,grow");
//---- messageBox ---- //---- messageBox ----
messageBox.addKeyListener(new KeyAdapter() { messageBox.addKeyListener(new KeyAdapter() {
@ -242,8 +267,10 @@ public class ChatWindow extends JPanel {
private JTextField username; private JTextField username;
private JTextField connAddr; private JTextField connAddr;
private JButton connectBtn; private JButton connectBtn;
private JScrollPane scrollPane; private JScrollPane chatScrollPane;
private JTextArea chat; private JTextArea chat;
private JScrollPane onlineScrollPane;
private JTextArea onlineUsers;
private JTextField messageBox; private JTextField messageBox;
private JButton sendBtn; private JButton sendBtn;
// JFormDesigner - End of variables declaration //GEN-END:variables @formatter:on // JFormDesigner - End of variables declaration //GEN-END:variables @formatter:on

View File

@ -28,6 +28,7 @@ new FormModel {
"text": "Username" "text": "Username"
addEvent( new FormEvent( "java.awt.event.FocusListener", "focusGained", "usernameFocusGained", true ) ) addEvent( new FormEvent( "java.awt.event.FocusListener", "focusGained", "usernameFocusGained", true ) )
addEvent( new FormEvent( "java.awt.event.FocusListener", "focusLost", "usernameFocusLost", true ) ) addEvent( new FormEvent( "java.awt.event.FocusListener", "focusLost", "usernameFocusLost", true ) )
addEvent( new FormEvent( "java.awt.event.KeyListener", "keyTyped", "usernameKeyTyped", true ) )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 0 1,growy" "value": "cell 0 1,growy"
} ) } )
@ -49,7 +50,7 @@ new FormModel {
"value": "cell 2 1,grow" "value": "cell 2 1,grow"
} ) } )
add( new FormContainer( "javax.swing.JScrollPane", new FormLayoutManager( class javax.swing.JScrollPane ) ) { add( new FormContainer( "javax.swing.JScrollPane", new FormLayoutManager( class javax.swing.JScrollPane ) ) {
name: "scrollPane" name: "chatScrollPane"
"horizontalScrollBarPolicy": 31 "horizontalScrollBarPolicy": 31
"autoscrolls": true "autoscrolls": true
add( new FormComponent( "javax.swing.JTextArea" ) { add( new FormComponent( "javax.swing.JTextArea" ) {
@ -58,11 +59,22 @@ new FormModel {
"font": new java.awt.Font( "Tahoma", 0, 11 ) "font": new java.awt.Font( "Tahoma", 0, 11 )
"lineWrap": true "lineWrap": true
auxiliary() { auxiliary() {
"JavaCodeGenerator.postCreateCode": "new SmartScroller(scrollPane, SmartScroller.VERTICAL, SmartScroller.END);" "JavaCodeGenerator.postCreateCode": "new SmartScroller(chatScrollPane, SmartScroller.VERTICAL, SmartScroller.END);"
} }
} ) } )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 0 2 3 1,grow" "value": "cell 0 2 2 1,grow"
} )
add( new FormContainer( "javax.swing.JScrollPane", new FormLayoutManager( class javax.swing.JScrollPane ) ) {
name: "onlineScrollPane"
"horizontalScrollBarPolicy": 31
"autoscrolls": true
add( new FormComponent( "javax.swing.JTextArea" ) {
name: "onlineUsers"
"editable": false
} )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 2 2,grow"
} ) } )
add( new FormComponent( "javax.swing.JTextField" ) { add( new FormComponent( "javax.swing.JTextField" ) {
name: "messageBox" name: "messageBox"

View File

@ -9,14 +9,32 @@ import java.net.MalformedURLException;
import java.net.Socket; import java.net.Socket;
import java.security.KeyStore; import java.security.KeyStore;
import java.security.SecureRandom; import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/*
Commands:
- 0x1: User connect
- 0x2: User disconnect
- 0x3: Message
- 0x4: Online List
- 0xf: End of PDU
Usable: 0-f
*/
public class Connection { public class Connection {
private Socket s; private Socket s;
private InputStream is; private InputStream is;
private OutputStream os;
private PrintStream out; private PrintStream out;
private String username; private String username;
private JTextArea chat; private JTextArea chat;
private List<String> onlineList = new ArrayList<>();
public Connection(String username, String address) throws Exception { public Connection(String username, String address) throws Exception {
String[] addrSplit = address.split(":"); String[] addrSplit = address.split(":");
@ -38,33 +56,104 @@ public class Connection {
s = factory.createSocket(addrSplit[0], Integer.parseInt(addrSplit[1])); s = factory.createSocket(addrSplit[0], Integer.parseInt(addrSplit[1]));
is = s.getInputStream(); is = s.getInputStream();
OutputStream os = s.getOutputStream(); os = s.getOutputStream();
out = new PrintStream(os); out = new PrintStream(os);
this.username = username; this.username = username;
os.write(0x1);
out.println(username); out.println(username);
os.write(0xf);
} }
public void sendMessage(String message) { public void sendMessage(String message) {
out.println(message); try {
os.write(0x3);
out.println(message);
os.write(0xf);
os.flush();
} catch (IOException e) {
Notifier.errorPopup("Error Sending Message", e.getMessage());
}
} }
public void setComponents(JTextArea chat) { public void setComponents(JTextArea chat, JTextArea online) {
this.chat = chat; this.chat = chat;
new Thread(() -> { new Thread(() -> {
byte[] buf = new byte[1024];
ChatWriter chatWriter = new ChatWriter();
try { try {
is.transferTo(new ChatWriter()); while (!s.isClosed()) {
} catch (IOException ignored) {} byte cmd;
close(); try {
cmd = (byte) is.read();
} catch (IOException e) {
ChatWindow.getInstance().resetConnection(false);
break;
}
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 -> { // User Connect
addOnlineUser(new String(Arrays.copyOfRange(buf, 0, i )));
online.setText(getFormattedOnline());
}
case 0x2 -> { // User Disconnect
removeOnlineUser(new String(Arrays.copyOfRange(buf, 0, i)));
online.setText(getFormattedOnline());
}
case 0x3 -> {
byte[] msg = Arrays.copyOfRange(buf, 0, i);
chatWriter.write(msg); // Send Message
}
case 0x4 -> {
onlineList.clear();
onlineList.add(new String(Arrays.copyOfRange(buf, 0, i + 1)));
online.setText(getFormattedOnline());
}
}
}
} catch (IOException e) {
e.printStackTrace();
Notifier.errorPopup("Error While Closing Connection Thread", e.getMessage());
}
}).start(); }).start();
} }
public void close() { public void addOnlineUser(String username) {
try { onlineList.add(username);
s.close(); }
} catch (IOException e) {
e.printStackTrace(); public void removeOnlineUser(String username) {
onlineList.remove(username);
}
public String getFormattedOnline() {
StringBuilder sb = new StringBuilder();
for (String s : onlineList) {
sb.append(s.trim().replace("\r", "").replace("\n", ""));
sb.append("\n");
} }
ChatWindow.getInstance().resetConnection(); return sb.substring(0, sb.length());
}
public void close() {
if (!s.isClosed()) {
try {
os.write(0x2);
out.println(username);
os.write(0xf);
s.close();
} catch (IOException e) {
Notifier.errorPopup("Connection Reset By Server", e.getMessage());
ChatWindow.getInstance().resetConnection(true);
}
}
ChatWindow.getInstance().resetConnection(false);
} }
private class ChatWriter extends OutputStream { private class ChatWriter extends OutputStream {
@ -73,11 +162,19 @@ public class Connection {
@Override @Override
public void write(int b) { public void write(int b) {
buf += (char) b; buf += (char) b;
if (((char) b) == '\n') this.flush(); }
@Override
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() {
System.out.println(buf);
chat.append(buf); chat.append(buf);
Notifier.messageReceived(Main.getFrame()); Notifier.messageReceived(Main.getFrame());
//Notifier.sendNotification(buf.substring(0, buf.indexOf(">") - 1), buf.substring(buf.indexOf(">"))); //Notifier.sendNotification(buf.substring(0, buf.indexOf(">") - 1), buf.substring(buf.indexOf(">")));

View File

@ -9,7 +9,7 @@ import java.awt.*;
public class Main { public class Main {
private static final FlatDarkLaf DARK_LAF = new FlatDarkLaf(); private static final FlatDarkLaf DARK_LAF = new FlatDarkLaf();
private static final FlatLightLaf LIGHT_LAF = new FlatLightLaf(); private static final FlatLightLaf LIGHT_LAF = new FlatLightLaf();
private static TrayIcon trayIcon; //private static TrayIcon trayIcon;
private static JFrame frame; private static JFrame frame;
public static void main(String[] args) { public static void main(String[] args) {
@ -44,7 +44,7 @@ public class Main {
} }
SwingUtilities.updateComponentTreeUI(frame); SwingUtilities.updateComponentTreeUI(frame);
} catch (UnsupportedLookAndFeelException e) { } catch (UnsupportedLookAndFeelException e) {
e.printStackTrace(); Notifier.errorPopup("Error Setting Look and Feel", e.getMessage());
} }
} }

View File

@ -10,4 +10,8 @@ public class Notifier {
Taskbar.getTaskbar().requestWindowUserAttention(frame); Taskbar.getTaskbar().requestWindowUserAttention(frame);
} }
} }
public static void errorPopup(String title, String message) {
JOptionPane.showMessageDialog(null, message, title, JOptionPane.ERROR_MESSAGE);
}
} }