Package soc.qase.com

Source Code of soc.qase.com.CommunicationHandler

//---------------------------------------------------------------------
// Name:      CommunicationHandler.java
// Author:      Bernard.Gorman@computing.dcu.ie
// Author:      Martin.Fredriksson@bth.se
//---------------------------------------------------------------------

package soc.qase.com;

import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;

import soc.qase.com.message.Connectionless;
import soc.qase.com.packet.ClientPacket;
import soc.qase.com.packet.ConnectionlessPacket;
import soc.qase.com.packet.Packet;
import soc.qase.com.packet.Sequence;

/*-------------------------------------------------------------------*/
/**  The CommunicationHandler class is a wrapper class for low-level
*  communication between a Quake2 client and a Quake2 server. The
*  class takes care of the physical connection, but it also
*  implements message sending methods and current ping
*  information. */
/*-------------------------------------------------------------------*/
public class CommunicationHandler
{
  // connection information
  private DatagramSocket socket = null;
  private boolean connected = false;
  private String host = null;
  private int clientID = 0;
  private int port = 0;
  private boolean reliableLock = false;
  private boolean unreliableLock = false;
  private boolean reliableReceived = false;
  private boolean serverBit = false;
  private boolean clientBit = false;
  private byte[] currentData = null;

  // game information
  private long currentTime = 0;
  private int ping = 0;

  // sequence information
  private Sequence lastReliableSequence = null;
  private Sequence clientSequence = null;
  private Sequence serverSequence = null;

/*-------------------------------------------------------------------*/
/**  Constructor. Sets the client ID of the current agent.
@param clientID Client identifier used throughout a complete
*  client-server connection (included in all messages sent). */
/*-------------------------------------------------------------------*/
  public CommunicationHandler(int clientID)
  {
    this.clientID = clientID;
  }

/*-------------------------------------------------------------------*/
/*-------------------------------------------------------------------*/
  private void init()
  {
    ping = 0;
    currentTime = 0;
    clientSequence = new Sequence(0);
    serverSequence = new Sequence(0);
    lastReliableSequence = new Sequence(0);
  }

/*-------------------------------------------------------------------*/
/**  Check if a CommunicationHandler object is connected to a host
*  or not.
@return true if connected, otherwise false. */
/*-------------------------------------------------------------------*/
  public boolean isConnected()
  {
    return connected;
  }

/*-------------------------------------------------------------------*/
/**  Connect to specified host and port.
@param host hostname.
@param port portnumber.
@return a boolean denoting if the connect call was successful
*  or not. */
/*-------------------------------------------------------------------*/
  public boolean connect(String host, int port)
  {
    boolean result = false;

    try
    {
      socket = new DatagramSocket();
      socket.connect(InetAddress.getByName(host), port);

      connected = true;
      init();

      result = connected;
    }
    catch(Exception e)
    {
      e.printStackTrace();
    }

    return result;
  }

/*-------------------------------------------------------------------*/
/**  Disconnect from current host. */
/*-------------------------------------------------------------------*/
  public void disconnect()
  {
    if(isConnected())
    {
      connected = false;
      socket.close();
    }
  }

/*-------------------------------------------------------------------*/
/**  Send a connectionless message.
@param command message to send to host. */
/*-------------------------------------------------------------------*/
  public void sendConnectionless(String command)
  {
    DatagramPacket outgoingPacket = null;
    ConnectionlessPacket packet = null;
    Connectionless message = null;
   
    try
    {
      message = new Connectionless(command);
      packet = new ConnectionlessPacket(message);

      byte[] outData = packet.getBytes();
      outgoingPacket = new DatagramPacket(outData, outData.length);

      socket.send(outgoingPacket);
    }
    catch(Exception e)
    {
      e.printStackTrace();
    }
  }

/*-------------------------------------------------------------------*/
/**  Send an unreliable ClientPacket message. This method call will
*  return immediately after successfully sending the message.
@param packet message to send to host. */
/*-------------------------------------------------------------------*/
  public void sendUnreliable(ClientPacket packet)
  {
    sendData(packet, false);
  }

/*-------------------------------------------------------------------*/
/**  Send a reliable ClientPacket message. This method call will not
*  return until a reliable reply has been received by this object
*  (blocking).
@param packet message to send to host. */
/*-------------------------------------------------------------------*/
  public void sendReliable(ClientPacket packet)
  {
    sendData(packet, true);
  }

