203 lines
		
	
	
		
			7.1 KiB
		
	
	
	
		
			Java
		
	
	
	
	
	
			
		
		
	
	
			203 lines
		
	
	
		
			7.1 KiB
		
	
	
	
		
			Java
		
	
	
	
	
	
| package electrosphere.net.client;
 | |
| 
 | |
| import electrosphere.entity.types.creature.CreatureUtils;
 | |
| import electrosphere.entity.Entity;
 | |
| import electrosphere.entity.EntityUtils;
 | |
| import electrosphere.logger.LoggerInterface;
 | |
| import electrosphere.main.Globals;
 | |
| import electrosphere.main.Main;
 | |
| import electrosphere.net.client.protocol.ClientProtocol;
 | |
| import electrosphere.net.parser.net.message.EntityMessage;
 | |
| import electrosphere.net.parser.net.message.NetworkMessage;
 | |
| import electrosphere.net.parser.net.message.PlayerMessage;
 | |
| import electrosphere.net.parser.net.message.ServerMessage;
 | |
| import electrosphere.net.parser.net.message.NetworkMessage.MessageType;
 | |
| import electrosphere.net.parser.net.message.ServerMessage.ServerMessageType;
 | |
| import electrosphere.net.parser.net.raw.NetworkParser;
 | |
| import java.io.IOException;
 | |
| import java.io.InputStream;
 | |
| import java.io.OutputStream;
 | |
| import java.math.BigInteger;
 | |
| import java.net.Socket;
 | |
| import java.net.SocketException;
 | |
| import java.security.spec.RSAKeyGenParameterSpec;
 | |
| import java.util.Properties;
 | |
| import java.util.Random;
 | |
| import java.util.concurrent.CopyOnWriteArrayList;
 | |
| import java.util.concurrent.Semaphore;
 | |
| import java.util.concurrent.TimeUnit;
 | |
| import java.util.logging.Level;
 | |
| import java.util.logging.Logger;
 | |
| import javax.crypto.spec.SecretKeySpec;
 | |
| 
 | |
| /**
 | |
|  *
 | |
|  * @author amaterasu
 | |
|  */
 | |
