· 9 years ago · Jan 10, 2017, 10:42 PM
1package chatServer;
2
3import java.io.*;
4import java.sql.*;
5import java.net.*;
6import java.text.SimpleDateFormat;
7import java.util.*;
8import java.util.Date;
9
10import org.mindrot.jbcrypt.BCrypt;
11
12public class Server {
13 private static int clientId;
14 private ArrayList<ClientThread> clientList;
15 private SimpleDateFormat time;
16 private int port;
17 private boolean running;
18
19 public static void main(String[] args) {
20 // start server on port 9007 unless a PortNumber is specified
21 int portNumber = 9007;
22 switch(args.length) {
23 case 1:
24 try {
25 portNumber = Integer.parseInt(args[0]);
26 }
27 catch(Exception e) {
28 System.out.println("Invalid port number.");
29 System.out.println("Java Server [portNumber]");
30 return;
31 }
32 case 0:
33 break;
34 default:
35 System.out.println("Java Server [portNumber]");
36 return;
37
38 }
39 // create a server object and start it
40 Server server = new Server(portNumber);
41 server.start();
42 }
43
44 public Server(int port){
45 this.port = port;
46 time = new SimpleDateFormat("HH:mm:ss");
47 clientList = new ArrayList<ClientThread>();
48 Statement st = null;
49 Connection conn = null;
50 try{
51 Class.forName("org.h2.Driver");
52 conn = DriverManager.getConnection("jdbc:h2:~/messageserver", "server", "server");
53 st = conn.createStatement();
54 st.execute("create table if not exists users(UserName varchar(20) primary key, Password varchar(255));");
55 }catch(ClassNotFoundException | SQLException e){
56 e.printStackTrace();
57 }finally{
58 try{
59 st.close();
60 conn.close();
61 }catch(SQLException e){
62 e.printStackTrace();
63 }
64 }
65 }
66 public void start(){
67 running = true;
68 try {
69 ServerSocket serverSocket = new ServerSocket(port);
70 while(running)
71 {
72 System.out.println("Waiting for connections. Port = " + port);
73 Socket socket = serverSocket.accept();
74 if(!running)
75 break;
76 ClientThread t = new ClientThread(socket);
77 clientList.add(t); // Needs changing for registered users
78 t.start();
79 }
80
81 try {
82 serverSocket.close();
83 for (int i = 0; i < clientList.size(); i++)
84 {
85 ClientThread tc = clientList.get(i);
86 try {
87 tc.inStream.close();
88 tc.outStream.close();
89 tc.socket.close();
90 } catch (IOException e) {
91
92 }
93 }
94 } catch (Exception e) {
95 System.out.println("Problem closing connections and server" + e);
96 }
97
98 } catch (IOException e){
99 String msg = time.format(new Date()) + " Exception on ServerSocket: " + e + "\n";
100 System.out.println(msg);
101 }
102 }
103
104 protected void stop() {
105 running = false;
106 try {
107 new Socket("localhost", port);
108 } catch (Exception e) {
109
110 }
111 }
112
113 public class ClientThread extends Thread {
114 Socket socket;
115 ObjectInputStream inStream;
116 ObjectOutputStream outStream;
117 String date;
118 int id;
119 public String username;
120 ChatMessage cm;
121
122 ClientThread(Socket socket){
123 this.socket = socket;
124 id = ++clientId;
125 try {
126 outStream = new ObjectOutputStream(socket.getOutputStream());
127 inStream = new ObjectInputStream(socket.getInputStream());
128
129 username = (String) inStream.readObject();
130 System.out.print(username + " connected");
131
132 } catch (IOException e) {
133 System.out.println("Exception creating streams");
134 return;
135 }
136
137 catch (ClassNotFoundException e ) {
138
139 }
140 }
141
142 public void run() {
143 // to loop until LOGOUT
144 boolean running = true;
145 while(running) {
146 // read a String (which is an object)
147 try {
148 cm = (ChatMessage) inStream.readObject();
149 }
150 catch (IOException e) {
151 System.out.println(username + " Exception reading Streams: " + e);
152 break;
153 }
154 catch(ClassNotFoundException e2) {
155 break;
156 }
157 String message = cm.getMessage();
158
159 // Switch on the type of message receive
160 switch(cm.getType()) {
161
162 case ChatMessage.MESSAGE:
163 broadcast(username + ": " + message);
164 break;
165 case ChatMessage.LOGOUT:
166 System.out.println(username + " disconnected with a LOGOUT message.");
167 running = false;
168 break;
169 case ChatMessage.WHOISIN:
170 writeMsg("List of the users connected at " + time.format(new Date()) + "\n");
171 // scan al the users connected
172 for(int i = 0; i < clientList.size(); ++i) {
173 ClientThread ct = clientList.get(i);
174 writeMsg((i+1) + ") " + ct.username + " since " + ct.date);
175 }
176 break;
177 case ChatMessage.LOGIN:
178 if(loginAttempt(message)){
179 writeMsg("true");
180 }else{
181 writeMsg("false");
182 }
183 break;
184 case ChatMessage.REGISTER:
185 if(register(message)){
186 writeMsg("true");
187// loginAttempt(message); auto login if register is successful?
188 }
189
190 break;
191 }
192 }
193 remove(id);
194 close();
195 }
196
197 private void close() {
198 // try to close the connection
199 try {
200 if(outStream != null) outStream.close();
201 }
202 catch(Exception e) {}
203 try {
204 if(inStream != null) inStream.close();
205 }
206 catch(Exception e) {};
207 try {
208 if(socket != null) socket.close();
209 }
210 catch (Exception e) {}
211 }
212
213 private boolean writeMsg(String msg) {
214 // if Client is still connected send the message to it
215 if(!socket.isConnected()) {
216 close();
217 return false;
218 }
219 // write the message to the stream
220 try {
221 outStream.writeObject(msg);
222 }
223 catch(IOException e) {
224 System.out.print("Error sending message to " + username);
225 System.out.println(e.toString());
226 }
227 return true;
228 }
229 }
230
231 private synchronized void broadcast(String message) {
232 String currentTime = time.format(new Date());
233 String messageLf = currentTime + " " + message + "\n"; // add HH:mm:ss and \n to the message
234 System.out.print(messageLf);
235
236 for(int i = clientList.size(); --i >= 0;) {
237 ClientThread ct = clientList.get(i);
238 // try to write to the Client if it fails remove it from the list
239 if(!ct.writeMsg(messageLf)) {
240 clientList.remove(i);
241 System.out.print("Disconnected Client " + ct.username + " removed from list.");
242 }
243 }
244 }
245 private synchronized boolean loginAttempt(String message){
246 String[] messages = message.split("$");
247 String Lusername = messages[0];
248 String password = messages[1];
249 Statement st = null;
250 Connection conn = null;
251 try{
252 String hashed = "";
253 Class.forName("org.h2.Driver");
254 conn = DriverManager.getConnection("jdbc:h2:~/messageserver", "server", "server");
255 st = conn.createStatement();
256 ResultSet rs = st.executeQuery("select password from users where username='" + Lusername + "';");
257 String storedPassword = rs.getString("password");
258 if(BCrypt.checkpw(password, storedPassword)){
259 //ClientThread name = new ClientThread(socket)
260 //username = Lusername; Need to update the username before returning true.
261 return true;
262 }
263 return false;
264 }catch(ClassNotFoundException | SQLException e){
265 e.printStackTrace();
266 }finally{
267 try{
268 st.close();
269 conn.close();
270 }catch(SQLException e){
271 e.printStackTrace();
272 }
273 }
274 return false;
275 }
276 private synchronized boolean register(String message){
277 String[] messages = message.split("$");
278 String username = messages[0];
279 String password = messages[1];
280 Statement st = null;
281 Connection conn = null;
282 try{
283 String hashed = "";
284 Class.forName("org.h2.Driver");
285 conn = DriverManager.getConnection("jdbc:h2:~/messageserver", "server", "server");
286 st = conn.createStatement();
287 ResultSet rs = st.executeQuery("select username from users where username='" + username + "';");
288 if(!rs.next()){
289 hashed = BCrypt.hashpw(password, BCrypt.gensalt());
290 st.executeUpdate("insert into users values('" + username + "', '" + hashed + "');");
291 return true;
292 }
293 }catch(ClassNotFoundException | SQLException e){
294 e.printStackTrace();
295
296 }finally{
297 try{
298 st.close();
299 conn.close();
300 }catch(SQLException e){
301 e.printStackTrace();
302 }
303 }
304 return false;
305 }
306
307 synchronized void remove(int id) {
308 // scan the array list until we found the Id
309 for(int i = 0; i < clientList.size(); ++i) {
310 ClientThread ct = clientList.get(i);
311 // found it
312 if(ct.id == id) {
313 clientList.remove(i);
314 return;
315 }
316 }
317 }
318}