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