libFAUDES

Sections

Index

iop_simplenet.h

Go to the documentation of this file.
00001 /** @file iop_simplenet.h Simple networked events via tcp/ip */
00002 
00003 /* 
00004    FAU Discrete Event Systems Library (libfaudes)
00005 
00006    Copyright (C) 2008, Thomas Moor
00007    Exclusive copyright is granted to Klaus Schmidt
00008 
00009 */
00010 
00011 
00012 
00013 #ifndef FAUDES_IOP_SIMPLENET_H
00014 #define FAUDES_IOP_SIMPLENET_H
00015 
00016 #include "corefaudes.h"
00017 #include "iop_vdevice.h"
00018 
00019 
00020 #ifndef FAUDES_WINEXTRA
00021 #include <sys/socket.h>
00022 #include <arpa/inet.h>
00023 #include <netdb.h>
00024 #include <cerrno>
00025 #else
00026 #include <winsock2.h>
00027 #include <pthread.h>
00028 #endif
00029 
00030  
00031 
00032 namespace faudes {
00033 
00034 
00035 /**
00036  * Simplenet node address.
00037  *
00038  * A node address consists of an ip address and a tcp port.
00039  * This convenience class implements string based access to both components.
00040  *
00041  */
00042 
00043 class SimplenetAddress {
00044 
00045 public:
00046 
00047   /** Default constructor */
00048   SimplenetAddress(void);
00049 
00050   /** Copy construct */
00051   SimplenetAddress(const SimplenetAddress& rOther);
00052 
00053   /** Construct from string */
00054   SimplenetAddress(const std::string& rString);
00055 
00056   /** Return true if valid */
00057   bool Valid(void) const;
00058 
00059   /** Get ip address */
00060   std::string Ip(void) const { return mIp; };
00061 
00062   /** Get tcp port */
00063   int Port(void) const { return mPort; };
00064 
00065   /** Get as colon seperated string */
00066   std::string IpColonPort(void) const;
00067 
00068   /** Set ip address */
00069   void Ip(std::string ip) { mIp=ip; };
00070 
00071   /** Set tcp port  */
00072   void Port(int port) { mPort=port; };
00073 
00074   /** Set from colon seperated string */
00075   void IpColonPort(std::string ipcolonport);
00076   
00077   /** Order for sorting containers of addresses */
00078   bool operator < (const SimplenetAddress& rOther) const;
00079 
00080  protected:
00081 
00082   /** Ip address */  
00083   std::string mIp;
00084 
00085   /** Tcp port */
00086   int mPort;
00087 
00088 };
00089 
00090 
00091 /**
00092  * Configuration of a network actuator mapping.
00093  *
00094  * There is nothing to configure here: any client that
00095  * connects to this device can subscribe to any actuator event.
00096  * Future versions of libFAUDES may specify a set of receipent
00097  * clients.
00098  *
00099  */
00100 
00101 class AttributeSimplenetActuator : public AttributeVoid {
00102 
00103 FAUDES_TYPE_DECLARATION(AttributeSimplenetActuator,AttributeVoid)
00104 
00105 public:
00106 
00107   /** Default constructor */
00108   AttributeSimplenetActuator(void) : AttributeVoid() {}; 
00109 
00110   /** Test for default value (never) */
00111   virtual bool IsDefault(void) const {return false;};
00112 
00113   /** Clear to default */
00114   virtual void Clear(void) {};
00115 
00116 protected:
00117 
00118   /** Copy method 
00119    *
00120    * @param rSrcAttr
00121    *   Source to copy from
00122    * @return
00123    *   Ref to this attribute
00124    */
00125   virtual AttributeSimplenetActuator& DoAssign(const AttributeSimplenetActuator& rSrcAttr) 
00126   {(void) rSrcAttr; return *this;};
00127 
00128   /**
00129    * Reads the attribute from TokenReader, see AttributeVoid for public wrappers.
00130    * 
00131    * If the current token indicates a sensor mapping, the method reads that
00132    * section. Else it does nothing. Exceptions may only be thrown
00133    * on invalid data within the section. The label argument is ignored, we use the 
00134    * hardcoded section "Actuator" for actuator attributes. The context argument is ignored.
00135    *
00136    * @param rTr
00137    *   TokenReader to read from
00138    * @param rLabel
00139    *   Section to read
00140    * @param pContext
00141    *   Read context to provide contextual information
00142    *
00143    * @exception Exception
00144    *   - IO error (id 1)
00145    */
00146   virtual void DoRead(TokenReader& rTr,const std::string& rLabel="", const Type* pContext=0);
00147  
00148   /**
00149    * Writes the attribute to TokenWriter, see AttributeVoid for public wrappers.
00150    *
00151    * Writes the actuator mapping data. The label argument is ignored, we use 
00152    * the hardcoded section "Actuator". The context argument is ignored.  
00153    *
00154    * @param rTw
00155    *   TokenWriter to write to
00156    * @param rLabel
00157    *   Section to write
00158    * @param pContext
00159    *   Read context to provide contextual information
00160    *
00161    * @exception Exception
00162    *   - IO error (id 2)
00163    */
00164   virtual void DoWrite(TokenWriter& rTw,const std::string& rLabel="", const Type* pContext=0) const;
00165 
00166 }; // end class AttributeSimplenetActuator
00167 
00168 
00169 /**
00170  * Configuration of a network sensor mapping.
00171  *
00172  * There is nothing to configure here: any server that
00173  * provides the repective event will be accepted. Future versions 
00174  * of libFAUDES may specify a set of servers here.
00175  *
00176  */
00177 
00178 class AttributeSimplenetSensor : public AttributeVoid {
00179 
00180 FAUDES_TYPE_DECLARATION(AttributeSimplenetSensor,AttributeVoid)
00181 
00182 public:
00183 
00184   /** Default constructor (no triggers) */
00185  AttributeSimplenetSensor(void) : AttributeVoid() {}; 
00186 
00187   /** Test for default value (never) */
00188   virtual bool IsDefault(void) const {return false;};
00189 
00190   /** Clear to default */
00191   virtual void Clear(void) {};
00192 
00193 protected:
00194 
00195   /** Copy method 
00196    *
00197    * @param rSrcAttr
00198    *   Source to copy from
00199    * @return
00200    *   Ref to this attribute
00201    */
00202   virtual AttributeSimplenetSensor& DoAssign(const AttributeSimplenetSensor& rSrcAttr) 
00203   {(void) rSrcAttr; return *this;};
00204 
00205 
00206   /**
00207    * Reads the attribute from TokenReader, see AttributeVoid for public wrappers.
00208    * 
00209    * If the current token indicates a sensor mapping, the method reads that
00210    * section. Else it does nothing. Exceptions may only be thrown
00211    * on invalid data within the section. The label argument is ignored, we the hardcoded
00212    * section "Sensor" for sensor device attributes. The context argument is ignored.
00213    *
00214    * @param rTr
00215    *   TokenReader to read from
00216    * @param rLabel
00217    *   Section to read
00218    * @param pContext
00219    *   Read context to provide contextual information
00220    *
00221    * @exception Exception
00222    *   - IO error (id 1)
00223    */
00224   virtual void DoRead(TokenReader& rTr,const std::string& rLabel="", const Type* pContext=0);
00225  
00226   /**
00227    * Writes the attribute to TokenWriter, see AttributeVoid for public wrappers.
00228    *
00229    * Writes the sensor mapping data.The label argument is ignored, we use 
00230    * the hardcoded section "Sensor". The context argument is ignored.  
00231    *
00232    * @param rTw
00233    *   TokenWriter to write to
00234    * @param rLabel
00235    *   Section to write
00236    * @param pContext
00237    *   Read context to provide contextual information
00238    *
00239    * @exception Exception
00240    *   - IO error (id 2)
00241    */
00242   virtual void DoWrite(TokenWriter& rTw,const std::string& rLabel="", const Type* pContext=0) const;
00243 
00244 }; // end class AttributeSimplenetSensor
00245 
00246 
00247 
00248 /**
00249  * Configuration of a networked sensor or actuator 
00250  *
00251  * This class is derived from the AttributeDeviceEvent to specialise
00252  * for networked sensor and actuator mapping.
00253  *
00254  */
00255 
00256 class AttributeSimplenetEvent : public AttributeDeviceEvent {
00257 
00258  FAUDES_TYPE_DECLARATION(AttributeSimplenetEvent,AttributeDeviceEvent)
00259 
00260 public:
00261 
00262   /** Default constructor (no mapping at all) */
00263   AttributeSimplenetEvent(void);
00264 
00265   /** Copy constructor */
00266   AttributeSimplenetEvent(const AttributeSimplenetEvent& rOtherAttr);
00267 
00268   /** Test for default value (never) */
00269   virtual bool IsDefault(void) const {return false;};
00270 
00271   /** Clear */
00272   virtual void Clear(void)  { AttributeDeviceEvent::Clear(); };
00273 
00274   /**  Get actuator mapping */
00275   const AttributeSimplenetActuator*  Actuatorp(void) const {
00276     return static_cast<AttributeSimplenetActuator*>(mpActuatorAttribute); };
00277 
00278   /**  Get sensor mapping */
00279   const AttributeSimplenetSensor*  Sensorp(void) const {
00280     return static_cast<AttributeSimplenetSensor*>(mpSensorAttribute); };
00281 
00282 protected:
00283 
00284   /** DoAssign */
00285   virtual AttributeSimplenetEvent& DoAssign(const AttributeSimplenetEvent& rSrc)  
00286   { AttributeDeviceEvent::DoAssign(rSrc); return *this;};
00287 
00288   /** Prototype, sensor */
00289   static AttributeSimplenetSensor sSensorPrototype;
00290 
00291   /** Prototype, actuator */
00292   static AttributeSimplenetActuator sActuatorPrototype;
00293 
00294 }; // class AttributeSimplenetEvent
00295 
00296 
00297 /**
00298  * An nDevice implements networked IO via a simple tcp/ip protocol. 
00299  *
00300  * @section SecIodeviceNDev1 Networking
00301  *
00302  * The purpose of this implementation of networked discrete events is to provide
00303  * a basis for case studies. However, simple networked events via nDevice must not 
00304  * be confused with ongoing research that addresses synchronisation and real 
00305  * time behaviour. We take a really pragmatic approach here.
00306  *
00307  * Our <em>network</em> is identified by its <em>network name</em>. It consists
00308  * a number of <em>nodes</em>, each identified by its <em>node name</em>. In the current implementation,
00309  * each node knows about the entire network ie knows about all other nodes. Each node plays two roles:
00310  * - the <em>server</em> role to send event notifications, and
00311  * - the <em>client</em> role to receive event notifications.
00312  *
00313  * As a server, the node is configured to listen on its <em>server port</em> for incomming 
00314  * tcp connections. When a client (eg some other node in client role) connects to the tcp port, the server 
00315  * replies to a simple command set in order to allow the client to subscribe to the nodes actuator events.
00316  * When the application executes an actuator on the node, this is notified to all connected clients and
00317  * the clients will interpret the event as a sensor reading. Vice versa, the node itself has the 
00318  * role of a client and subscribes its sensor events from all other nodes. 
00319  *
00320  * @section SecIodeviceNDev2 Protocol Details
00321  *
00322  * The protocol for commands and notification is libFAUDES-token based and can be inspected eg via nc or telnet; 
00323  * see the shell script in the tutorial. 
00324  * Event notifications are sent spontaneous to all subscribing nodes in the format 
00325  * <tt><Notify> "event" </Notify></tt>.
00326  * Commands are accepted in the format <tt><Cmd> "command" </Cmd></tt> and will be
00327  * answered accordingly.
00328  *
00329  * <table>
00330  * <tr>
00331  * <td> Command on tcp server port</td>
00332  * <td> Reply </td>
00333  * </tr>
00334  * <tr>
00335  * <td>  <tt><Cmd> "Info"  </Cmd></tt> </td>
00336  * <td> Configuration of node as token string </td>
00337  * </tr>
00338  * <tr>
00339  * <td> <tt><Cmd> "Status"  </Cmd></tt>  </td>
00340  * <td> Up/StartUop/Down/ShutDown </td>
00341  * </tr>
00342  * <tr>
00343  * <td> <tt><Subscribe> "ev1" ... "evN"  </Subscribe></tt> </td>
00344  * <td> Positive Acknowledge to accept subscription of events </td>
00345  * </tr>
00346  * </table>
00347  *
00348  * @section SecIodeviceNDev3 Name Resolution
00349  *
00350  * On the technical side, each node needs to figure the ip addresses incl tcp ports on which the 
00351  * other nodes provide their service. To ease configuration, this information is distributed by 
00352  * udp datagrams. In order to locate the other nodes within the network, a node may  broadcasts a 
00353  * network <em>request</em> datagramm. Each node that receives such a request, replies with an 
00354  * <em>advert</em> datagramm to provide its address. Thus, the simple net nodes rely on some 
00355  * underlying name resolution by dns services, but node configuration itself refers to simple-net node names
00356  * only. Since each node knows about the names of all participating nodes, each node will know when 
00357  * all connections are up. 
00358  * 
00359  * <table>
00360  * <tr>
00361  * <td> Broadcast on simplenet udp port</td>
00362  * <td> Reply </td>
00363  * </tr>
00364  * <tr>
00365  * <td> <tt><Request> "network"  </Request></tt> </td>
00366  * <td> Advertisement of networkname, nodename and ip-address:port </td>
00367  * </tr>
00368  * </table>
00369  * <p>
00370  *
00371  * @section SecIodeviceNDev4 File IO
00372  *
00373  * For token IO, the nDevice reads and writes a section with label  
00374  * "SimplenetDevice". There are no relevant attributes yet. Simple machine example:
00375  *
00376  * @code
00377  * <SimplenetDevice>
00378  *
00379  * "simplemachine"     % node id
00380  * 1000                % time scale (ms/ftu)
00381  * "localhost:40000"   % server tcp port 
00382  * "simpleloop"        % network id
00383  *
00384  * <Network>           
00385  * "simplemachine"     % other nodes ..,
00386  * "simplesupervisor"  % ... in this network
00387  * </Network>
00388  *
00389  * <SimplenetEvents>
00390  * "alpha"  <Input></Input>
00391  * "beta"   <Output></Output>
00392  * "mue"    <Output></Output>
00393  * "lambda" <Input></Input>
00394  * </SimplenetEvents>
00395  *
00396  * </SimplenetDevice>
00397  * @endcode
00398  *
00399  * @section SecIodeviceNDev5 Implementation Notes
00400  *
00401  * The current status of the code is premature; network io
00402  * assumes reasonably large buffers; thread/select mechanism is inefficient; 
00403  * exception handling wont work; etc etc
00404  * 
00405  *
00406  * @ingroup IODevicePlugin 
00407  */
00408 
00409 class nDevice : public vDevice {    
00410 
00411   // provide all access to background tasks
00412   friend void* NDeviceListen(void*);
00413   friend void* NDeviceServer(void*);
00414   friend void* NDeviceReply(void*);
00415 
00416  public:
00417   /**
00418    * Default constructor
00419    */
00420   nDevice(void);
00421 
00422   /**
00423    * Explicit destructor.
00424    */
00425   virtual ~nDevice(void);
00426 
00427   /**
00428    * Clear all configuration.
00429    * This implies Stop().
00430    */
00431   virtual void Clear(void);
00432 
00433   /**
00434    * Set up internal data structures
00435    *
00436    */
00437   virtual void Compile(void);
00438 
00439   /**
00440    * Add entry to node name resolution
00441    *
00442    * @param rNode
00443    *   Name of node to register
00444    * @param rAddress 
00445    *  Address incl port 
00446    */
00447   void InsertNodeAddress(const std::string& rNode, const SimplenetAddress& rAddress);
00448  
00449 
00450   /**
00451    * Activate the device. This function enables actuator execution and sensor reading.
00452    * It starts the background thread for incomming connections and tries to connect to relevant servers.
00453    *
00454    * @exception Exception
00455    *   - Not yet configured (id 551)
00456    *   - Fatal network error (id 553)
00457    *   - Fatal pthread error (id 554)
00458    */
00459   virtual void Start(void);
00460 
00461   /**
00462    * Deactivate the device. This function disables actuator execution and sensor reading.
00463    * It stops the backhround thread to provide connections and disconnects from any servers.
00464    */
00465   virtual void Stop(void);
00466 
00467   /**
00468    * Reset device. Resets buffered sensor events and current time.
00469    *
00470    */
00471   virtual void Reset(void);
00472 
00473   /**
00474    * Run actuator command.
00475    *
00476    * @exception Exception
00477    *   - unknown actuator event (id 65)
00478    */
00479   virtual void WriteActuator(Idx actuator);
00480 
00481 
00482 
00483  protected:
00484 
00485   /**
00486    * Actual method to read device configuration from tokenreader.
00487    *
00488    * This method calls the base class to read the device name and the
00489    * the timescale. It then reads address, networkid and nodes.
00490    * Overall device configuration is consists of DoReadPreface,
00491    * DoReadConfiguration and Compile. It isimplemented in vDevice.
00492    * The label and context parameters are ignored.
00493    *
00494    * @param rTr
00495    *   TokenReader to read from
00496    * @param rLabel
00497    *   Section to read
00498    * @param pContext
00499    *   Read context to provide contextual information
00500    *
00501    * @exception Exception
00502    *   - IO error (id 1)
00503    */
00504   virtual void DoReadPreface(TokenReader& rTr,  const std::string& rLabel = "", const Type* pContext=0);
00505  
00506   /**
00507    * Actual method to write the device configuration to a TokenWriter.
00508    *
00509    * This method calls the base class vDevice to write the device name and
00510    * the time scale. It then writes network related data. The label and
00511    * context parameters are ignored.
00512    *
00513    * @param rTw
00514    *   Reference to TokenWriter
00515    * @param rLabel
00516    *   Label of section to write
00517    * @param pContext
00518    *   Read context to provide contextual information
00519    * @exception Exception 
00520    *   - IO errors (id 2)
00521    */
00522   virtual void DoWritePreface(TokenWriter& rTw, const std::string& rLabel="", const Type* pContext=0) const;
00523 
00524 
00525   /** Overall configuration (with actual type) */
00526   TaNameSet<AttributeSimplenetEvent>* pConfiguration ;
00527 
00528   /** Simplenet: network id */
00529   std::string mNetwork;
00530 
00531   /** Simplenet: address of my server port */
00532   SimplenetAddress mAddress;
00533 
00534   /** Simplenet: effective address of my server port */
00535   SimplenetAddress mEffectiveAddress;
00536 
00537   /** Simplenet: list of nodes in this network */
00538   std::set<std::string> mNetworkNodes;
00539   
00540   /** Simplenet: list of event server addresses */
00541   std::set<std::string> mSensorServers;
00542   
00543   /** Compiled data: map subscriptions */
00544   std::map<std::string,EventSet> mSensorSubscriptions;
00545 
00546   /** Background: mutex for below shared variables*/
00547   pthread_mutex_t mMutex;
00548 
00549   /** Background: thread handle (global) */
00550   pthread_t mThreadListen; 
00551 
00552   /** Background: request to join via flag (mutexed) */
00553   bool mStopListen;
00554 
00555   /** Background: server socket to listen (background only) */
00556   int mServerSocket;
00557   
00558   /** Background: server port to bind (background only) */
00559   struct sockaddr_in mServerAddress;
00560 
00561   /** Background: udp broadcast socket (background only) */
00562   int mBroadcastSocket;
00563   
00564   /** Background: state of a connection to a client (shared) */
00565   typedef struct {
00566     nDevice* mDevice;        // refernce to this device
00567     int  mClientSocket;      // the socket the client is connected to
00568     pthread_t mThread;       // the thread we run to reply to client requests
00569     EventSet mEvents;        // events the client has subscribed to 
00570   } ClientState;  
00571 
00572   /** Background: map sockets to connection states (shared) */
00573   std::map<int, ClientState> mActuatorClientStates;
00574 
00575   /** Background: state of a connection to an event server (shared)*/
00576   typedef struct {
00577     SimplenetAddress mAddress;  // ip address incland tcp port of remote server
00578     EventSet mEvents;           // events we have subscribed to
00579     int  mServerSocket;         // socket used to connect with provider
00580     std::string mLineBuffer;    // buffer to receive one line
00581   } ServerState;  
00582 
00583   /** Background: connection states to event servers (by node name)*/
00584   std::map<std::string,ServerState> mSensorServerStates;
00585 
00586 
00587 
00588 }; // end class nDevice
00589 
00590 // declare background threads
00591 void* NDeviceListen(void*);
00592 void* NDeviceServer(void*);
00593 void* NDeviceReply(void*);
00594 
00595 } // namespace faudes
00596 
00597 
00598 #endif // include

libFAUDES 2.14g --- 2009-12-3 --- c++ source docu by doxygen 1.5.6