  private byte[] incomingBuffer = new byte[2048];
  private DatagramPacket incomingPacket = new DatagramPacket(incomingBuffer, incomingBuffer.length);

/*-------------------------------------------------------------------*/
/**  Receive data from connected server. This method call will not
*  return until a reply has been received by this object (blocking).
@return data received from host. */
/*-------------------------------------------------------------------*/
  public byte[] receiveData()
  {
    long previousTime = 0;
    byte[] incomingData = null;
   
    try
    {
      if(reliableReceived)
      {
        reliableReceived = false;
        return currentData;
      }

      socket.receive(incomingPacket);

      previousTime = currentTime;
      currentTime = System.currentTimeMillis();

      ping = (int)(currentTime - previousTime);
      incomingData = new byte[incomingPacket.getLength()];

      for(int i = 0; i < incomingPacket.getLength(); i++)
        incomingData[i] = incomingPacket.getData()[i];

      incomingData = processIncomingPacket(incomingData);
    }
    catch(Exception e)
    {  }

    return incomingData;
  }

/*-------------------------------------------------------------------*/
/*-------------------------------------------------------------------*/
  private void sendData(Packet packet, boolean reliable)
  {
    DatagramPacket outgoingPacket = null;
   
    try
    {
      if(reliable)
      {
        clientSequence = clientSequence.getNext();
        clientSequence.setReliable(true);
        serverSequence.setReliable(serverBit);

        ((ClientPacket)packet).setFirstSequence(clientSequence);
        ((ClientPacket)packet).setSecondSequence(serverSequence);

        byte[] outData = packet.getBytes();
        outgoingPacket = new DatagramPacket(outData, outData.length);

        for(int i = 0; reliableReceived != true; i++)
        {
          if((i % 10) == 0)
            socket.send(outgoingPacket);

          Thread.sleep(50);
          currentData = receiveData();
        }
      }
      else
      {
        clientSequence = clientSequence.getNext();
        clientSequence.setReliable(false);
        serverSequence.setReliable(serverBit);

        ((ClientPacket)packet).setFirstSequence(clientSequence);
        ((ClientPacket)packet).setSecondSequence(serverSequence);

        byte[] outData = packet.getBytes();
        outgoingPacket = new DatagramPacket(outData, outData.length);

        socket.send(outgoingPacket);
      }
    }
    catch(Exception e)
    {
      // e.printStackTrace(); // always "Socket closed" - ignore
    }
  }

/*-------------------------------------------------------------------*/
/*-------------------------------------------------------------------*/
  private byte[] processIncomingPacket(byte[] data)
  {
    ClientPacket currentPacket;
    Sequence sequenceOne = null;
    Sequence sequenceTwo = null;
    int length = 0;

    sequenceOne = new Sequence(data);

    if(sequenceOne.intValue() == 0x7fffffff && sequenceOne.isReliable())
      return data;
    else
    {
      serverSequence = sequenceOne;
      sequenceTwo = new Sequence(data, 4);

      if(serverSequence.isReliable())
      {
        if(serverSequence.intValue() > lastReliableSequence.intValue())
        {
          lastReliableSequence = new Sequence(serverSequence.intValue());
          serverBit = serverBit ^ true;
        }
      }

      if(sequenceTwo.isReliable() != clientBit)
      {
        clientBit = sequenceTwo.isReliable();
        reliableReceived = true;       
      }
    }

    return data;
  }

/*-------------------------------------------------------------------*/
/**  Get current ping.
@return current ping. */
/*-------------------------------------------------------------------*/
  public int getPing()
  {
    return ping;
  }

/*-------------------------------------------------------------------*/
/**  Get the client sequence included in the next message sent to
*  the connected host.
@return next client sequence. */
/*-------------------------------------------------------------------*/
  public Sequence getNextSequence()
  {
    return clientSequence.getNext();
  }
}
TOP

Related Classes of soc.qase.com.CommunicationHandler

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.