diff --git a/src/GUI/DrawingArea.java b/src/GUI/DrawingArea.java
new file mode 100644
index 0000000000000000000000000000000000000000..380c4958e7992cc7ea39b0ceaefcbc9b1543133c
--- /dev/null
+++ b/src/GUI/DrawingArea.java
@@ -0,0 +1,339 @@
+package GUI;
+
+import javax.imageio.ImageIO;
+import javax.swing.*;
+import java.awt.*;
+import java.awt.event.*;
+import java.awt.geom.Ellipse2D;
+import java.awt.geom.Line2D;
+import java.awt.geom.Rectangle2D;
+import java.awt.geom.RectangularShape;
+import java.awt.image.BufferedImage;
+import java.io.File;
+import java.io.IOException;
+
+public class DrawingArea extends JPanel {
+
+    /// enum for all different mode ///
+    enum Mode { FREEHAND, LINE, CIRCLE, RECTANGLE, OVAL, ERASE }
+
+    /// Canvas size parameter ///
+    private final static int AREA_WIDTH = 600;
+    private final static int AREA_HEIGHT = 500;
+
+    /// Shape to be drawn on the canvas ///
+    private Shape drawing;
+
+    private Point startPoint;
+    private Point previousPoint;
+    private Point currentPoint;
+
+    /// Default mode and color ///
+    private Color shapeColor = new Color(0, 0, 0);
+    private Mode currentMode = Mode.FREEHAND;
+
+    /// Create a empty canvas ///
+    private BufferedImage image = new BufferedImage(AREA_WIDTH, AREA_HEIGHT, BufferedImage.TYPE_INT_ARGB);
+
+    /// Drawing tool
+    private Graphics2D g2 = (Graphics2D) image.getGraphics();
+
+
+
+    public DrawingArea() {
+
+        setBackground(Color.WHITE); // Set Background color
+        setDoubleBuffered(false);   // Non-buffered drawing
+
+        /// Antialiasing the graphic for smoothness ///
+        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
+
+
+/// Mouse listeners for pressing///
+        addMouseListener(new MouseAdapter() {
+            public void mousePressed(MouseEvent e) {
+
+                startPoint = previousPoint = e.getPoint();
+
+/// Instantiate object based on current mode ///
+                switch (currentMode) {
+
+                    case FREEHAND:
+                    case LINE:
+
+                        drawing = new Line2D.Double();
+                        break;
+
+                    case ERASE:
+                    case CIRCLE:
+                    case OVAL:
+
+                        drawing = new Ellipse2D.Double();
+                        break;
+
+                    case RECTANGLE:
+
+                        drawing = new Rectangle2D.Double();
+                        break;
+                }
+            }
+        });
+
+/// Mouse motion listeners for dragging ///
+        addMouseMotionListener(new MouseMotionAdapter() {
+            public void mouseDragged(MouseEvent e) {
+
+                currentPoint = e.getPoint();
+
+                int x = Math.min(startPoint.x, e.getX());
+                int y = Math.min(startPoint.y, e.getY());
+                int width = Math.abs(startPoint.x - e.getX());
+                int height = Math.abs(startPoint.y - e.getY());
+
+                switch (currentMode) {
+
+/// Freehand drawing is continuously drawing line from current point to previous point ///
+                    case FREEHAND:
+
+                        ((Line2D) drawing).setLine(currentPoint, previousPoint);
+                        g2.setColor(shapeColor);
+                        g2.draw(drawing);
+                        previousPoint = currentPoint;
+                        break;
+
+/// Single line ///
+                    case LINE:
+
+                        ((Line2D) drawing).setLine(startPoint, currentPoint);
+                        break;
+
+/// Eraser is continuously drawing "small white circle" from current point to previous point ///
+                    case ERASE:
+
+                        ((Ellipse2D) drawing).setFrame(currentPoint.getX(), currentPoint.getY(), 10, 10);
+                        g2.setColor(Color.WHITE);
+                        g2.fill(drawing);
+                        g2.draw(drawing);
+                        break;
+
+/// Single circle (How to draw more intuitively?)///
+                    case CIRCLE:
+
+                        double radius = Math.sqrt(width * width + height * height);
+//                        ((Ellipse2D) drawing).setFrame(x, y, radius, radius);
+                        ((Ellipse2D) drawing).setFrame(startPoint.getX() - radius, startPoint.getY() - radius, 2 * radius, 2 * radius);
+                        break;
+
+/// Single oval ///
+                    case OVAL:
+
+                        ((Ellipse2D) drawing).setFrame(x, y, width, height);
+                        break;
+
+/// Single rectangle ///
+                    case RECTANGLE:
+
+                        ((Rectangle2D) drawing).setFrame(x, y, width, height);
+                        break;
+                }
+
+                repaint();
+
+
+            }
+        });
+
+/// Mouse listener for releasing ///
+        addMouseListener(new MouseAdapter() {
+            public void mouseReleased(MouseEvent e) {
+
+/// Draw the final drawing to the buffered image ///
+                switch (currentMode) {
+                    case OVAL:
+                    case RECTANGLE:
+                    case CIRCLE:
+
+/// Abort drawing if 2D has no width or height ///
+                        if (((RectangularShape) drawing).getWidth() == 0 || ((RectangularShape) drawing).getHeight() == 0) {
+                            break;
+                        }
+                    case FREEHAND:
+                    case LINE:
+//                        Graphics2D g2 = (Graphics2D) image.getGraphics();
+                        g2.setColor(shapeColor);
+
+/// Uncomment the line below to fill the shapes with color ///
+//                        g2.fill(drawing);
+                        g2.draw(drawing);
+                }
+
+                g2 = (Graphics2D) image.getGraphics();
+                g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
+                g2.setColor(shapeColor);
+                
+/// This repaint is needed if we want to fill the drawing shape with color                
+                repaint();
+
+                drawing = null;
+            }
+        });
+    }
+
+
+
+    @Override
+    public Dimension getPreferredSize()
+    {
+        return isPreferredSizeSet() ?
+                super.getPreferredSize() : new Dimension(AREA_WIDTH, AREA_HEIGHT);
+    }
+
+/// Create a white image to clear previous drawing ///
+    public void clear() {
+
+        image = new BufferedImage(AREA_WIDTH, AREA_HEIGHT, BufferedImage.TYPE_INT_ARGB);
+        g2 = (Graphics2D) image.getGraphics();
+        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
+        repaint();
+
+    }
+
+    @Override
+    protected void paintComponent(Graphics g) {
+        super.paintComponent(g);
+
+/// Draw the whole image on JPanel ///
+        if (image != null) {
+                g.drawImage(image, 0, 0, null);
+            }
+
+/// Draw temporary shape ///
+        if (drawing != null) {
+            Graphics2D g2 = (Graphics2D) g;
+
+/// Eraser has no border color ///
+            Color borderColor = currentMode != Mode.ERASE ? shapeColor : Color.WHITE;
+            g2.setColor(borderColor);
+            g2.draw(drawing);
+        }
+    }
+
+/// File manipulations (PNG only) ///
+    public void saveFile() {
+        try {
+            ImageIO.write(image, "PNG", new File("Saved_White_Board.png"));
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+    }
+
+    public void saveAsFile(File file) {
+        try {
+            ImageIO.write(image, "PNG", file);
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+    }
+
+    public void openFile(File file) {
+        try {
+            image = ImageIO.read(file);
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+        repaint();
+    }
+
+/// Drawing mode setters ///
+
+    public void setModeFreehand() {
+        currentMode = Mode.FREEHAND;
+    }
+
+    public void setModeLine() {
+        currentMode = Mode.LINE;
+    }
+
+    public void setModeCircle() {
+        currentMode = Mode.CIRCLE;
+    }
+
+    public void setModeRectangle() {
+        currentMode = Mode.RECTANGLE;
+    }
+
+    public void setModeOval() {
+        currentMode = Mode.OVAL;
+    }
+
+    public void setModeErase() {
+        currentMode = Mode.ERASE;
+    }
+
+/// Drawing color setters ///
+
+    public void setColorAqua() {
+        shapeColor = new Color(0,255, 255);
+    }
+
+    public void setColorBlack() {
+        shapeColor = new Color(0, 0, 0);
+    }
+
+    public void setColorBlue() {
+        shapeColor = new Color(0, 0, 255);
+    }
+
+    public void setColorFuchsia() {
+        shapeColor = new Color(255, 0, 255);
+    }
+
+    public void setColorGray() {
+        shapeColor = new Color(128, 128, 128);
+    }
+
+    public void setColorGreen() {
+        shapeColor = new Color(0, 128, 0);
+    }
+
+    public void setColorLime() {
+        shapeColor = new Color(0, 255, 0);
+    }
+
+    public void setColorMaroon() {
+        shapeColor = new Color(128,0, 0);
+    }
+
+    public void setColorNavy() {
+        shapeColor = new Color(0, 0, 128);
+    }
+
+    public void setColorOlive() {
+        shapeColor = new Color(128, 128, 0);
+    }
+
+    public void setColorPurple() {
+        shapeColor = new Color(128, 0, 128);
+    }
+
+    public void setColorRed() {
+        shapeColor = new Color(255, 0, 0);
+    }
+
+    public void setColorSilver() {
+        shapeColor = new Color(192, 192, 192);
+    }
+
+    public void setColorTeal() {
+        shapeColor = new Color(0, 128, 128);
+    }
+
+    public void setColorWhite() {
+        shapeColor = new Color(255, 255, 255);
+    }
+
+    public void setColorYellow() {
+        shapeColor = new Color(255, 255, 0);
+    }
+
+}
\ No newline at end of file
diff --git a/src/GUI/MenuBar.java b/src/GUI/MenuBar.java
new file mode 100644
index 0000000000000000000000000000000000000000..b466e4b9cbe917d1c2acd97dee35ef4d995acfd8
--- /dev/null
+++ b/src/GUI/MenuBar.java
@@ -0,0 +1,7 @@
+package GUI;
+
+import javax.swing.*;
+
+public class MenuBar extends JMenuBar {
+    JButton clearBtn, newBtn, openBtn, saveBtn, saveAsBtn, closeBtn;
+}
diff --git a/src/GUI/ToolBar.java b/src/GUI/ToolBar.java
new file mode 100644
index 0000000000000000000000000000000000000000..04087e80db705c26881b58bcde46bfead77687d7
--- /dev/null
+++ b/src/GUI/ToolBar.java
@@ -0,0 +1,100 @@
+package GUI;
+
+import javax.swing.*;
+import java.awt.*;
+
+public class ToolBar extends JPanel {
+    private DrawingArea drawingArea;
+
+    public ToolBar() {
+
+    }
+}
+
+class Tools extends JPanel {
+
+}
+
+class ColorPallete extends JPanel {
+    private Color color;
+
+    public ColorPallete() {
+        this.color = new Color(0, 0, 0);    // Black
+    }
+
+    public void setColor(Color color) {
+        this.color = color;
+    }
+
+    public void setColorRBG(int r, int b, int g) {
+        this.color = new Color(r, b, g);
+    }
+
+    public Color getColor() {
+        return this.color;
+    }
+
+    public void setColorAqua() {
+        this.color = new Color(0,255, 255);
+    }
+
+    public void setColorBlack() {
+        this.color = new Color(0, 0, 0);
+    }
+
+    public void setColorBlue() {
+        this.color = new Color(0, 0, 255);
+    }
+
+    public void setColorFuchsia() {
+        this.color = new Color(255, 0, 255);
+    }
+
+    public void setColorGray() {
+        this.color = new Color(128, 128, 128);
+    }
+
+    public void setColorGreen() {
+        this.color = new Color(0, 128, 0);
+    }
+
+    public void setColorLime() {
+        this.color = new Color(0, 255, 0);
+    }
+
+    public void setColorMaroon() {
+        this.color = new Color(128,0, 0);
+    }
+
+    public void setColorNavy() {
+        this.color = new Color(0, 0, 128);
+    }
+
+    public void setColorOlive() {
+        this.color = new Color(128, 128, 0);
+    }
+
+    public void setColorPurple() {
+        this.color = new Color(128, 0, 128);
+    }
+
+    public void setColorRed() {
+        this.color = new Color(255, 0, 0);
+    }
+
+    public void setColorSilver() {
+        this.color = new Color(192, 192, 192);
+    }
+
+    public void setColorTeal() {
+        this.color = new Color(0, 128, 128);
+    }
+
+    public void setColorWhite() {
+        this.color = new Color(255, 255, 255);
+    }
+
+    public void setColorYellow() {
+        this.color = new Color(255, 255, 0);
+    }
+}
\ No newline at end of file
diff --git a/src/client/Client.java b/src/client/Client.java
new file mode 100644
index 0000000000000000000000000000000000000000..7538b770a977b0e48b04eb27ae0fe687891fe653
--- /dev/null
+++ b/src/client/Client.java
@@ -0,0 +1,75 @@
+package client;
+
+import java.net.InetAddress;
+import java.rmi.Remote;
+import java.rmi.registry.LocateRegistry;
+import java.rmi.registry.Registry;
+import java.rmi.server.UnicastRemoteObject;
+import java.util.ArrayList;
+import java.util.Scanner;
+
+import remote.IClientController;
+import remote.IDrawingController;
+import remote.IUpdateController;
+
+/**
+ * This class retrieves a reference to the remote object from the RMI registry.
+ * It invokes the methods on the remote object as if it was a local object of the type of the
+ * remote interface.
+ *
+ */
+public class Client {
+    private static int id;
+
+    public static void main(String[] args) {
+        Scanner keyboard = new Scanner(System.in);
+
+        try {
+            //Connect to the rmiregistry that is running on localhost
+            Registry registryServer = LocateRegistry.getRegistry("localhost");
+//            Registry registryServer = LocateRegistry.getRegistry("10.13.64.162");
+
+            IClientController clientController = (IClientController) registryServer.lookup("ClientController");
+
+            //Create rmiregistry for server to send commands that requests client to update drawing, chat, etc...
+            IUpdateController updateController = new UpdateController();
+            Registry registryClient = LocateRegistry.getRegistry();
+            registryClient.rebind("UpdateController", updateController);
+
+            // RMI client will give a stub of itself to the server
+//            Remote aRemoteObj = (Remote) UnicastRemoteObject.exportObject(new UpdateController(), 0);
+
+
+            //Call methods on the remote object as if it was a local object
+            System.out.println("Client: calling remote methods");
+
+            String result = clientController.joinServer("Hai", InetAddress.getLocalHost(), "UpdateController");
+            System.out.println(result);
+
+            // Test commands
+            ArrayList<String> usernameList = new ArrayList<>();
+            String command;
+            while(true) {
+                command = keyboard.nextLine();
+                switch (command) {
+                    case "test1":
+                        usernameList = clientController.getUsernameList();
+                        if (!usernameList.isEmpty()) {
+                            for (int i = 0; i < usernameList.size(); i++) {
+                                System.out.println(usernameList.get(i));
+                            }
+                        }
+                        break;
+                    default:
+                        System.out.println("nothing");
+                        break;
+                }
+            }
+
+        }catch(Exception e) {
+            e.printStackTrace();
+        }
+
+    }
+
+}
\ No newline at end of file
diff --git a/src/client/Client2.java b/src/client/Client2.java
new file mode 100644
index 0000000000000000000000000000000000000000..8d01a53df569ed35d383028c8f786c97b28d7abf
--- /dev/null
+++ b/src/client/Client2.java
@@ -0,0 +1,47 @@
+package client;
+
+import remote.IClientController;
+import remote.IDrawingController;
+import remote.IUpdateController;
+
+import java.net.InetAddress;
+import java.rmi.registry.LocateRegistry;
+import java.rmi.registry.Registry;
+
+/**
+ * This class retrieves a reference to the remote object from the RMI registry.
+ * It invokes the methods on the remote object as if it was a local object of the type of the
+ * remote interface.
+ *
+ */
+public class Client2 {
+    private static int id;
+
+    public static void main(String[] args) {
+
+
+        try {
+            //Connect to the rmiregistry that is running on localhost
+            Registry registryServer = LocateRegistry.getRegistry("localhost");
+            IDrawingController drawingController = (IDrawingController) registryServer.lookup("DrawingController");
+            IClientController clientController = (IClientController) registryServer.lookup("ClientController");
+
+            //Create rmiregistry for server to send commands that requests client to update drawing, chat, etc...
+            IUpdateController updateController = new UpdateController();
+            Registry registryClient = LocateRegistry.getRegistry();
+            registryClient.rebind("UpdateController", updateController);
+
+            //Call methods on the remote object as if it was a local object
+            System.out.println("Client: calling remote methods");
+
+            String result = clientController.joinServer("HaiHai", InetAddress.getLocalHost(), "UpdateController");
+            System.out.println(result);
+            while(true);
+
+        }catch(Exception e) {
+            e.printStackTrace();
+        }
+
+    }
+
+}
\ No newline at end of file
diff --git a/src/client/ClientCanvas.java b/src/client/ClientCanvas.java
new file mode 100644
index 0000000000000000000000000000000000000000..88d13cce50fca20e3d835b80a31c1f5431d4ec22
--- /dev/null
+++ b/src/client/ClientCanvas.java
@@ -0,0 +1,44 @@
+package client;
+
+import GUI.DrawingArea;
+import remote.IClientController;
+import remote.IDrawingController;
+import server.User;
+
+import java.rmi.registry.LocateRegistry;
+import java.rmi.registry.Registry;
+import java.util.ArrayList;
+import java.util.Observable;
+
+public class ClientCanvas extends Observable {
+
+    private static int id=1;
+    private IClientController clientController;
+    private IDrawingController drawingController;
+    private ArrayList<User> users;
+    private DrawingArea drawing;
+
+    public ClientCanvas() {
+        users = new ArrayList<>();
+        drawing = new DrawingArea();
+        try {
+            //Connect to the rmiregistry that is running on localhost
+            Registry registry = LocateRegistry.getRegistry("localhost");
+
+            //Retrieve the stub/proxy for the remote math object from the registry
+            this.drawingController = (IDrawingController) registry.lookup("DrawingController");
+            this.clientController = (IClientController) registry.lookup("ClientController");
+
+            //Call methods on the remote object as if it was a local object
+            System.out.println("Client: calling remote methods");
+
+//            clientController.addClient(id);
+
+        }catch(Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+
+
+}
\ No newline at end of file
diff --git a/src/client/DrawingArea.java b/src/client/DrawingArea.java
index 4bd67e64820af78685bc9cc8a1a7639c4fcb8030..25bebca63d869427c4f7448a84c85834c56fab7e 100644
--- a/src/client/DrawingArea.java
+++ b/src/client/DrawingArea.java
@@ -1,5 +1,3 @@
-package client;
-
 import javax.imageio.ImageIO;
 import javax.swing.*;
 import java.awt.*;
@@ -47,7 +45,7 @@ public class DrawingArea extends JPanel {
     public DrawingArea() {
 
 /// Antialiasing the graphic for smoothness ///
-//        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
+        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
 
 /// Set Background color ///
         setBackground(Color.WHITE);
@@ -176,8 +174,8 @@ public class DrawingArea extends JPanel {
                 g2 = (Graphics2D) image.getGraphics();
                 g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
                 g2.setColor(shapeColor);
-
-/// This repaint is needed if we want to fill the drawing shape with color
+                
+/// This repaint is needed if we want to fill the drawing shape with color                
                 repaint();
 
                 drawing = null;
diff --git a/src/client/PaintGUI.java b/src/client/PaintGUI.java
index 02ea1bce4399175d6903809aea3653751cd2046e..df27b3bdebd88e706e0e4cae0569bc77385b8e47 100644
--- a/src/client/PaintGUI.java
+++ b/src/client/PaintGUI.java
@@ -1,5 +1,3 @@
-package client;
-
 import javax.swing.*;
 import java.awt.*;
 import java.awt.event.ActionEvent;
diff --git a/src/client/UpdateController.java b/src/client/UpdateController.java
new file mode 100644
index 0000000000000000000000000000000000000000..7ca67e8e916a82cafdb2da1c73e39115f1888d5b
--- /dev/null
+++ b/src/client/UpdateController.java
@@ -0,0 +1,33 @@
+package client;
+
+import remote.IUpdateController;
+
+import java.io.Serializable;
+import java.rmi.RemoteException;
+import java.rmi.server.UnicastRemoteObject;
+import java.util.ArrayList;
+
+public class UpdateController extends UnicastRemoteObject implements IUpdateController, Serializable {
+    private ArrayList<String> userList;
+
+    protected UpdateController() throws RemoteException {
+        userList = new ArrayList<>();
+    }
+
+    @Override
+    public void updateClient(String text) throws RemoteException {
+        System.out.println("Client " + text + " just joined the server.");
+        userList.add(text);
+    }
+
+    @Override
+    public ArrayList<String> getUserList() throws RemoteException {
+        return userList;
+    }
+
+    @Override
+    public void updateUserList(ArrayList userList) throws RemoteException {
+        this.userList = userList;
+    }
+
+}
diff --git a/src/remote/IClientController.java b/src/remote/IClientController.java
new file mode 100644
index 0000000000000000000000000000000000000000..8f8a60079003c9475b7c3c5b8a1624d151eef8ca
--- /dev/null
+++ b/src/remote/IClientController.java
@@ -0,0 +1,13 @@
+package remote;
+
+import java.io.Serializable;
+import java.net.InetAddress;
+import java.rmi.Remote;
+import java.rmi.RemoteException;
+import java.util.ArrayList;
+
+public interface IClientController extends Remote {
+
+    public String joinServer(String userName, InetAddress ipAddress, String rmiName) throws RemoteException;
+    public ArrayList<String> getUsernameList() throws RemoteException;
+}
diff --git a/src/remote/IDrawingController.java b/src/remote/IDrawingController.java
new file mode 100644
index 0000000000000000000000000000000000000000..3588c6ffd440bac80968656dad3958869e97e874
--- /dev/null
+++ b/src/remote/IDrawingController.java
@@ -0,0 +1,22 @@
+package remote;
+
+import java.rmi.Remote;
+import java.rmi.RemoteException;
+
+
+/**
+ * RMI Remote interface - must be shared between client and server.
+ * All methods must throw RemoteException.
+ * All parameters and return types must be either primitives or Serializable.
+ *
+ * Any object that is a remote object must implement this interface.
+ * Only those methods specified in a "remote interface" are available remotely.
+ */
+public interface IDrawingController extends Remote {
+
+    public double drawLine(double a, double b) throws RemoteException;
+
+    public double drawRectangle(double a, double b) throws RemoteException;
+
+
+}
diff --git a/src/remote/IUpdateController.java b/src/remote/IUpdateController.java
new file mode 100644
index 0000000000000000000000000000000000000000..caad27c6264f84f0e9890a2e954f58d6510b7e7d
--- /dev/null
+++ b/src/remote/IUpdateController.java
@@ -0,0 +1,17 @@
+package remote;
+
+import java.rmi.Remote;
+import java.rmi.RemoteException;
+import java.util.ArrayList;
+
+/**
+ * RMI Remote interface - IRemoteUpdate.
+ * Allows Server to command Client to update: canvas, chat, other.
+ */
+
+public interface IUpdateController extends Remote {
+
+    public void updateClient(String text) throws RemoteException;
+    public ArrayList<String> getUserList() throws RemoteException;
+    public void updateUserList(ArrayList userList) throws RemoteException;
+}
diff --git a/src/server/ClientController.java b/src/server/ClientController.java
new file mode 100644
index 0000000000000000000000000000000000000000..e7504b41ff95d688dcb5f9cc3a63e12c430af531
--- /dev/null
+++ b/src/server/ClientController.java
@@ -0,0 +1,70 @@
+package server;
+
+import java.io.Serializable;
+import java.net.InetAddress;
+import java.rmi.Remote;
+import java.rmi.RemoteException;
+import java.rmi.registry.LocateRegistry;
+import java.rmi.registry.Registry;
+import java.rmi.server.UnicastRemoteObject;
+import java.util.ArrayList;
+import java.util.Observable;
+import java.util.Observer;
+
+import client.UpdateController;
+import remote.IClientController;
+import remote.IUpdateController;
+
+/**
+ * Server side implementation of the remote interface.
+ * Must extend UnicastRemoteObject, to allow the JVM to create a
+ * remote proxy/stub.
+ *
+ */
+public class ClientController extends UnicastRemoteObject implements IClientController, Serializable {
+
+    /**
+     * Added
+     */
+    //private static final long serialVersionUID = 1L;
+
+    private ArrayList<User> userList;
+
+    protected ClientController() throws RemoteException {
+        userList = new ArrayList<>();
+    }
+
+    @Override
+    public String joinServer(String userName, InetAddress ipAddress, String rmiName) throws RemoteException {
+        try
+        {
+            Registry userRMI = LocateRegistry.getRegistry(ipAddress.getHostAddress());
+            IUpdateController updateController = (IUpdateController) userRMI.lookup(rmiName);
+
+            User user = new User(userName, ipAddress, rmiName);
+            userList.add(user);
+            for (User u : userList) {
+                if (!userName.equals(u.getUsername())) {
+                    u.getUpdateController().updateClient(userName);
+                }
+            }
+            System.out.println("User " + userName + " added successfully");
+        }
+        catch (Exception e)
+        {
+            e.printStackTrace();
+        }
+        return "update successfully";
+    }
+
+    @Override
+    public ArrayList<String> getUsernameList() throws RemoteException {
+        ArrayList<String> usernameList = new ArrayList<>();
+        for (User u : userList) {
+            usernameList.add(u.getUsername());
+        }
+        return usernameList;
+    }
+
+
+}
\ No newline at end of file
diff --git a/src/server/DrawingController.java b/src/server/DrawingController.java
new file mode 100644
index 0000000000000000000000000000000000000000..00ec6c538b0e73279207e231053f3da5ff364391
--- /dev/null
+++ b/src/server/DrawingController.java
@@ -0,0 +1,35 @@
+package server;
+
+import java.rmi.RemoteException;
+        import java.rmi.server.UnicastRemoteObject;
+
+import remote.IDrawingController;
+
+/**
+ * Server side implementation of the remote interface.
+ * Must extend UnicastRemoteObject, to allow the JVM to create a
+ * remote proxy/stub.
+ *
+ */
+public class DrawingController extends UnicastRemoteObject implements IDrawingController {
+
+    /**
+     * Added
+     */
+    //private static final long serialVersionUID = 1L;
+    private int numberOfComputations;
+
+    protected DrawingController() throws RemoteException {
+        numberOfComputations = 0;
+    }
+
+    @Override
+    public double drawLine(double a, double b) throws RemoteException {
+        return a+b;
+    }
+
+    @Override
+    public double drawRectangle(double a, double b) throws RemoteException {
+        return 0;
+    }
+}
\ No newline at end of file
diff --git a/src/server/Server.java b/src/server/Server.java
new file mode 100644
index 0000000000000000000000000000000000000000..c279c47e83567624b581763c8be5736aaf4091f0
--- /dev/null
+++ b/src/server/Server.java
@@ -0,0 +1,68 @@
+package server;
+
+import java.rmi.registry.LocateRegistry;
+import java.rmi.registry.Registry;
+import java.util.ArrayList;
+import java.util.Observable;
+import java.util.Scanner;
+
+import remote.IClientController;
+import remote.IDrawingController;
+
+public class Server extends Observable {
+
+    public static void main(String[] args)  {
+
+        try {
+
+            //Export the remote math object to the Java RMI runtime so that it
+            //can receive incoming remote calls.
+            //Because RemoteMath extends UnicastRemoteObject, this
+            //is done automatically when the object is initialized.
+            //
+            //RemoteMath obj = new RemoteMath();
+            //IRemoteMath stub = (IRemoteMath) UnicastRemoteObject.exportObject(obj, 0);
+            //
+            IDrawingController drawingController = new DrawingController();
+            IClientController clientController = new ClientController();
+
+            //Publish the remote object's stub in the registry under the name "Compute"
+            Registry registry = LocateRegistry.getRegistry();
+            registry.rebind("DrawingController", drawingController);
+            registry.rebind("ClientController", clientController);
+
+            System.out.println("Server is ready");
+
+
+            // Test client update command
+            // Get client registry
+            ArrayList<String> usernameList = new ArrayList<>();
+            Scanner keyboard = new Scanner(System.in);
+            String command;
+            while(true) {
+                command = keyboard.nextLine();
+                switch (command) {
+                    case "test1":
+                        usernameList = clientController.getUsernameList();
+                        if (!usernameList.isEmpty()) {
+                            for (int i = 0; i < usernameList.size(); i++) {
+                                System.out.println(usernameList.get(i));
+                            }
+                        }
+                        break;
+                    default:
+                        System.out.println("nothing");
+                        break;
+                }
+            }
+
+
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+
+    }
+
+
+}
+
diff --git a/src/server/ServerDriver.java b/src/server/ServerDriver.java
new file mode 100644
index 0000000000000000000000000000000000000000..b6e7cfa6970a19ebefb091274102d6ab28c7f69a
--- /dev/null
+++ b/src/server/ServerDriver.java
@@ -0,0 +1,20 @@
+package server;
+
+import java.rmi.RemoteException;
+
+public class ServerDriver {
+    private ClientController clientController;
+    private DrawingController drawingController;
+
+    private ServerDriver() throws RemoteException {
+        try {
+            this.clientController = new ClientController();
+            this.drawingController = new DrawingController();
+        }
+        catch (Exception e) {
+            e.printStackTrace();
+        }
+
+
+    }
+}
diff --git a/src/server/User.java b/src/server/User.java
new file mode 100644
index 0000000000000000000000000000000000000000..6583e2133e000b14c54b7d6c8e36c6b828609d89
--- /dev/null
+++ b/src/server/User.java
@@ -0,0 +1,44 @@
+package server;
+
+import remote.IUpdateController;
+
+import java.net.InetAddress;
+import java.rmi.NotBoundException;
+import java.rmi.RemoteException;
+import java.rmi.registry.LocateRegistry;
+import java.rmi.registry.Registry;
+
+public class User {
+    private String userName;
+    private String RMIName;
+    private InetAddress ipAddress;
+    private IUpdateController updateController;
+
+    public User (String username, InetAddress ipAddress, String rmiName) throws RemoteException, NotBoundException {
+        this.userName = username;
+        this.ipAddress = ipAddress;
+        this.RMIName = rmiName;
+        Registry userRMI = LocateRegistry.getRegistry(ipAddress.getHostAddress());
+        this.updateController = (IUpdateController) userRMI.lookup(rmiName);
+    }
+
+    public String getUsername()
+    {
+        return userName;
+    }
+
+    public InetAddress getIpAddress()
+    {
+        return ipAddress;
+    }
+
+    public String getRMIname()
+    {
+        return RMIName;
+    }
+
+    public IUpdateController getUpdateController()
+    {
+        return updateController;
+    }
+}