· 9 years ago · Jan 14, 2017, 10:24 PM
1import java.io.IOException;
2import java.io.ObjectInputStream;
3import java.io.ObjectOutputStream;
4import java.net.ServerSocket;
5import java.net.Socket;
6import java.sql.Connection;
7import java.sql.DriverManager;
8import java.sql.ResultSet;
9import java.sql.SQLException;
10import java.sql.Statement;
11import java.text.SimpleDateFormat;
12import java.util.ArrayList;
13import java.util.Date;
14
15import org.mindrot.jbcrypt.BCrypt;
16
17public class Server {
18 private static int clientId;
19 private ArrayList<ClientThread> clientList;
20 private SimpleDateFormat time;
21 private int port;
22 private boolean running;
23
24 public static void main(String[] args) {
25 // start server on port 9007 unless a PortNumber is specified
26 int portNumber = 9007;
27 switch(args.length) {
28 case 1:
29 try {
30 portNumber = Integer.parseInt(args[0]);
31 }
32 catch(Exception e) {
33 System.out.println("Invalid port number.");
34 System.out.println("Java Server [portNumber]");
35 return;
36 }
37 case 0:
38 break;
39 default:
40 System.out.println("Java Server [portNumber]");
41 return;
42
43 }
44 // create a server object and start it
45 Server server = new Server(portNumber);
46 server.start();
47 }
48
49 public Server(int port){
50 this.port = port;
51 time = new SimpleDateFormat("HH:mm:ss");
52 clientList = new ArrayList<ClientThread>();
53 Statement st = null;
54 Connection conn = null;
55 try{
56 Class.forName("org.h2.Driver");
57 conn = DriverManager.getConnection("jdbc:h2:~/messageserver", "server", "server");
58 st = conn.createStatement();
59 st.execute("create table if not exists users(UserName varchar(20) primary key, Password varchar(255));");
60 }catch(ClassNotFoundException | SQLException e){
61 e.printStackTrace();
62 }finally{
63 try{
64 st.close();
65 conn.close();
66 }catch(SQLException e){
67 e.printStackTrace();
68 }
69 }
70 }
71 public void start(){
72 running = true;
73 try {
74 ServerSocket serverSocket = new ServerSocket(port);
75 while(running)
76 {
77 System.out.println("Waiting for connections. Port = " + port);
78 Socket socket = serverSocket.accept();
79 if(!running)
80 break;
81 ClientThread t = new ClientThread(socket);
82 clientList.add(t); // Needs changing for registered users
83 t.start();
84 }
85
86 try {
87 serverSocket.close();
88 for (int i = 0; i < clientList.size(); i++)
89 {
90 ClientThread tc = clientList.get(i);
91 try {
92 tc.inStream.close();
93 tc.outStream.close();
94 tc.socket.close();
95 } catch (IOException e) {
96
97 }
98 }
99 } catch (Exception e) {
100 System.out.println("Problem closing connections and server" + e);
101 }
102
103 } catch (IOException e){
104 String msg = time.format(new Date()) + " Exception on ServerSocket: " + e + "\n";
105 System.out.println(msg);
106 }
107 }
108
109 protected void stop() {
110 //running = false;
111 try {
112 new Socket("localhost", port);
113 } catch (Exception e) {
114
115 }
116 }
117
118 public class ClientThread extends Thread {
119 Socket socket;
120 ObjectInputStream inStream;
121 ObjectOutputStream outStream;
122 String date;
123 int id;
124 public String username;
125 ChatMessage cm;
126
127 ClientThread(Socket socket){
128 this.socket = socket;
129 id = ++clientId;
130 try {
131 ChatMessage cm2 = null;
132 outStream = new ObjectOutputStream(socket.getOutputStream());
133 inStream = new ObjectInputStream(socket.getInputStream());
134 while(true){
135 try{
136 cm2 = (ChatMessage)(inStream.readObject());
137 }catch(ClassNotFoundException cnf){
138 System.out.println(cnf);
139 }
140 int type = cm2.getType();
141 if(type==3){
142 if(loginAttempt(cm2.getMessage())){
143 writeMsg(3, "true");
144 break;
145 }else{
146 writeMsg(3, "false");
147 }
148 } else if(type==4){
149 if(register(cm2.getMessage())){
150 writeMsg(4, "true");
151 }else{
152 writeMsg(4, "false");
153 }
154 }
155 }
156 String[] messages = cm2.getMessage().split("\\$");
157 username = messages[0];
158
159 System.out.println(username + " connected");
160 broadcast(username + " has connected.");
161 } catch (IOException e) {
162 System.out.println("Exception creating streams");
163 return;
164 }
165 }
166
167 public void run() {
168 // to loop until LOGOUT
169 boolean running = true;
170 WhoIsIn();
171 while(running) {
172 // read a String (which is an object)
173 try {
174 cm = (ChatMessage) inStream.readObject();
175 }
176 catch (IOException e) {
177 System.out.println(username + " Exception reading Streams: " + e);
178 System.out.println(username + " closed connection.");
179 break;
180 }
181 catch(ClassNotFoundException e2) {
182 break;
183 }
184 String message = cm.getMessage();
185
186 // Switch on the type of message receive
187 switch(cm.getType()) {
188
189 case ChatMessage.MESSAGE:
190 System.out.println(message);
191 broadcast(username + ": " + message);
192 break;
193 case ChatMessage.LOGOUT:
194 System.out.println(username + " disconnected with a LOGOUT message.");
195 running = false;
196 remove(id);
197 break;
198 case ChatMessage.WHOISIN:
199 writeMsg("List of the users connected at " + time.format(new Date()) + "\n");
200 // scan al the users connected
201 for(int i = 0; i < clientList.size(); ++i) {
202 ClientThread ct = clientList.get(i);
203 writeMsg((i+1) + ") " + ct.username + " since " + ct.date);
204 }
205 break;
206 case ChatMessage.LOGIN:
207 if(loginAttempt(message)){
208 writeMsg(3, "true");
209 }else{
210 writeMsg(3, "false");
211 }
212 break;
213 case ChatMessage.REGISTER:
214 if(register(message)){
215 writeMsg(4, "true");
216// loginAttempt(message); auto login if register is successful?
217 } else{
218 writeMsg(4, "false");
219 }
220
221 break;
222 case ChatMessage.PRIVATE:
223 System.out.println("private message:");
224 String userName = "", messagepm = "";
225 try{
226 String[] messages = message.split("\\:", 2);
227 userName = messages[0];
228 messagepm = messages[1];
229 System.out.println(userName);
230 System.out.println(messagepm);
231 }catch(Exception e){
232 System.out.println(e);
233 writeMsg(5, "false");
234 break;
235 }
236 try{
237 messagepm = (time.format(new Date())) + " from:" + userName + " ~ " + messagepm + "\n"; // add HH:mm:ss and \n to the message
238 for(int i = clientList.size(); --i >= 0;) {
239 ClientThread ct = clientList.get(i);
240 if(ct.username.equals(userName)){
241 // try to write to the Client if it fails remove it from the list
242 if(!ct.writeMsg(5, messagepm)) {
243 clientList.remove(i);
244 System.out.print("Disconnected Client " + ct.username + " removed from list.");
245 writeMsg(5, "false2");
246 }else{
247 writeMsg(5, "true");
248 }
249 }
250 }
251 }catch(Exception e){
252 System.out.println("Private message error\\!" + e);
253 }
254 break;
255 }
256 }
257 remove(id);
258 close();
259 }
260
261 private void close() {
262 // try to close the connection
263 try {
264 if(outStream != null) outStream.close();
265 }
266 catch(Exception e) {}
267 try {
268 if(inStream != null) inStream.close();
269 }
270 catch(Exception e) {};
271 try {
272 if(socket != null) socket.close();
273 }
274 catch (Exception e) {}
275 }
276
277
278 private boolean writeMsg(String msg) {
279 // if Client is still connected send the message to it
280 if(!socket.isConnected()) {
281 close();
282 return false;
283 }
284 // write the message to the stream
285 try {
286 outStream.writeObject(msg);
287 }
288 catch(IOException e) {
289 System.out.print("Error sending message to " + username);
290 System.out.println(e.toString());
291 }
292 return true;
293 }
294 private boolean writeMsg(int type ,String msg) {
295 // if Client is still connected send the message to it
296 if(!socket.isConnected()) {
297 close();
298 return false;
299 }
300 // write the message to the stream
301 try {
302 ChatMessage LogObj = new ChatMessage(type, msg);
303 outStream.writeObject(LogObj);
304
305 }
306 catch(IOException e) {
307 System.out.print("Error sending message to " + username);
308 System.out.println(e.toString());
309 }
310 return true;
311 }
312 }
313
314 private synchronized void broadcast(String message) {
315 String currentTime = time.format(new Date());
316 String messageLf = currentTime + " " + message + "\n"; // add HH:mm:ss and \n to the message
317 System.out.print(messageLf);
318
319 for(int i = clientList.size(); --i >= 0;) {
320 ClientThread ct = clientList.get(i);
321 // try to write to the Client if it fails remove it from the list
322 if(!ct.writeMsg(1, messageLf)) {
323 clientList.remove(i);
324 System.out.print("Disconnected Client " + ct.username + " removed from list.");
325 }
326 }
327 }
328 private synchronized boolean loginAttempt(String message){
329 String[] messages = message.split("\\$");
330 String Lusername = messages[0];
331 String password = "";
332 try{
333 password = messages[1];
334 }catch(ArrayIndexOutOfBoundsException arrayofb){
335 System.out.println("no password");
336 }
337 Statement st = null;
338 Connection conn = null;
339 try{
340 String hashed = "";
341 Class.forName("org.h2.Driver");
342 conn = DriverManager.getConnection("jdbc:h2:~/messageserver", "server", "server");
343 st = conn.createStatement();
344 ResultSet rs = st.executeQuery("select password from users where username='" + Lusername + "';");
345 String storedPassword = "";
346 while(rs.next()){
347 storedPassword = rs.getString(storedPassword + "PASSWORD");
348 }
349 if(BCrypt.checkpw(password, storedPassword)){
350 return true;
351 }
352 return false;
353 }catch(ClassNotFoundException | SQLException e){
354 e.printStackTrace();
355 System.out.println("999");
356 return false;
357 }catch(Exception ee){
358 System.out.println("login failed.");
359 return false;
360 }
361 finally{
362 try{
363 st.close();
364 conn.close();
365 }catch(SQLException e){
366 e.printStackTrace();
367 }
368 }
369
370 }
371 private synchronized boolean register(String message){
372 String[] messages = message.split("\\$");
373 String username = messages[0];
374 String password = "";
375 try{
376 password = messages[1];
377 }catch(ArrayIndexOutOfBoundsException arrayofb){
378 System.out.println("no password (Register)");
379 }
380 System.out.println("Creating account, " + username + "\npassword:"+ password);
381 Statement st = null;
382 Connection conn = null;
383 try{
384 String hashed = "";
385 Class.forName("org.h2.Driver");
386 conn = DriverManager.getConnection("jdbc:h2:~/messageserver", "server", "server");
387 st = conn.createStatement();
388 try{
389 hashed = BCrypt.hashpw(password, BCrypt.gensalt());
390 st.executeUpdate("insert into users values('" + username + "', '" + hashed + "');");
391 System.out.println("Registration successful");
392 return true;
393 }catch(Exception sqle){
394 System.out.println("Registration failed");
395 return false;
396 }
397 }catch(ClassNotFoundException | SQLException e){
398 e.printStackTrace();
399
400 }finally{
401 try{
402 st.close();
403 conn.close();
404 }catch(SQLException e){
405 e.printStackTrace();
406 }
407 }
408 return false;
409 }
410 private synchronized void WhoIsIn(){
411 for(int i = clientList.size(); --i >= 0;) {
412 try{
413 ClientThread ct = clientList.get(i);
414 ct.writeMsg(0, "#");
415 // try to write to the Client if it fails remove it from the list
416 for(int x = clientList.size(); --i >= 0;){
417 ClientThread ctx = clientList.get(x);
418 ct.writeMsg(0, ctx.username);
419 }
420 }catch(Exception e){
421 e.printStackTrace();
422 }
423 }
424 }
425 synchronized void remove(int id) {
426 // scan the array list until we found the Id
427 for(int i = 0; i < clientList.size(); ++i) {
428 ClientThread ct = clientList.get(i);
429 // found it
430 if(ct.id == id) {
431 broadcast(ct.username +" has disconnected.");
432 clientList.remove(i);
433 WhoIsIn();
434 return;
435 }
436 }
437 }
438}