/*****************************
File:      RemoteTCPServer.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 RemoteTCPServer.h
/// \brief Header file for RemoteTCPServer, a server communications link that uses TCP/IP network protocol.

#ifndef RemoteTCPServer_H
#define RemoteTCPServer_H

#include "H3DNetworkingUtils/RemoteServer.h"

// This next line is needed because H3DAPI.dll instantiates this template but this class does not see the header with 
// the instantiation in it. So without the line, this class would instantiate an identical one and there would
// be a multiply defined symbol in the link stage.
template struct __declspec(dllimport) H3D::AutoUpdate <H3D::SFBool>;

namespace H3DNetworkingUtils {
   
/// \class RemoteTCPServer
/// The RemoteTCPServer class starts a Remote server using a TCP port.
/// It starts listening on the given port for a connection from a
/// remote client, then continues with the base class's behaviour, using a
/// newly allocate dport for communications.
/// 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.  \n
/// <b>Examples:</b>
///   - <a href="../../examples/RemoteSFTestServer.x3d">RemoteMFTestServer.x3d</a>
///   - <a href="../../examples/RemoteSFTestClient.x3d">RemoteMFTestClient.x3d</a>

class H3D_NETWORKING_UTILS_DLL_SPEC RemoteTCPServer : public RemoteServer {
public:

   /// Constructor
   RemoteTCPServer();

   /// Destructor
   virtual ~RemoteTCPServer();

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

protected:

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

   /// Start the receiving thread.
   virtual void startReceiving();

   /// This function runs in a new thread, to listen for new connections.
   virtual void listeningLoop();

  /// Data for the listening loop to use \n
  ///(A second thread cannot safely read
  /// fields used by the graphics thread)
   struct ListenData {
    int port;
    bool periodic_send;
  };

  static void listeningThread(void * client_data) {
    static_cast<RemoteTCPServer*>(client_data)->listeningLoop();
  }

   /// returns true if the listening loop is running
   bool listeningLoopRunning();

   /// Start the listening loop
   void setListeningLoopRunning(bool v);
   
   /// Stop the listening loop
   void stopListeningThread();
   
   bool keepListening();

private:
  Thread * listening_threadP;
  ListenData listen_data; // After initial setup, this should only be used by
  // the listening loop.

  bool periodic_snd; // A copy of the periodic_send field value for use in the
  // listening thread.

   bool stop_listening_thread;
   bool listening_loop_running;  // This is accessed by several threads. Use listeningLoopRunning() for safe access.
   Mutex listening_loop_lock;
};

}

#endif