| public class ClientNetworking implements Runnable{
 | |
|     
 | |
|     String address;
 | |
|     int port;
 | |
|     
 | |
|     public Socket socket;
 | |
| //    CryptoInputStream inputStream;
 | |
| //    CryptoOutputStream outputStream;
 | |
|     InputStream inputStream;
 | |
|     OutputStream outputStream;
 | |
|     boolean initialized;
 | |
|     NetworkParser parser;
 | |
|     
 | |
|     ClientProtocol clientProtocol = new ClientProtocol();
 | |
| 
 | |
|     static final int MAX_CONNECTION_ATTEMPTS = 10;
 | |
| 
 | |
|     //set to true to also get ping and pong messages in debug logging
 | |
|     boolean echoPings = false;
 | |
| 
 | |
|     //thresholds for when to send pings and to determine when we've disconnected
 | |
|     static final long SEND_PING_THRESHOLD = 3000;
 | |
|     static final long PING_DISCONNECT_THRESHOLD = 20000;
 | |
|     //times for calculating ping-pong
 | |
|     long lastPingTime = 0;
 | |
|     long lastPongTime = 0;
 | |
|     
 | |
|     public ClientNetworking(String address, int port){
 | |
|         this.address = address;
 | |
|         this.port = port;
 | |
|     }
 | |
|     
 | |
|     
 | |
|     
 | |
|     @Override
 | |
|     public void run(){
 | |
|         initialized = false;
 | |
|             //        final SecretKeySpec key = new SecretKeySpec(("1234567890123456").getBytes(),"AES");
 | |
| //        final Properties properties = new Properties();
 | |
| //        final RSAKeyGenParameterSpec spec = new RSAKeyGenParameterSpec(4096, BigInteger.probablePrime(4000, new Random()));
 | |
| //        try {
 | |
| //            inputStream = new CryptoInputStream("AES/ECB/PKCS5Padding",properties,socket.getInputStream(),key,spec);
 | |
| //        } catch (IOException ex) {
 | |
| //            ex.printStackTrace();
 | |
| //            System.exit(1);
 | |
| //        }
 | |
| //        try {
 | |
| //            outputStream = new CryptoOutputStream("AES/ECB/PKCS5Padding",properties,socket.getOutputStream(),key,spec);
 | |
| //        } catch (IOException ex) {
 | |
| //            ex.printStackTrace();
 | |
| //            System.exit(1);
 | |
| //        }
 | |
| 
 | |
|         //attempt connection
 | |
|         int connectionAttempts = 0;
 | |
|         boolean connected = false;
 | |
|         while(!connected){
 | |
|             try {
 | |
|                 this.socket = new Socket(address,port);
 | |
|                 connected = true;
 | |
|             } catch (IOException ex) {
 | |
|                 LoggerInterface.loggerNetworking.WARNING("Client failed to connect!");
 | |
|             }
 | |
|             if(!connected){
 | |
|                 try {
 | |
|                     TimeUnit.MILLISECONDS.sleep(50);
 | |
|                 } catch (InterruptedException e) {}
 | |
|                 connectionAttempts++;
 | |
|             }
 | |
|             if(connectionAttempts > MAX_CONNECTION_ATTEMPTS){
 | |
|                 LoggerInterface.loggerNetworking.ERROR("Max client connection attempts!", new Exception());
 | |
|                 // System.exit(1);
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         //create parser
 | |
|         try {
 | |
|             inputStream = socket.getInputStream();
 | |
|             outputStream = socket.getOutputStream();
 | |
|             parser = new NetworkParser(inputStream,outputStream);
 | |
|         } catch (IOException ex) {
 | |
|             LoggerInterface.loggerNetworking.ERROR("Error on client socket", ex);
 | |
|         }
 | |
|         
 | |
|         //start parsing messages
 | |
|         initialized = true;
 | |
|         while(Main.isRunning()){
 | |
|             //attempt poll incoming messages
 | |
|             parser.readMessagesIn();
 | |
|             //outgoing messages
 | |
|             parser.pushMessagesOut();
 | |
|             //ping logic
 | |
|             long currentTime = System.currentTimeMillis();
 | |
|             //basically if we haven't sent a ping in a while, send one
 | |
|             if(currentTime - lastPingTime > SEND_PING_THRESHOLD){
 | |
|                 queueOutgoingMessage(ServerMessage.constructPingMessage());
 | |
|                 lastPingTime = currentTime;
 | |
|                 if(lastPongTime == 0){
 | |
|                     lastPongTime = lastPingTime;
 | |
|                 }
 | |
|             }
 | |
|             if(lastPingTime - lastPongTime > PING_DISCONNECT_THRESHOLD){
 | |
|                 //disconnected from the server
 | |
|                 LoggerInterface.loggerNetworking.WARNING("Disconnected from server");
 | |
|                 //close socket
 | |
|                 if(socket.isConnected()){
 | |
|                     try {
 | |
|                         socket.close();
 | |
|                     } catch (IOException e) {
 | |
|                         LoggerInterface.loggerNetworking.ERROR("Error closing socket", e);
 | |
|                     }
 | |
|                 }
 | |
|                 //TODO: kick us back to the main menu
 | |
|                 break;
 | |
|             }
 | |
|         }
 | |
|         
 | |
|     }
 | |
|     
 | |
|     
 | |
|     public void parseMessages(){
 | |
|         if(initialized){
 | |
|             while(parser.hasIncomingMessaage()){
 | |
|                 NetworkMessage message = parser.popIncomingMessage();
 | |
|                 //print network message
 | |
|                 printMessage(message);
 | |
|                 //do something
 | |
|                 clientProtocol.handleMessage(message);
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Print out the network message type, this only prints ping and pong if echoPings is true
 | |
|      */
 | |
|     void printMessage(NetworkMessage message){
 | |
|         //only print ping and pong if echoPings is true
 | |
|         if(message.getType() == MessageType.SERVER_MESSAGE){
 | |
|             if((((ServerMessage)message).getMessageSubtype()) == ServerMessageType.PING ||
 | |
|                (((ServerMessage)message).getMessageSubtype()) == ServerMessageType.PONG
 | |
|                 ){
 | |
|                         if(this.echoPings == true){
 | |
|                     LoggerInterface.loggerNetworking.DEBUG("[Server] New message " + message.getType());
 | |
|                 }
 | |
|             } else {
 | |
|                 LoggerInterface.loggerNetworking.DEBUG("[Server] New message " + message.getType());
 | |
|             }
 | |
|         } else {
 | |
|             LoggerInterface.loggerNetworking.DEBUG("[Server] New message " + message.getType());
 | |
|         }
 | |
|     }
 | |
|     
 | |
|     
 | |
|     public void queueOutgoingMessage(NetworkMessage message){
 | |
|         parser.addOutgoingMessage(message);
 | |
|     }
 | |
|     
 | |
|     public ClientProtocol getClientProtocol(){
 | |
|         return clientProtocol;
 | |
|     }
 | |
| 
 | |
|     public void markReceivedPongMessage(){
 | |
|         lastPongTime = System.currentTimeMillis();
 | |
|     }
 | |
|     
 | |
| }
 |