/*****************************
File:     RemoteUDPServer.h
Language:   C++ (header)
Project:    H3DNetworkingUtils
The contents of this file are subject to the Mozilla Public License
Version 1.1 (the "License"); you may not use this file except in
compliance with the License. You may obtain a copy of the License at
http://www.mozilla.org/MPL/

Software distributed under the License is distributed on an "AS IS"
basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
License for the specific language governing rights and limitations
under the License.

The Original Code is H3DNetworkingUtils v1.0.

The Initial Developer of the Original Code is CSIRO.
Portions created by the Initial Developer are Copyright (C) 1009 CSIRO. All Rights Reserved.
Contributor(s):
    Chris Gunn  <Chris.Gunn@csiro.au> <ChrisJGunn@gmail.com>
***************************/

/// \file RemoteUDPServer.h
/// \brief Header file for RemoteUDPServer, a server communications link that uses UDP/IP network protocol.

#ifndef RemoteUDPServer_H
#define RemoteUDPServer_H


#include "H3DNetworkingUtils/RemoteServer.h"
#include "H3DNetworkingUtils/lockwrap.h"

namespace H3DNetworkingUtils {

/// \class RemoteUDPServer
/// The RemoteUDPServer class starts a Remote server using a UDP port.
/// It starts listening on the given port for a connection from a
/// Remote Client, then continues with the base class's behaviour using the port
/// for comms.
/// UDP is connectionless, data can come from any client.
/// In our usage, it should always come from the same client, although currently
/// this is not checked.
/// When open is changed from false to true, the listening port is monitored
/// for a connection from a client.
/// When it is changed from true to false, the connection is closed.
/// At present, only one remote connection is handled at any one time.

/// IMPORTANT NOTE: Do not route from anything in the haptics loop to a remote
/// field if you have periodicSend FALSE. This is because it will then try to
/// send whenever the value changes - i.e. from the haptics loop itself. This will
/// fail, because the haptics loop has special capabilities which seem to prevent
/// it using sockets. You probably don't want it to interrupt haptics to do socket
/// stuff anyway. Make sure you set periodic send true if you are routing in from
/// the haptics thread.

/// When the client first connects, it sends a pulse packet to the server. The
/// servers responds with a pulse.  \n
/// <b>Examples:</b>
///   - <a href="../../examples/RealtimeAttractorTestServer.x3d">RealtimeAttractorTestServer.x3d</a>
///   - <a href="../../examples/RealtimeAttractorTestClient.x3d">RealtimeAttractorTestClient.x3d</a>

class H3D_NETWORKING_UTILS_DLL_SPEC RemoteUDPServer : public RemoteServer {
public:

   /// Constructor
   RemoteUDPServer();

   /// Destructor
   virtual ~RemoteUDPServer();

  /// The X3D interface
  static H3D::H3DNodeDatabase database;

protected:

  /// Write a single packet of data to socket
  virtual void sendThisPacket(Packet & packet);

  /// This function runs in a new thread.
  virtual void receiveLoop ();

  /// This function runs in a new thread.
  virtual void sendLoop();

  /// Start the server
  virtual void startServer(int port_number);

private:
  InetAddr remote_end;
  Packet pulse_packet;
  Mutex send_packet_lock;
  double accumulated_time_to_kill;
};

}

#endif
