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