|
libFAUDES
Sections
Index
|
iop_simplenet.cppGo to the documentation of this file.00001 /** @file iop_simplenet.cpp 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 #include "iop_simplenet.h" 00014 #include <time.h> 00015 #include <sys/time.h> 00016 00017 00018 // fix winsock 00019 #ifdef FAUDES_WINEXTRA 00020 #define close closesocket 00021 #define socklen_t int 00022 #define WINCASTSTR (char *) 00023 #else 00024 #define WINCASTSTR 00025 #endif 00026 00027 // fix non strict bsd 00028 #ifndef SO_REUSEPORT 00029 #define SO_REUSEPORT SO_REUSEADDR 00030 #endif 00031 00032 // todo: runtime opt for broadcast port 00033 #define FAUDES_IODEVICE_BROADCASTPORT 40000 00034 00035 namespace faudes { 00036 00037 00038 /* 00039 ********************************************** 00040 ********************************************** 00041 ********************************************** 00042 00043 implementation: SimplenetAddress 00044 00045 ********************************************** 00046 ********************************************** 00047 ********************************************** 00048 */ 00049 00050 // construct 00051 SimplenetAddress::SimplenetAddress(void) { 00052 mIp=""; 00053 mPort=-1; 00054 } 00055 00056 // copy construct 00057 SimplenetAddress::SimplenetAddress(const SimplenetAddress& rOther) { 00058 mIp=rOther.mIp; 00059 mPort=rOther.mPort; 00060 } 00061 00062 // construct from string 00063 SimplenetAddress::SimplenetAddress(const std::string& rString) { 00064 IpColonPort(rString); 00065 } 00066 00067 // validity 00068 bool SimplenetAddress::Valid(void) const { 00069 if(mPort<=0) return false; 00070 if(mIp=="") return false; 00071 if(mIp.find(':',0)!=std::string::npos) return false; 00072 return true; 00073 } 00074 00075 // get colon seperated string 00076 std::string SimplenetAddress::IpColonPort(void) const { 00077 std::string res; 00078 if(!Valid()) return res; 00079 res=mIp+":"+ToStringInteger(mPort); 00080 return res; 00081 } 00082 00083 // Set from colon seperated string 00084 void SimplenetAddress::IpColonPort(std::string ipcolonport) { 00085 FD_DHV("SimplenetAddress::IpColonPort(): " << ipcolonport << " --> ?"); 00086 // invalid 00087 mIp=""; 00088 mPort=-1; 00089 // find colon 00090 unsigned int cpos = ipcolonport.find(':',0); 00091 if(cpos==std::string::npos) return; 00092 if(cpos==0) return; 00093 if(cpos+1>= ipcolonport.length()) return; 00094 // extract ip 00095 mIp=ipcolonport.substr(0,cpos); 00096 // extract port 00097 mPort=ToIdx(ipcolonport.substr(cpos+1)); 00098 // report 00099 FD_DHV("SimplenetAddress::IpColonPort(): " << ipcolonport << " --> " << IpColonPort()); 00100 // test for errors (might be too strict) 00101 if(IpColonPort()!=ipcolonport) { 00102 mIp=""; 00103 mPort=-1; 00104 } 00105 } 00106 00107 // sorting 00108 bool SimplenetAddress::operator < (const SimplenetAddress& rOther) const { 00109 if(this->mIp < rOther.mIp) return true; 00110 if(this->mIp > rOther.mIp) return false; 00111 if(this->mPort < rOther.mPort) return true; 00112 return false; 00113 } 00114 00115 /* 00116 ********************************************** 00117 ********************************************** 00118 ********************************************** 00119 00120 implementation: AttributeSimplenetActuator 00121 00122 ********************************************** 00123 ********************************************** 00124 ********************************************** 00125 */ 00126 00127 // std faudes type 00128 FAUDES_TYPE_IMPLEMENTATION(AttributeSimplenetActuator,AttributeVoid) 00129 00130 00131 //DoWrite(rTw); 00132 void AttributeSimplenetActuator::DoWrite(TokenWriter& rTw, const std::string& rLabel, const Type* pContext) const { 00133 (void) rLabel; (void) pContext; 00134 rTw.WriteBegin("Output"); 00135 rTw.WriteEnd("Output"); 00136 } 00137 00138 00139 //DoRead(rTr) 00140 void AttributeSimplenetActuator::DoRead(TokenReader& rTr, const std::string& rLabel, const Type* pContext) { 00141 (void) rLabel; (void) pContext; 00142 // report 00143 FD_DHV("AttributeSimplenetActuator(" << this << ")::DoRead(tr)"); 00144 00145 // test for actuator section 00146 Token token; 00147 rTr.Peek(token); 00148 if(token.Type()!=Token::Begin) return; 00149 if(token.StringValue()!="Output") return; 00150 00151 // read actuator section 00152 rTr.ReadBegin("Output"); 00153 rTr.ReadEnd("Output"); 00154 } 00155 00156 00157 /* 00158 ********************************************** 00159 ********************************************** 00160 ********************************************** 00161 00162 implementation: AttributeSimplenetSensor 00163 00164 ********************************************** 00165 ********************************************** 00166 ********************************************** 00167 */ 00168 00169 00170 // std faudes type 00171 FAUDES_TYPE_IMPLEMENTATION(AttributeSimplenetSensor,AttributeVoid) 00172 00173 00174 //DoWrite(rTw); 00175 void AttributeSimplenetSensor::DoWrite(TokenWriter& rTw, const std::string& rLabel, const Type* pContext) const { 00176 (void) rLabel; (void) pContext; 00177 rTw.WriteBegin("Input"); 00178 rTw.WriteEnd("Input"); 00179 } 00180 00181 00182 //DoRead(rTr) 00183 void AttributeSimplenetSensor::DoRead(TokenReader& rTr, const std::string& rLabel, const Type* pContext) { 00184 (void) rLabel; (void) pContext; 00185 // report 00186 FD_DHV("AttributeSimplenetSensor(" << this << ")::DoRead(tr)"); 00187 00188 // test for sensor section 00189 Token token; 00190 rTr.Peek(token); 00191 if(token.Type()!=Token::Begin) return; 00192 if(token.StringValue()!="Input") return; 00193 00194 // read sensor section 00195 rTr.ReadBegin("Input"); 00196 rTr.ReadEnd("Input"); 00197 } 00198 00199 00200 00201 00202 /* 00203 ********************************************** 00204 ********************************************** 00205 ********************************************** 00206 00207 implementation: AttributeSimplenetEvent 00208 00209 ********************************************** 00210 ********************************************** 00211 ********************************************** 00212 */ 00213 00214 00215 // statics 00216 AttributeSimplenetActuator AttributeSimplenetEvent::sActuatorPrototype; 00217 AttributeSimplenetSensor AttributeSimplenetEvent::sSensorPrototype; 00218 00219 // std faudes type 00220 FAUDES_TYPE_IMPLEMENTATION(AttributeSimplenetEvent,AttributeDeviceEvent) 00221 00222 // Default constructor, set my prototypes 00223 AttributeSimplenetEvent::AttributeSimplenetEvent(void) : AttributeDeviceEvent() { 00224 FD_DHV("AttributeSimplenetEvent::AttributeSimplenetEvent(" << this << ")");; 00225 pActuatorPrototype=&sActuatorPrototype; 00226 pSensorPrototype=&sSensorPrototype; 00227 } 00228 00229 // Copy constructor 00230 AttributeSimplenetEvent::AttributeSimplenetEvent(const AttributeSimplenetEvent& rOtherAttr) : 00231 AttributeDeviceEvent() 00232 { 00233 FD_DHV("AttributeSimplenetEvent(" << this << "): form other attr " << &rOtherAttr); 00234 pActuatorPrototype=&sActuatorPrototype; 00235 pSensorPrototype=&sSensorPrototype; 00236 DoAssign(rOtherAttr); 00237 } 00238 00239 00240 00241 /* 00242 ********************************************** 00243 ********************************************** 00244 ********************************************** 00245 00246 implementation: nDevice 00247 00248 ********************************************** 00249 ********************************************** 00250 ********************************************** 00251 */ 00252 00253 // helper: send entire buffer 00254 int syncSend(int dest, const char* data, int len, int flag) { 00255 int from=0; 00256 int left=len; 00257 while(left>0) { 00258 int rc=send(dest, data+from, left, 0); 00259 if(rc<0) { 00260 std::stringstream errstr; 00261 errstr << "Simplenet fatal network error (cannot send message)"; 00262 throw Exception("nDevice::syncSend", errstr.str(), 553); 00263 } 00264 left-=rc; 00265 } 00266 return len; 00267 } 00268 00269 00270 // constructor 00271 nDevice::nDevice(void) : vDevice() { 00272 FD_DH("nDevice(" << this << ")::nDevice()"); 00273 mpConfiguration = new TaNameSet<AttributeSimplenetEvent>; 00274 pConfiguration = dynamic_cast< TaNameSet<AttributeSimplenetEvent>* >(mpConfiguration); 00275 // default token section 00276 mDefaultLabel="SimplenetDevice"; 00277 // default network data 00278 mName="SimplenetNode"; 00279 mNetwork="Simplenet"; 00280 mAddress.IpColonPort("localhost:40000"); 00281 // clear/prepare state 00282 pthread_mutex_init(&mMutex, NULL); 00283 mServerSocket=-1; 00284 mBroadcastSocket=-1; 00285 } 00286 00287 // destructor 00288 nDevice::~nDevice(void) { 00289 FD_DH("nDevice(" << this << ")::~nDevice()"); 00290 // stop 00291 Stop(); 00292 // clean up my data 00293 pthread_mutex_destroy(&mMutex); 00294 } 00295 00296 // clear all configuration 00297 void nDevice::Clear(void) { 00298 FD_DH("nDevice(" << this << ")::Clear()"); 00299 // call base, incl stop 00300 vDevice::Clear(); 00301 // clear compiled data 00302 mSensorSubscriptions.clear(); 00303 mSensorServers.clear(); 00304 } 00305 00306 // add node address 00307 void nDevice::InsertNodeAddress(const std::string& node, const SimplenetAddress& rAddress) { 00308 FD_DHV("nDevice(" << this << ")::InsertNodeAddress(" << node << ", " << rAddress.IpColonPort() << ")"); 00309 std::map<std::string,nDevice::ServerState>::iterator sit; 00310 sit=mSensorServerStates.find(node); 00311 // bail out on unknown nodes 00312 if(sit==mSensorServerStates.end()) return; 00313 // bail out on knwon address 00314 if(sit->second.mAddress.Valid()) return; 00315 // record 00316 sit->second.mAddress=rAddress; 00317 // todo: fix active sockets 00318 sit->second.mServerSocket=-1; 00319 // done 00320 FD_DH("nDevice(" << this << ")::InsertNodeAddress(" << node << ", " << rAddress.IpColonPort() << "): accept as new"); 00321 } 00322 00323 00324 //Compile(void) 00325 void nDevice::Compile(void){ 00326 //setup up internal data structure 00327 FD_DHV("nDevice(" << this << ")::Compile()"); 00328 // call base 00329 vDevice::Compile(); 00330 } 00331 00332 00333 //DoWritePreface(rTr,rLabel) 00334 void nDevice::DoWritePreface(TokenWriter& rTw, const std::string& rLabel, const Type* pContext) const { 00335 FD_DHV("nDevice::DoWrite()"); 00336 //call base 00337 vDevice::DoWritePreface(rTw,rLabel,pContext); 00338 // write my data 00339 rTw.WriteString(mAddress.IpColonPort()); 00340 rTw.WriteString(mNetwork); 00341 // write my nodes 00342 rTw.WriteBegin("Network"); 00343 std::set<std::string>::const_iterator nit; 00344 for(nit=mNetworkNodes.begin();nit!=mNetworkNodes.end();nit++) 00345 rTw.WriteString(*nit); 00346 rTw.WriteEnd("Network"); 00347 } 00348 00349 //DoRead(rTr,rLabel) 00350 void nDevice::DoReadPreface(TokenReader& rTr, const std::string& rLabel, const Type* pContext) { 00351 FD_DHV("nDevice::DoReadPreface()"); 00352 // call base (reads name and timescale) 00353 vDevice::DoReadPreface(rTr,rLabel,pContext); 00354 // read my data: server port 00355 mAddress.IpColonPort(rTr.ReadString()); 00356 if(!mAddress.Valid()) { 00357 std::stringstream errstr; 00358 errstr << "Simplenet address expected at " << rTr.FileLine(); 00359 throw Exception("nDevice::DoRead", errstr.str(), 50); 00360 } 00361 // read my data: network id 00362 mNetwork=rTr.ReadString(); 00363 // read network nodes 00364 mNetworkNodes.clear(); 00365 rTr.ReadBegin("Network"); 00366 while(!rTr.Eos("Network")) { 00367 mNetworkNodes.insert(rTr.ReadString()); 00368 } 00369 rTr.ReadEnd("Network"); 00370 } 00371 00372 00373 // lock - unlock shortcuts; 00374 #define LOCK_E {int rc = pthread_mutex_lock(&mMutex); \ 00375 if(rc) {FD_ERR("nDevice::LOCK_E: lock mutex error\n"); exit(1); }} 00376 #define UNLOCK_E {int rc = pthread_mutex_unlock(&mMutex); \ 00377 if(rc) {FD_ERR("nDevice::LOCK_E: unlock mutex error\n"); exit(1); }} 00378 #define TLOCK_E {int rc = pthread_mutex_lock(&ndevice->mMutex); \ 00379 if(rc) {FD_ERR("nDevice::TLOCK_E: lock mutex error\n"); exit(1); }} 00380 #define TUNLOCK_E {int rc = pthread_mutex_unlock(&ndevice->mMutex); \ 00381 if(rc) {FD_ERR("nDevice::TLOCK_E: unlock mutex error\n"); exit(1); }} 00382 00383 00384 // Write Actuator 00385 void nDevice::WriteActuator(Idx actuator) { 00386 00387 FD_DH("nDevice::WriteActuator(" << mActuators.SymbolicName(actuator) << ")"); 00388 00389 // bail out (do notify clients even when servers incomplete) 00390 if(mState!=Up && mState!=StartUp) return; 00391 00392 // test event 00393 if(!mActuators.Exists(actuator)) { 00394 std::stringstream errstr; 00395 errstr << "Unknown actuator event " << actuator; 00396 throw Exception("nDevice::WriteActuator", errstr.str(), 65); 00397 } 00398 00399 // find properties 00400 const AttributeSimplenetActuator* aattr = pConfiguration->Attribute(actuator).Actuatorp(); 00401 if(!aattr) { 00402 std::stringstream errstr; 00403 errstr << "Invalid actuator attribute " << actuator; 00404 throw Exception("nDevice::WriteActuator", errstr.str(), 65); 00405 } 00406 00407 // report 00408 std::string message= "<Notify> \"" + mActuators.SymbolicName(actuator) + "\" </Notify>\n"; 00409 FD_DH("nDevice::WriteActuator(): message: " << message.substr(0,message.length()-1)); 00410 00411 // send event to those clients that did subscribe 00412 LOCK_E; 00413 std::map<int,ClientState>::iterator sit=mActuatorClientStates.begin(); 00414 for(;sit!=mActuatorClientStates.end();sit++) { 00415 if(!sit->second.mEvents.Empty()) 00416 if(!sit->second.mEvents.Exists(actuator)) 00417 continue; 00418 int clientsock=sit->second.mClientSocket; 00419 FD_DH("nDevice::WriteActuator(): to socket " << clientsock); 00420 syncSend(clientsock, message.c_str(), message.length(), 0); 00421 } 00422 UNLOCK_E; 00423 FD_DH("nDevice::WriteActuator(): done"); 00424 } 00425 00426 00427 00428 // Start(void) 00429 void nDevice::Start(void) { 00430 if(mState!=Down) return; 00431 FD_DH("nDevice(" << mName <<")::Start()"); 00432 // call base 00433 vDevice::Start(); 00434 mState=StartUp; 00435 // clear event server states 00436 mSensorServerStates.clear(); 00437 std::set<std::string>::iterator nit; 00438 for(nit=mNetworkNodes.begin(); nit!=mNetworkNodes.end();nit++) { 00439 if(*nit == mName) continue; 00440 mSensorServerStates[*nit].mAddress= SimplenetAddress("unknown:0"); 00441 mSensorServerStates[*nit].mEvents= EventSet(); 00442 mSensorServerStates[*nit].mServerSocket=-1; 00443 mSensorServerStates[*nit].mLineBuffer=""; 00444 } 00445 // set my effective address 00446 char hostname[1024]; 00447 int hostname_len =1023; 00448 if(gethostname(hostname,hostname_len)!=0) { 00449 std::stringstream errstr; 00450 errstr << "Simplenet fatal network error (cannot get hostname)"; 00451 throw Exception("nDevice::Start", errstr.str(), 553); 00452 } 00453 hostname[hostname_len]=0; 00454 mEffectiveAddress=mAddress; 00455 mEffectiveAddress.Ip(hostname); 00456 FD_DH("nDevice::Start(): server adress " << mEffectiveAddress.IpColonPort()); 00457 // open a tcp port to listen: create socket 00458 mServerSocket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); 00459 if(mServerSocket<=0) { 00460 std::stringstream errstr; 00461 errstr << "Simplenet fatal network error (cannot open server socket)"; 00462 throw Exception("nDevice::Start", errstr.str(), 553); 00463 } 00464 int reuse=1; 00465 setsockopt(mServerSocket,SOL_SOCKET, SO_REUSEADDR, WINCASTSTR &reuse, sizeof(reuse)); 00466 // open a tcp port to listen: set up address 00467 memset(&mServerAddress, 0, sizeof(mServerAddress)); 00468 mServerAddress.sin_family = AF_INET; 00469 mServerAddress.sin_addr.s_addr = htonl(INADDR_ANY); 00470 mServerAddress.sin_port = htons(mAddress.Port()); 00471 // open a tcp port to listen: bind socket to address 00472 if(bind(mServerSocket, (struct sockaddr *) &mServerAddress,sizeof(mServerAddress)) <0) { 00473 std::stringstream errstr; 00474 errstr << "Simplenet fatal network error (cannot bind socket)"; 00475 throw Exception("nDevice::Start", errstr.str(), 553); 00476 } 00477 // open a tcp port to listen: start to listen 00478 if(listen(mServerSocket, 77) < 0) { // todo: max pending connections 00479 std::stringstream errstr; 00480 errstr << "Simplenet fatal network error (cannot listen from socket)"; 00481 throw Exception("nDevice::Start", errstr.str(), 553); 00482 } 00483 // open a udp port to listen: create socket 00484 mBroadcastSocket = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP); 00485 if(mBroadcastSocket<=0) { 00486 std::stringstream errstr; 00487 errstr << "Simplenet fatal network error (cannot open broadcast socket)"; 00488 throw Exception("nDevice::Start", errstr.str(), 553); 00489 } 00490 //int reuse=1; 00491 setsockopt(mBroadcastSocket,SOL_SOCKET, SO_REUSEADDR, WINCASTSTR &reuse, sizeof(reuse)); 00492 setsockopt(mBroadcastSocket,SOL_SOCKET, SO_REUSEPORT, WINCASTSTR &reuse, sizeof(reuse)); 00493 // open a udp port: enable broadcast 00494 // int reuse 00495 if(setsockopt(mBroadcastSocket, SOL_SOCKET, SO_BROADCAST, (char *) &reuse, sizeof(reuse)) ) { 00496 std::stringstream errstr; 00497 errstr << "Simplenet fatal network error (cannot setopt broadcast socket)"; 00498 throw Exception("nDevice::Start", errstr.str(), 553); 00499 } 00500 // open a udp port to listen: set up address 00501 struct sockaddr_in broadcastaddr; 00502 memset(&broadcastaddr, 0, sizeof(broadcastaddr)); 00503 broadcastaddr.sin_family = AF_INET; 00504 broadcastaddr.sin_addr.s_addr = htonl(INADDR_ANY); 00505 broadcastaddr.sin_port = htons(FAUDES_IODEVICE_BROADCASTPORT); 00506 // open a udp port to listen: bind socket to address 00507 if(bind(mBroadcastSocket, (struct sockaddr *) &broadcastaddr,sizeof(broadcastaddr)) <0) { 00508 std::stringstream errstr; 00509 errstr << "Simplenet fatal network error (cannot bind broadcast socket)"; 00510 throw Exception("nDevice::Start", errstr.str(), 553); 00511 } 00512 // start background thread to listen: create thread 00513 pthread_attr_t attr; 00514 pthread_attr_init(&attr); 00515 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); 00516 // start background threadto listen: run thread 00517 mStopListen=false; 00518 int rc = pthread_create(&mThreadListen, &attr, NDeviceListen, this); 00519 // start background thread to listen: dont need the attribute anymore 00520 pthread_attr_destroy(&attr); 00521 // pthread error 00522 if(rc) { 00523 std::stringstream errstr; 00524 errstr << "Simplenet fatal pthread error (cannot create thread)"; 00525 throw Exception("nDevice::Start", errstr.str(), 554); 00526 } 00527 } 00528 00529 // Stop(void) 00530 void nDevice::Stop(void) { 00531 // bail out 00532 if(mState!=Up && mState!=StartUp) return; 00533 FD_DH("nDevice::Stop()"); 00534 // stop background threads 00535 LOCK_E; 00536 mStopListen=true; 00537 UNLOCK_E; 00538 // signal update to my threads: via udp message ... release select 00539 std::string message= "<Stop> \"" + mNetwork + "\" \"" + mName + "\" </Stop>\n"; 00540 struct sockaddr_in broadcastaddr; 00541 broadcastaddr.sin_family=AF_INET; 00542 broadcastaddr.sin_port=htons(FAUDES_IODEVICE_BROADCASTPORT); 00543 broadcastaddr.sin_addr.s_addr=htonl(INADDR_BROADCAST); 00544 LOCK_E; 00545 sendto(mBroadcastSocket,message.c_str(),message.length(),0,(struct sockaddr *) & broadcastaddr, sizeof(broadcastaddr)); 00546 UNLOCK_E; 00547 // wait until listen thread finished ... implies all other threads finished too 00548 FD_DH("nDevice::Stop(): waiting for listen thread"); 00549 pthread_join(mThreadListen, NULL); 00550 FD_DH("nDevice::Stop(): listen thread finished"); 00551 // close server socket 00552 shutdown(mServerSocket,2); 00553 close(mServerSocket); 00554 mServerSocket=-1; 00555 // close broadcast socket 00556 shutdown(mBroadcastSocket,2); 00557 close(mBroadcastSocket); 00558 mBroadcastSocket=-1; 00559 // call base (implies reset) 00560 vDevice::Stop(); 00561 } 00562 00563 00564 00565 // background thread, listening on my port for clients to connect 00566 void* NDeviceListen(void* arg){ 00567 bool term; 00568 std::map<std::string,nDevice::ServerState>::iterator sit; 00569 std::map<int,nDevice::ClientState>::iterator cit; 00570 // cast this object 00571 nDevice* ndevice= static_cast<nDevice*>(arg); 00572 // say hello 00573 FD_DH("nDevice::Listen(" << ndevice << ")"); 00574 // clear broadcast time stamp 00575 timeval lastbroadcast; 00576 lastbroadcast.tv_sec=0; 00577 lastbroadcast.tv_usec=0; 00578 00579 // infinite loop 00580 while(true){ 00581 00582 // report missing servers 00583 int missing=0; 00584 for(sit=ndevice->mSensorServerStates.begin(); sit!=ndevice->mSensorServerStates.end(); sit++) { 00585 if(sit->second.mServerSocket>0) continue; 00586 FD_DH("nDevice::Listen(): missing server for node " << sit->first); 00587 missing++; 00588 } 00589 if(missing>0 && ndevice->mState==vDevice::Up) { 00590 TLOCK_E; 00591 ndevice->mState=vDevice::StartUp; 00592 TUNLOCK_E; 00593 } 00594 if(missing==0 && ndevice->mState==vDevice::StartUp) { 00595 TLOCK_E; 00596 ndevice->mState=vDevice::Up; 00597 TUNLOCK_E; 00598 } 00599 if(missing>0 && ndevice->mState==vDevice::StartUp) { 00600 // is a broadcast due? 00601 timeval now; 00602 gettimeofday(&now,0); 00603 if(now.tv_sec - lastbroadcast.tv_sec >5) { 00604 // udp message 00605 std::string message= "<Request> \"" + ndevice->mNetwork + "\" </Request>\n"; 00606 // udp broadcast 00607 struct sockaddr_in broadcastaddr; 00608 broadcastaddr.sin_family=AF_INET; 00609 broadcastaddr.sin_port=htons(FAUDES_IODEVICE_BROADCASTPORT); 00610 broadcastaddr.sin_addr.s_addr=htonl(INADDR_BROADCAST); 00611 TLOCK_E; 00612 int rc=sendto(ndevice->mBroadcastSocket,message.c_str(),message.length(),0,(struct sockaddr *) & broadcastaddr, sizeof(broadcastaddr)); 00613 (void) rc; 00614 FD_DH("nDevice::Listen(): broadcast message: " << message.substr(0,message.length()-1) << " #" << rc); 00615 TUNLOCK_E; 00616 gettimeofday(&lastbroadcast,0); 00617 } 00618 } 00619 00620 // initiate/maintane subscriptions 00621 for(sit=ndevice->mSensorServerStates.begin(); sit!=ndevice->mSensorServerStates.end(); sit++) { 00622 // have active connection? 00623 if(sit->second.mServerSocket>0) continue; 00624 // have an address? 00625 if(!sit->second.mAddress.Valid()) continue; 00626 // try to connect 00627 FD_DH("nDevice::Listen(): subscribing to " << sit->first << 00628 " at " << sit->second.mAddress.IpColonPort()); 00629 // open a tcp port: create socket 00630 int serversock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); 00631 if(serversock<=0) { 00632 FD_DH("nDevice::Listen(): subscription failed: no socket"); 00633 continue; 00634 } 00635 // open a tcp port: set up internet address 00636 unsigned long int serverinaddr = INADDR_NONE; 00637 if(serverinaddr==INADDR_NONE) { 00638 FD_DH("nDevice::Listen(): using address in dot format"); 00639 serverinaddr = inet_addr(sit->second.mAddress.Ip().c_str()); 00640 } 00641 if(serverinaddr==INADDR_NONE) { 00642 struct hostent *host; 00643 host = gethostbyname(sit->second.mAddress.Ip().c_str()); 00644 if(host!=0) { 00645 FD_DH("nDevice::Listen(): unsing address by name lookup"); 00646 serverinaddr = *(unsigned long int*) host->h_addr; 00647 } 00648 } 00649 if(serverinaddr==INADDR_NONE) { 00650 FD_DH("nDevice::Listen(): subscription failed: invalid address " << sit->second.mAddress.Ip()); 00651 close(serversock); 00652 continue; 00653 } 00654 // open a tcp port: set up socket address 00655 struct sockaddr_in serveraddress; 00656 memset(&serveraddress, 0, sizeof(serveraddress)); 00657 serveraddress.sin_family = AF_INET; 00658 serveraddress.sin_addr.s_addr=serverinaddr; 00659 serveraddress.sin_port = htons(sit->second.mAddress.Port()); 00660 // open a tcp port: connect 00661 if(connect(serversock, (struct sockaddr*) &serveraddress, sizeof(serveraddress))<0) { 00662 FD_DH("nDevice::Listen(): subscription failed: connect"); 00663 close(serversock); 00664 continue; 00665 } 00666 // record success, say hello to remote sensor server, ask for info 00667 FD_DH("nDevice::Listen(): subscribing to " << sit->first << " via socket " << serversock); 00668 sit->second.mServerSocket=serversock; 00669 std::string hello; 00670 hello="% Simplenet universal event subscription: \""+ndevice->mName+"\" subscribing from \""+sit->first+"\"\n"; 00671 syncSend(serversock, hello.c_str(), hello.length(), 0); 00672 hello="% Expecting notifications in format '<Notify> \"event_name\" </Notify>'\n"; 00673 syncSend(serversock, hello.c_str(), hello.length(), 0); 00674 hello="% Sending info command, explicit subscription may follow\n"; 00675 syncSend(serversock, hello.c_str(), hello.length(), 0); 00676 hello="<Cmd> \"Info\" </Cmd>\n"; 00677 syncSend(serversock, hello.c_str(), hello.length(), 0); 00678 FD_DH("nDevice::Listen(): subscribing to " << sit->first << " via socket " << serversock << ": ok"); 00679 } 00680 00681 // prepare relevant on sources ... 00682 fd_set mysocks; 00683 int mysocks_max=0; 00684 FD_ZERO(&mysocks); 00685 // ... my server listen socket , expecting other nodes to subscribe 00686 FD_SET(ndevice->mServerSocket, &mysocks); 00687 if(mysocks_max<ndevice->mServerSocket) mysocks_max=ndevice->mServerSocket; 00688 // ... udp port, expecting requests and adverts 00689 FD_SET(ndevice->mBroadcastSocket, &mysocks); 00690 if(mysocks_max< ndevice->mBroadcastSocket) mysocks_max=ndevice->mBroadcastSocket; 00691 // ... sensor server connections, expecting notifications 00692 for(sit=ndevice->mSensorServerStates.begin(); sit!=ndevice->mSensorServerStates.end(); sit++) { 00693 int serversock=sit->second.mServerSocket; 00694 if(serversock<0) continue; 00695 FD_SET(serversock, &mysocks); 00696 if(mysocks_max< serversock) mysocks_max=serversock; 00697 } 00698 00699 // wait for traffic with moderate timeout 00700 struct timeval tv; 00701 tv.tv_sec = 10; 00702 tv.tv_usec = 0; 00703 FD_DH("nDevice::Listen(): listen as node \"" << ndevice->mName << "\" on network \"" << ndevice->mNetwork << "\""); 00704 int avail=select(mysocks_max+1, &mysocks, NULL, NULL, &tv); 00705 00706 // handle request for subscription 00707 if(avail>0) if(FD_ISSET(ndevice->mServerSocket,&mysocks)) { 00708 int clientsock=-1; 00709 struct sockaddr_in clientaddr; 00710 socklen_t clientaddr_len = sizeof(clientaddr); 00711 clientsock=accept(ndevice->mServerSocket, (struct sockaddr *) &clientaddr, &clientaddr_len ); 00712 if(clientsock<0) { 00713 FD_DH("nDevice::Listen(): failed to accept incomming connection"); 00714 break; 00715 } 00716 FD_DH("nDevice::Listen(): connection request from " << inet_ntoa(clientaddr.sin_addr)); 00717 // lock for client data base 00718 TLOCK_E; 00719 // record client 00720 nDevice::ClientState* cstate = &ndevice->mActuatorClientStates[clientsock]; 00721 cstate->mDevice=ndevice; 00722 cstate->mClientSocket=clientsock; 00723 // start server thread for new client 00724 pthread_attr_t attr; 00725 pthread_attr_init(&attr); 00726 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 00727 pthread_t clientthread; 00728 int rc = pthread_create(&clientthread, &attr, NDeviceReply,cstate); 00729 pthread_attr_destroy(&attr); 00730 cstate->mThread=clientthread; 00731 // unlock for client data base 00732 TUNLOCK_E; 00733 // pthread error 00734 if(rc) { 00735 std::stringstream errstr; 00736 errstr << "Simplenet fatal pthread error (cannot create thread)"; 00737 throw Exception("nDevice::Listen()", errstr.str(), 554); 00738 } 00739 } 00740 00741 // handle incomming broadcast 00742 if(avail>0) 00743 if(FD_ISSET(ndevice->mBroadcastSocket,&mysocks)) { 00744 // get message 00745 char data[1024]; 00746 int data_len=1023; 00747 struct sockaddr_in fromaddr; 00748 socklen_t fromaddr_len = sizeof(fromaddr); 00749 data_len=recvfrom(ndevice->mBroadcastSocket,data,data_len,0, (struct sockaddr*) &fromaddr,&fromaddr_len); 00750 if(data_len<0) data_len=0; // todo: eof 00751 data[data_len]=0; 00752 if(data_len>=1) if(data[data_len-1]=='\n') data[data_len-1]=0; 00753 FD_DH("nDevice::Listen(): received udp datagram " << data << 00754 " from " << inet_ntoa(fromaddr.sin_addr)); 00755 // interpret message 00756 TokenReader tr(TokenReader::String,std::string(data)); 00757 try { 00758 Token token; 00759 tr.Peek(token); 00760 // interpret udp request ... 00761 if(token.Type()==Token::Begin && token.StringValue()=="Request") { 00762 tr.ReadBegin("Request"); 00763 if(tr.ReadString()==ndevice->mNetwork) { 00764 // set up advert 00765 std::string message= "<Advert> \"" 00766 + ndevice->mNetwork + "\" \"" 00767 + ndevice->mName + "\"" + 00768 " \"" + ndevice->mEffectiveAddress.IpColonPort() +"\"" + 00769 " </Advert>\n"; 00770 FD_DH("nDevice::Listen(): reply advert: " << message.substr(0,message.length()-1)); 00771 // udp broadcast 00772 struct sockaddr_in broadcastaddr; 00773 broadcastaddr.sin_family=AF_INET; 00774 broadcastaddr.sin_port=htons(FAUDES_IODEVICE_BROADCASTPORT); 00775 broadcastaddr.sin_addr.s_addr=htonl(INADDR_BROADCAST); 00776 TLOCK_E; 00777 sendto(ndevice->mBroadcastSocket,message.c_str(),message.length(),0,(struct sockaddr *) & broadcastaddr, sizeof(broadcastaddr)); 00778 TUNLOCK_E 00779 } else { 00780 FD_DH("nDevice::Listen(): ingoring request from other network"); 00781 } 00782 } 00783 // interpret udp advert ... 00784 if(token.Type()==Token::Begin && token.StringValue()=="Advert") { 00785 tr.ReadBegin("Advert"); 00786 if(tr.ReadString()==ndevice->mNetwork) { 00787 std::string node = tr.ReadString(); 00788 std::string saddr = tr.ReadString(); 00789 SimplenetAddress addr(saddr); 00790 addr.Ip(inet_ntoa(fromaddr.sin_addr)); // overwrite with actual ip 00791 FD_DH("nDevice::Listen(): accepting advert from my network"); 00792 ndevice->InsertNodeAddress(node,addr); 00793 } else { 00794 FD_DH("nDevice::Listen(): ingoring advert from other network"); 00795 } 00796 } 00797 } catch (faudes::Exception&) { 00798 FD_DH("nDevice::Listen(): invalid udp message"); 00799 } 00800 } 00801 00802 00803 // handle event notification and other commands from remote sensor servers 00804 if(avail>0) 00805 if(!FD_ISSET(ndevice->mServerSocket,&mysocks)) 00806 if(!FD_ISSET(ndevice->mBroadcastSocket,&mysocks)) { 00807 for(sit=ndevice->mSensorServerStates.begin(); sit!=ndevice->mSensorServerStates.end(); sit++) { 00808 int serversock=sit->second.mServerSocket; 00809 if(serversock<0) continue; 00810 if(FD_ISSET(serversock, &mysocks)) { 00811 FD_DH("nDevice::Listen(): reading sock " << serversock); 00812 // buffer data in line buffer 00813 char buffer[1025]; 00814 int count = recv(serversock, buffer, 1024, 0); 00815 if(count<=0) { // todo: test eof 00816 FD_DH("nDevice::Listen(): reading sock " << serversock << " : eof"); 00817 close(serversock); 00818 sit->second.mServerSocket=-1; 00819 continue; 00820 } 00821 FD_DH("nDevice::Listen(): reading sock " << serversock << ": #" << count); 00822 buffer[count]=0; 00823 sit->second.mLineBuffer +=std::string(buffer); 00824 // interpret line(s) 00825 if(count>0) 00826 if(buffer[count-1]=='\n') 00827 if(sit->second.mLineBuffer.length()>0) 00828 { 00829 const std::string& linebuffer = sit->second.mLineBuffer; 00830 FD_DH("nDevice::Listen(): " << serversock << ": line: " << linebuffer); 00831 // tokenise notification 00832 TokenReader tr(TokenReader::String,linebuffer); 00833 int ncount=0; 00834 try { 00835 Token token; 00836 while(tr.Peek(token)) { 00837 // its an event notify 00838 if(token.Type()==Token::Begin && token.StringValue()=="Notify") { 00839 tr.ReadBegin("Notify"); 00840 std::string event = tr.ReadString(); 00841 tr.ReadEnd("Notify"); 00842 pthread_mutex_lock(ndevice->pBufferMutex); 00843 FD_DH("nDevice::Listen(): found event " << event); 00844 Idx sev=ndevice->mSensors.Index(event); 00845 if(sev) ndevice->pSensorBuffer->push_back(sev); 00846 pthread_mutex_unlock(ndevice->pBufferMutex); 00847 ncount++; 00848 continue; 00849 } 00850 // its an info 00851 if(token.Type()==Token::Begin && token.StringValue()=="SimplenetDevice") { 00852 FD_DH("nDevice::Listen(): found device info"); 00853 nDevice remote; 00854 remote.Read(tr); 00855 FD_DH("nDevice::Listen(): found device with actuators " << remote.Actuators().ToString()); 00856 EventSet sevents=ndevice->Sensors(); 00857 sevents.SetIntersection(remote.Actuators()); 00858 sevents.Name("Subscribe"); 00859 std::string message=sevents.ToString(); 00860 FD_DH("nDevice::Listen(): subscribing events " << message); 00861 message += "\n"; 00862 syncSend(serversock,message.c_str(), message.length(),0); 00863 continue; 00864 } 00865 // skip other sections 00866 if(token.Type()==Token::Begin) { 00867 FD_DH("nDevice::Listen(): ignore section " << token.StringValue()); 00868 std::string section=token.StringValue(); 00869 tr.ReadBegin(section); 00870 while(!tr.Eos(section)) tr.Get(token); 00871 tr.ReadEnd(section); 00872 continue; 00873 } 00874 // ignore token 00875 FD_DH("nDevice::Listen(): error: ignore token"); 00876 tr.Get(token); 00877 } 00878 } catch (faudes::Exception&) { 00879 FD_DH("nDevice::Listen(): " << serversock << ": invalid notification"); 00880 } 00881 sit->second.mLineBuffer.clear(); 00882 // signal condition 00883 if(ncount>0) { 00884 FD_DH("nDevice::Listen(): broadcast condition"); 00885 pthread_mutex_lock(ndevice->pWaitMutex); 00886 pthread_cond_broadcast(ndevice->pWaitCondition); 00887 pthread_mutex_unlock(ndevice->pWaitMutex); 00888 ncount=0; 00889 } 00890 } 00891 } 00892 } 00893 } 00894 00895 // some error 00896 if(avail<0) { 00897 FD_DH("nDevice::Listen(): select error"); 00898 } 00899 00900 // terminate thread on request 00901 TLOCK_E; 00902 term= ndevice->mStopListen; 00903 TUNLOCK_E; 00904 if(term) break; 00905 } 00906 00907 // enforce reply threads to terminate 00908 FD_DH("nDevice::Listen(): cancel reply threads"); 00909 TLOCK_E; 00910 for(cit=ndevice->mActuatorClientStates.begin(); cit!=ndevice->mActuatorClientStates.end(); cit++) { 00911 pthread_cancel(cit->second.mThread); 00912 } 00913 TUNLOCK_E; 00914 FD_DH("nDevice::Listen(): close reply sockts"); 00915 TLOCK_E; 00916 for(cit=ndevice->mActuatorClientStates.begin(); cit!=ndevice->mActuatorClientStates.end(); cit++) { 00917 int clientsock= cit->second.mClientSocket; 00918 if(clientsock>0) close(clientsock); 00919 cit->second.mClientSocket=-1; 00920 } 00921 TUNLOCK_E; 00922 FD_DH("nDevice::Listen(): discard client data"); 00923 TLOCK_E; 00924 ndevice->mActuatorClientStates.clear(); 00925 TUNLOCK_E; 00926 // done 00927 FD_DH("nDevice::Listen(): terminating listen thread"); 00928 for(sit=ndevice->mSensorServerStates.begin(); sit!=ndevice->mSensorServerStates.end(); sit++) { 00929 int serversock=sit->second.mServerSocket; 00930 if(serversock>0) close(serversock); 00931 sit->second.mServerSocket=-1; 00932 } 00933 pthread_exit(NULL); 00934 return NULL; 00935 } 00936 00937 00938 00939 00940 00941 // background thread, reply on client request 00942 void* NDeviceReply(void* arg) { 00943 bool term=false; 00944 // cast my state 00945 nDevice::ClientState* cstate= static_cast<nDevice::ClientState*>(arg); 00946 nDevice* ndevice = cstate->mDevice; 00947 // get my socket 00948 TLOCK_E; 00949 int clientsock = cstate->mClientSocket; 00950 TUNLOCK_E; 00951 FD_DH("nDevice::Reply(" << clientsock << "): start"); 00952 // say hello 00953 std::string hello; 00954 hello="% Simplenet Event Server: \""+ndevice->mName+"\" providing events\n"; 00955 send(clientsock, hello.c_str(), hello.length(), 0); 00956 hello="% Notifications will have format '<Notify> \"event_name\" </Notify>'\n"; 00957 syncSend(clientsock, hello.c_str(), hello.length(), 0); 00958 hello="% Commands are accepted in format '<Cmd> \"cmd_name\" </Cmd>'\n"; 00959 syncSend(clientsock, hello.c_str(), hello.length(), 0); 00960 hello="% Supported commands are \"Info\" and \"Status\"\n"; 00961 syncSend(clientsock, hello.c_str(), hello.length(), 0); 00962 // have a linebuffer 00963 std::string linebuffer; 00964 // loop forever 00965 while(true) { 00966 FD_DH("nDevice::Reply(" << clientsock << "): waiting"); 00967 // allow for cancel 00968 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE,NULL); 00969 // select my socket with moderate time out 00970 fd_set mysock; 00971 FD_ZERO(&mysock); 00972 FD_SET(clientsock, &mysock); 00973 struct timeval tv; 00974 tv.tv_sec = 100; 00975 tv.tv_usec = 0; 00976 pthread_testcancel(); // fix LinuxThread were select is no cancelation point 00977 int avail=select(clientsock+1, &mysock, NULL, NULL, &tv); 00978 pthread_testcancel(); 00979 // dont cancle 00980 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE,NULL); 00981 // read data to buffer 00982 FD_DH("nDevice::Reply(" << clientsock << "): release"); 00983 if(avail>0) { 00984 char buffer[1025]; 00985 int count = recv(clientsock, buffer, 1024, 0); 00986 if(count<=0) { // todo: test eof 00987 FD_DH("nDevice::Reply(" << clientsock << "): eof"); 00988 term=true; 00989 break; 00990 } 00991 FD_DH("nDevice::Reply(" << clientsock << "): count: " << count); 00992 buffer[count]=0; 00993 linebuffer +=std::string(buffer); 00994 avail=0; 00995 // pass on complete lines for interpretation 00996 if(count>0) if(buffer[count-1]=='\n') avail=1; 00997 } 00998 // evaluate linebuffer 00999 int ncount=0; 01000 if(avail>0) { 01001 FD_DH("nDevice::Reply(" << clientsock << "): line: " << linebuffer); 01002 // tokenise command 01003 TokenReader tr(TokenReader::String,linebuffer); 01004 try { 01005 Token token; 01006 while(tr.Peek(token)) { 01007 // its a command 01008 if(token.Type()==Token::Begin && token.StringValue()=="Cmd") { 01009 tr.ReadBegin("Cmd"); 01010 std::string cmd = tr.ReadString(); 01011 tr.ReadEnd("Cmd"); 01012 std::string response="<NAck> </NAck>\n"; 01013 FD_DH("nDevice::Reply(" << clientsock << "): received cmd " << cmd); 01014 // command: info 01015 if(cmd=="Info") { 01016 TLOCK_E; 01017 response=ndevice->ToString() + "\n"; 01018 TUNLOCK_E; 01019 } 01020 // command: status 01021 if(cmd=="Status") { 01022 TLOCK_E; 01023 if(ndevice->mState==vDevice::Up) response="<Ack> \"Up\" </Ack>\n"; 01024 if(ndevice->mState==vDevice::StartUp) response="<Ack> \"StartUp\" </Ack>\n"; 01025 if(ndevice->mState==vDevice::ShutDown) response="<Ack> \"ShutDown\" </Ack>\n"; 01026 TUNLOCK_E; 01027 } 01028 // its a reset request 01029 if(cmd=="ResetRequest") { 01030 FD_DH("nDevice::Reply(" << clientsock << "): reset request"); 01031 pthread_mutex_lock(ndevice->pBufferMutex); 01032 if(!ndevice->mResetRequest) ncount++; 01033 ndevice->mResetRequest=true; 01034 pthread_mutex_unlock(ndevice->pBufferMutex); 01035 response="<Ack> </Ack>\n"; 01036 } 01037 // send reply 01038 syncSend(clientsock, response.c_str(), response.length(), 0); 01039 } 01040 // its a event subscription 01041 if(token.Type()==Token::Begin && token.StringValue()=="Subscribe") { 01042 EventSet sevents; 01043 sevents.Read(tr,"Subscribe"); 01044 FD_DH("nDevice::Reply(" << clientsock << "): providing events " << sevents.ToString()); 01045 TLOCK_E; 01046 cstate->mEvents.InsertSet(sevents); 01047 TUNLOCK_E; 01048 } 01049 } 01050 } catch (faudes::Exception&) { 01051 FD_DH("nDevice::Reply(" << clientsock << "): invalid cmd"); 01052 } 01053 // done 01054 linebuffer=""; 01055 // tell waiting processes 01056 if(ncount>0) { 01057 FD_DH("nDevice::Reply(" << clientsock << "): broadcast condition"); 01058 pthread_mutex_lock(ndevice->pWaitMutex); 01059 pthread_cond_broadcast(ndevice->pWaitCondition); 01060 pthread_mutex_unlock(ndevice->pWaitMutex); 01061 ncount=0; 01062 } 01063 } 01064 // lost connection / socket closed 01065 if(avail<0) { 01066 FD_DH("nDevice::Reply(" << clientsock << "): socket closed"); 01067 break; 01068 } 01069 } // loop 01070 // remove client state 01071 TLOCK_E; 01072 if(cstate->mClientSocket>0) close(clientsock); 01073 cstate->mClientSocket=-1; 01074 ndevice->mActuatorClientStates.erase(clientsock); 01075 TUNLOCK_E; 01076 // done 01077 FD_DH("nDevice::Reply(" << clientsock << "): terminate"); 01078 pthread_exit(NULL); 01079 return NULL; 01080 } 01081 01082 // reset dynamic faudes state (buffered events, current time) 01083 void nDevice::Reset(void) { 01084 // call base for time and sensor buffer 01085 vDevice::Reset(); 01086 // bail out (do notify clients even when servers incomplete) 01087 if(mState!=Up && mState!=StartUp) return; 01088 // report 01089 std::string message= "<Cmd> \"ResetRequest\" </Cmd>\n"; 01090 FD_DH("nDevice::Reset(): message: " << message.substr(0,message.length()-1)); 01091 // send cmd to all my servers 01092 LOCK_E; 01093 std::map<std::string,ServerState>::iterator sit=mSensorServerStates.begin(); 01094 for(; sit!=mSensorServerStates.end(); sit++) { 01095 int serversock=sit->second.mServerSocket; 01096 if(serversock<0) continue; 01097 FD_DH("nDevice::Reset(): to socket " << serversock); 01098 syncSend(serversock, message.c_str(), message.length(), 0); 01099 } 01100 UNLOCK_E; 01101 } 01102 01103 01104 01105 01106 01107 01108 } // name space 01109 01110 01111 |
libFAUDES 2.16b --- 2010-9-8 --- c++ source docu by doxygen 1.6.3