scp-app

git clone git://git.codymlewis.com/scp-app.git
Log | Files | Refs | LICENSE

Chat.java (7324B)


      1 import java.util.Scanner;
      2 import java.io.BufferedReader;
      3 import java.io.PrintWriter;
      4 import java.math.BigInteger;
      5 import java.io.IOException;
      6 import java.net.InetAddress;
      7 import java.net.Socket;
      8 import java.awt.FlowLayout;
      9 import java.awt.event.ActionEvent;
     10 import java.awt.event.ActionListener;
     11 import javax.swing.JFrame;
     12 import javax.swing.JTextArea;
     13 import javax.swing.JTextField;
     14 import javax.swing.JButton;
     15 import javax.swing.JLabel;
     16 import javax.swing.JScrollPane;
     17 import javax.swing.ScrollPaneConstants;
     18 import javax.swing.text.DefaultCaret;
     19 /**
     20  * Chat.java
     21  * Shared functions and variables between ChatServer and ChatClient
     22  *
     23  * @author Cody Lewis
     24  * @since 2018-08-19
     25  */
     26 public class Chat extends JFrame {
     27     protected PrintWriter out;
     28     protected BufferedReader in;
     29     protected Socket cliSocket;
     30     protected InetAddress address;
     31     protected int port;
     32     protected String username;
     33     protected String otherUsername;
     34     public static final long serialVersionUID = 1L;
     35     protected JTextArea msgArea;
     36     protected JTextField msgField;
     37     protected boolean disconnect;
     38     protected Thread recvMsg;
     39     protected boolean isRecieving;
     40     protected BigInteger sessionKey;
     41     /**
     42      * Enum of the various error codes returned by the classes
     43      */
     44     protected enum errorCodes {
     45         SCPERROR(-1),
     46         UNKNOWNHOSTERROR(-2),
     47         IOERROR(-3),
     48         NULLERROR(-4);
     49 
     50         private final int code; // error code variable
     51         /**
     52          * Default constructor
     53          */
     54         private errorCodes(int code) { this.code = code; }
     55         /**
     56          * Get the error code value
     57          * @return the error code of this
     58          */
     59         public int value() { return code; }
     60     }
     61     public Chat() {}
     62     /**
     63      * Input Constructor
     64      */
     65     public Chat(String title) {
     66         // Some sentinal values
     67         disconnect = false;
     68         isRecieving = true;
     69 
     70         // Construct the GUI
     71         setLayout(new FlowLayout());
     72         msgArea = new JTextArea(20, 55);
     73         // Make the text area have scrollback and auto scroll with text updates
     74         JScrollPane msgAScrollPane = new JScrollPane(msgArea);
     75         msgAScrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
     76         DefaultCaret caret = (DefaultCaret) msgArea.getCaret();
     77         caret.setUpdatePolicy(DefaultCaret.ALWAYS_UPDATE);
     78         add(msgAScrollPane);
     79         JLabel lbl = new JLabel("Message: ");
     80         add(lbl);
     81         msgField = new JTextField(30);
     82         add(msgField);
     83         // Some buttons with actions
     84         JButton msgBtn = new JButton("Send");
     85         add(msgBtn);
     86         msgBtn.addActionListener(new Send());
     87         JButton exitBtn = new JButton("Disconnect");
     88         add(exitBtn);
     89         exitBtn.addActionListener(new Exit());
     90         setTitle(title);
     91         setSize(700, 375);
     92         setVisible(true);
     93     }
     94     /**
     95      * Message sending action
     96      */
     97     private class Send implements ActionListener {
     98         @Override
     99         public void actionPerformed(ActionEvent evt) {
    100             try {
    101                 String[] messages = textToMessage();
    102                 for(String message : messages) {
    103                     msgArea.append("Waiting for message to send...\n");
    104                     out.println(SCP.message(address.getHostAddress(), port, message));
    105                     msgArea.append("Message Sent: " + AES.decrypt(sessionKey.toByteArray(), message) + "\n");
    106                 }
    107             } catch(Exception e) {
    108                 System.err.println("Error: " + e.getMessage());
    109             }
    110         }
    111     }
    112     /**
    113      * Message recieving thread
    114      */
    115     protected class Recieve implements Runnable {
    116         private String uname;
    117         /**
    118          * Input constructor
    119          */
    120         public Recieve(String uname) { this.uname = uname; }
    121         public void run() {
    122             try {
    123                 while(isRecieving) {
    124                     String recievedMessage = recieveMessage();
    125                     if(recievedMessage == "DISCONNECT") {
    126                         out.println(SCP.acknowledge());
    127                         msgArea.append("Other user disconnected\n");
    128                         recvMsg.interrupt();
    129                         disconnect = true;
    130                         isRecieving = false;
    131                     } else if(recievedMessage == "ACKNOWLEDGE") {
    132                         msgArea.append("Successfully disconnected\n");
    133                     } else {
    134                         msgArea.append(String.format("%s: %s\n", uname, recievedMessage));
    135                     }
    136                 }
    137             } catch(SCPException SCPe) {
    138                 System.err.println("Error: " + SCPe.getMessage());
    139             } catch(IOException ioe) {
    140                 System.err.println("Error: " + ioe.getMessage());
    141             } catch(NullPointerException npe) {
    142                 msgArea.append("\nUnexpected cut-off from other user\n");
    143                 recvMsg.interrupt();
    144                 disconnect = true;
    145                 isRecieving = false;
    146             }
    147         }
    148     }
    149     /**
    150      * Loop for sending a recieving messages
    151      */
    152     protected void messageLoop() throws SCPException, IOException {
    153         recvMsg = new Thread(new Recieve(otherUsername), "scp");
    154         recvMsg.start();
    155     }
    156     /**
    157      * Recieve a message from the other user
    158      */
    159     protected String recieveMessage() throws SCPException, IOException {
    160         String packet = "", line = "";
    161         while((line = in.readLine()).compareTo("SCP END") != 0) {
    162             packet += line + "\n";
    163         }
    164         if(SCP.parseDisconnect(packet)) {
    165             return "DISCONNECT";
    166         }
    167         if(SCP.parseAcknowledge(packet)) {
    168             return "ACKNOWLEDGE";
    169         }
    170         String message = SCP.parseMessage(packet, address.getHostAddress(), port);
    171         return AES.decrypt(sessionKey.toByteArray(), message);
    172     }
    173     /**
    174      * Disconnection event handler
    175      */
    176     private class Exit implements ActionListener {
    177         @Override
    178         public void actionPerformed(ActionEvent evt) {
    179             try {
    180                 recvMsg.interrupt();
    181                 isRecieving = false;
    182                 disconnect = true;
    183                 out.println(SCP.disconnect());
    184                 String message = recieveMessage();
    185                 if(message.compareTo("ACKNOWLEDGE") == 0) {
    186                     msgArea.append("Successfully disconnected\n");
    187                 } else {
    188                     throw new SCPException("Other user did not acknowledge disconnect");
    189                 }
    190             } catch(SCPException SCPe) {
    191                 System.err.println(SCPe.getMessage() + "\n");
    192             } catch(IOException ioe) {
    193                 System.err.println("Error: " + ioe.getMessage());
    194             }
    195         }
    196     }
    197     /**
    198      * Take an input from the users and give an out suitable to put into a message
    199      * @return A String of the input formatted to be embedded in a SCP message
    200      */
    201     protected String[] textToMessage() {
    202         try {
    203             String[] message = AES.encrypt(sessionKey.toByteArray(), msgField.getText());
    204             msgField.setText("");
    205             return message;
    206         } catch(Exception e) {
    207             System.out.println("Error: " + e.getMessage());
    208             return null;
    209         }
    210     }
    211 }