| |
libFAUDES
Sections
Index
|
iop_simplenet.hGo 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