Package com.ngt.jopenmetaverse.shared.sim

Source Code of com.ngt.jopenmetaverse.shared.sim.UDPBase

/**
* A library to interact with Virtual Worlds such as OpenSim
* Copyright (C) 2012  Jitendra Chauhan, Email: jitendra.chauhan@gmail.com
*
* This library is free software; you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License,
* or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package com.ngt.jopenmetaverse.shared.sim;

import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.net.SocketException;
import com.ngt.jopenmetaverse.shared.sim.buffers.UDPPacketBuffer;
import com.ngt.jopenmetaverse.shared.sim.events.ThreadPool;
import com.ngt.jopenmetaverse.shared.sim.events.ThreadPoolFactory;
import com.ngt.jopenmetaverse.shared.util.JLogger;
import com.ngt.jopenmetaverse.shared.util.Utils;

public abstract class UDPBase {
  // these abstract methods must be implemented in a derived class to actually do
  // something with the packets that are sent and received.
  protected abstract void PacketReceived(UDPPacketBuffer buffer);
  protected abstract void PacketSent(UDPPacketBuffer buffer, int bytesSent);
  private static ThreadPool threadPool = ThreadPoolFactory.getThreadPool();


  // the port to listen on
  protected int udpPort;

  // the remote endpoint to communicate with
  protected InetSocketAddress remoteEndPoint = null;

  // the UDP socket
  private DatagramSocket udpSocket;

  // the all important shutdownFlag.
  private volatile boolean shutdownFlag = true;

  /// <summary>
  /// Initialize the UDP packet handler in server mode
  /// </summary>
  /// <param name="port">Port to listening for incoming UDP packets on</param>
  public UDPBase(int port)
  {
    udpPort = port;
  }

  /// <summary>
  /// Initialize the UDP packet handler in client mode
  /// </summary>
  /// <param name="endPoint">Remote UDP server to connect to</param>
  public UDPBase(InetSocketAddress endPoint)
  {
    remoteEndPoint = endPoint;
    //FIXME Need to remove following hardcoding . Used only for testing with Android Emulator
    udpPort = Settings.UDP_BIND_PORT;
  }

  /// <summary>
  ///
  /// </summary>
  public void Start() throws SocketException
  {
    if (shutdownFlag)
    {
      //            final int SIO_UDP_CONNRESET = -1744830452;

      SocketAddress ipep = new InetSocketAddress(Settings.BIND_ADDR, udpPort);
      udpSocket = new DatagramSocket(ipep);
      //            try
      //            {
      //                // this udp socket flag is not supported under mono,
      //                // so we'll catch the exception and continue
      //                udpSocket.IOControl(SIO_UDP_CONNRESET, new byte[] { 0 }, null);
      //            }
      //            catch (SocketException)
      //            {
      //                Logger.DebugLog("UDP SIO_UDP_CONNRESET flag not supported on this platform");
      //            }
      //            udpSocket.bind(ipep);

      // we're not shutting down, we're starting up
      shutdownFlag = false;

      // kick off an async receive.  The Start() method will return, the
      // actual receives will occur asynchronously and will be caught in
      // AsyncEndRecieve().
      AsyncBeginReceive();
    }
  }

  /// <summary>
  ///
  /// </summary>
  public void Stop()
  {
    if (!shutdownFlag)
    {
      // wait indefinitely for a writer lock.  Once this is called, the .NET runtime
      // will deny any more reader locks, in effect blocking all other send/receive
      // threads.  Once we have the lock, we set shutdownFlag to inform the other
      // threads that the socket is closed.
      shutdownFlag = true;
      udpSocket.close();
    }
  }

  /// <summary>
  ///
  /// </summary>
  public boolean isRunning()
  {
    return !shutdownFlag;
  }

  private void AsyncBeginReceive()
  {
    // allocate a dedicated thread.
    threadPool.execute(new Runnable(){
      public void run()
      {
        //While it is not shutdown
        while (!shutdownFlag)
        {
          final UDPPacketBuffer buf = new UDPPacketBuffer();
          DatagramPacket receivePacket = new DatagramPacket(buf.getData(), buf.getData().length);
          try {
            udpSocket.receive(receivePacket);
            buf.setDataLength(receivePacket.getLength());
            buf.setRemoteEndPoint(receivePacket.getSocketAddress());
            //Start another receiving, it will keep the server going

            //start another thread to process the packet
            threadPool.execute(new Runnable(){
              public void run()
              {
                PacketReceived(buf);
              }
            });
          }
          catch (Exception e) {
            //TODO handle error in a better way
            JLogger.error("Error while recieving packet\n" + Utils.getExceptionStackTraceAsString(e))
          }
        }
      }});
  }

  public void AsyncBeginSend(final UDPPacketBuffer buf)
  {
    if (!shutdownFlag)
    {
      threadPool.execute(new Runnable(){
        public void run()
        {
          try {
            DatagramPacket sendPacket = new DatagramPacket(buf.getData(), buf.getDataLength(), buf.getRemoteEndPoint());
            //            JLogger.debug(String.format("Data sending to server of length %d \n%s ", buf.getDataLength(), Utils.bytesToHexDebugString(buf.getData(), buf.getDataLength(), "")));
            udpSocket.send(sendPacket);
            PacketSent(buf, buf.getDataLength());
          }
          catch (Exception e) {
            //TODO handle error in a better way
            JLogger.error("Error while sending packet\n" + Utils.getExceptionStackTraceAsString(e));
          }
        }
      });
    }
  }
}
TOP

Related Classes of com.ngt.jopenmetaverse.shared.sim.UDPBase

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.