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