- Main Page
- Classes
- Files

- Search for |

# RemoteConnection.h

Go to the documentation of this file.

    00001 /*****************************
    00002 File:      RemoteConnection.h
    00003 Language:   C++ (header)
    00004 Project:    H3DNetworkingUtils
    00005 The contents of this file are subject to the Mozilla Public License
    00006 Version 1.1 (the "License"); you may not use this file except in
    00007 compliance with the License. You may obtain a copy of the License at
    00008 http://www.mozilla.org/MPL/
    00009
    00010 Software distributed under the License is distributed on an "AS IS"
    00011 basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
    00012 License for the specific language governing rights and limitations
    00013 under the License.
    00014
    00015 The Original Code is H3DNetworkingUtils v1.0.
    00016
    00017 The Initial Developer of the Original Code is CSIRO.
    00018 Portions created by the Initial Developer are Copyright (C) 1009 CSIRO. All Rights Reserved.
    00019 Contributor(s):
    00020     Chris Gunn  <Chris.Gunn@csiro.au> <ChrisJGunn@gmail.com>
    00021 ***************************/
    00022
    00025
    00026 #ifndef RemoteConnection_H
    00027 #define RemoteConnection_H
    00028
    00029
    00030 #include "H3DNetworkingUtils/Config.h"
    00031 #include <H3D/Group.h>
    00032 #include <H3DUtil/Threads.h>
    00033 #include "H3DNetworkingUtils/RemoteField.h"
    00034 #include "H3DNetworkingUtils/sockwrap.h"
    00035 #include "H3DNetworkingUtils/lockwrap.h"
    00036 #include "H3DNetworkingUtils/threadwrap.h"
    00037 #include "H3DNetworkingUtils/PacketSequenceChecker.h"
    00038 #include "H3DNetworkingUtils/Packet.h"
    00039 #include <queue>
    00040 #include "H3DNetworkingUtils/BufferedSField.h"
    00041 #include "H3DNetworkingUtils/RemoteSync.h"
    00042
    00043 namespace H3D {
    00044   H3D_VALUE_EXCEPTION( int, RemoteFieldIDTooLarge );
    00045 }
    00046
    00047 namespace H3DNetworkingUtils {
    00048
    00077
    00078 class H3D_NETWORKING_UTILS_DLL_SPEC RemoteConnection : public H3D::Group {
    00079 public:
    00080
    00081    static H3D::H3DNodeDatabase database;
    00082
    00083    virtual ~RemoteConnection();
    00084    virtual void initialize();
    00085
    00086    class H3D_NETWORKING_UTILS_DLL_SPEC MFRemoteField : public H3D::TypedMFNode< RemoteField >{
    00087    public:
    00088       virtual void onAdd(H3D::Node * nodeP);
    00089       RemoteConnection * conP;
    00090    };
    00091
    00092    typedef H3D::TypedSFNode<RemoteSync> SFRemoteSync;
    00093
    00094    // Public fields
    00095
    00101    auto_ptr<H3D::SFString      >      errorMessage;
    00102
    00109    auto_ptr<H3D::SFString      >      infoMessage;
    00110
    00119    auto_ptr<H3D::SFFloat       >      simulatedLatency;
    00120
    00121    auto_ptr<MFRemoteField      >      remoteFields;
    00122
    00132    auto_ptr<H3D::SFBool        >      periodicSend;
    00133
    00138    auto_ptr<H3D::SFFloat       >      periodicSendRate;
    00139
    00144    auto_ptr<SFRemoteSync       >      remoteSync;
    00145
    00150    auto_ptr<BufferedSField<H3D::SFBool> >      isConnected;
    00151
    00152
    00153    typedef void (* CallbackFn)(void *);
    00154
    00156    void setOpenCommsCallbackFn(CallbackFn fn, void * client_data) {
    00157       open_comms_cb_fn = fn;
    00158       open_comms_cb_data = client_data;
    00159    }
    00160
    00162    void setCloseCommsCallbackFn(CallbackFn fn, void * client_data) {
    00163       close_comms_cb_fn = fn;
    00164       close_comms_cb_data = client_data;
    00165    }
    00166
    00168    virtual void requestClose();
    00169
    00171    bool closeRequested() const {return close_requested;}
    00172
    00174    void read(char * data, int num_bytes) {read_packet.read(data, num_bytes);}
    00175
    00178    void write(const char * data, int num_bytes) {write_packet.write((void*)data, num_bytes);}
    00179
    00181    bool hasSock() const {return sockP != 0;}
    00182
    00186    virtual void showError(const char * msg);
    00187
    00190    virtual void showInfo(const char * msg);
    00191
    00194    virtual void showInfo(const string msg)   {showInfo(msg.data());}
    00195
    00197    void writeFieldHeader(int fld_id, bool with_timestamp);
    00198
    00200    double readDouble();
    00201
    00203    void writeDouble(const double & val);
    00204
    00206    float readFloat();
    00207
    00209    void writeFloat(const float & val);
    00210
    00212    H3D::H3DFloat readH3DFloat() {return (H3D::H3DFloat)readDouble();}
    00213
    00215    void writeH3DFloat(const H3D::H3DFloat & val) {writeDouble(val);}
    00216
    00222    virtual void sendPacket();
    00223
    00226    void lockWriteThread() {write_lock.lock();}
    00227
    00229    void unlockWriteThread() {write_lock.unlock();}
    00230
    00231
    00232
    00233 protected:
    00234    // traverseSG traverses the RemoteFields in turn.
    00235    virtual void traverseSG( H3D::TraverseInfo &ti );
    00236
    00237    RemoteConnection( H3D::Inst<H3D::SFString       >     _errorMessage = 0,
    00238                      H3D::Inst<H3D::SFString       >     _infoMessage = 0,
    00239                      H3D::Inst<H3D::SFFloat        >     _simulatedLatency = 0,
    00240                      H3D::Inst<MFRemoteField       >     _remoteFields = 0,
    00241                      H3D::Inst<H3D::SFBool         >     _periodicSend = 0,
    00242                      H3D::Inst<H3D::SFFloat        >     _periodicSendRate = 0,
    00243                      H3D::Inst<SFRemoteSync        >     _remoteSync = 0,
    00244                      H3D::Inst<BufferedSField<H3D::SFBool>  > _isConnected = 0);
    00245    // Constructor is protected so that it can not explicitely be called:
    00246    // rather it should be implicely called from an inheriting class's
    00247    // constructor.
    00248    // This is since it is an abstract class.
    00249
    00250    static void receivingLoopTH(void * client_data) {
    00251       static_cast<RemoteConnection*>(client_data)->receiveLoop();
    00252    }
    00253
    00254    virtual void receiveLoop();
    00255    // Wait and receive packets.
    00256
    00257    virtual bool doClosedActions() {return false;}
    00258    // Do any actions that are required while the connection is closed.
    00259    // This is different for servers and clients, so must be overridden.
    00260    // The return value tells the receive loop whether to break out of the
    00261    // loop.
    00262    // NOTE Make sure you only call this from the receiving thread.
    00263
    00264    virtual bool receivePacket();
    00265    // read a single packet of data from socket
    00266    // Returns false on failure, true on success..
    00267
    00268    virtual void sendThisPacket(Packet & packet);
    00269    // Write a single packet of data to socket, given the packet
    00270
    00271    virtual void readPacket();
    00272    // get data from the packet
    00273
    00274    virtual void readField(int field_id);
    00275    // Read the field with the given id.
    00276
    00277    static void sendLoopTH(void * client_data) {
    00278       RemoteConnection * objP = static_cast<RemoteConnection* >(client_data);
    00279       objP->sendLoop();
    00280    }
    00281    virtual void sendLoop();
    00282    // The send loop thread starts here, if we are doing periodic sending.
    00283
    00284    void setConnected(bool val) {
    00285       connected = val;
    00286       isConnected->setValue(val, id);
    00287    }
    00288
    00289    virtual void setSendTimeout(InetSock * sockP, int millisecs);
    00290    // Set the timeout on send operations.
    00291
    00292    virtual void sendFields(bool first_connection);
    00293    // Sends all fields once only.
    00294    // If first connection ios true, it will send only those fields that have
    00295    // sendOnConnect true.
    00296    // if first_connection is false, it will send all fields.
    00297
    00298    virtual void doGraphicsLoopActions();
    00299    // Do any actions required periodically at graphics loop rate.
    00300    // Note this does NOT handle the periodic send option, that happens in
    00301    // another thread.
    00302
    00303    void requestOpenComms() {
    00304       comms_lock.lock();
    00305       comms_open_requested = true;
    00306       comms_lock.unlock();
    00307    }
    00308
    00309    bool commsOpenRequested() const {
    00310       comms_lock.lock();
    00311       bool ret = comms_open_requested;
    00312       comms_lock.unlock();
    00313       return ret;
    00314    }
    00315
    00316    virtual void close();
    00317    // Close the connection.
    00318
    00319    // Request comms to be opened.
    00320    // If periodicSend, a new thread to send periodically will be created.
    00321
    00322    bool isShuttingDown();
    00323    void setShuttingDown(bool v);
    00324
    00325    bool receiveLoopRunning();
    00326    void setReceiveLoopRunning(bool v);
    00327
    00328    bool sendLoopRunning();
    00329    void setSendLoopRunning(bool v);
    00330
    00331    InetSock * sockP;
    00332    bool close_requested;
    00333    Thread * receive_loop_threadP;
    00334    Thread * send_loop_threadP;
    00335    bool use_seq_numbers;
    00336    Packet write_packet;
    00337    Packet read_packet;
    00338    bool initialized;
    00339    double period;
    00340    double last_send_time;
    00341    double last_try_time;
    00342    CallbackFn open_comms_cb_fn;
    00343    void * open_comms_cb_data;
    00344    CallbackFn close_comms_cb_fn;
    00345    void * close_comms_cb_data;
    00346    Mutex sock_lock;
    00347    Semaphore connected_sem;
    00348    InetAddr remote_end;
    00349
    00350 private:
    00351    bool comms_open_requested;
    00352    mutable Mutex comms_lock;
    00353    mutable Mutex msg_lock;
    00354    Mutex write_lock;
    00355    PacketSequenceChecker::u_int16 seq_number;
    00356    PacketSequenceChecker seq_checker;
    00357    static const int MAX_PACKET_SIZE;
    00358    std::queue<Packet*> sim_latency_buffer;
    00359    bool sim_latency;
    00360    unsigned int max_sim_latency_buf_size;
    00361    bool little_endian;
    00362    static const int MAX_ID;
    00363    bool error_msg_waiting;
    00364    bool info_msg_waiting;
    00365    char * error_msg;
    00366    char * info_msg;
    00367    char * remote_client_addr;
    00368    bool connected; // We need this as well as the isConnected field, since
    00369                      // that is a ThreadSafe field and may not get changed immediately.
    00370
    00371    bool shutting_down;  // This is accessed by several threads. Use isShuttingDown() for safe access.
    00372    Mutex shutdown_lock;
    00373    bool receive_loop_running;  // This is accessed by several threads. Use receiveLoopRunning() for safe access.
    00374    Mutex receive_loop_lock;
    00375    bool send_loop_running;  // This is accessed by several threads. Use sendLoopRunning() for safe access.
    00376    Mutex send_loop_lock;
    00377 };
    00378
    00379 }
    00380
    00381 #endif