void PortCoreOutputUnit::runSimulation() { if (op!=NULL) { Route route = op->getRoute(); setMode(); getOwner().reportUnit(this,true); String msg = String("Sending output from ") + route.getFromName() + " to " + route.getToName() + " using " + route.getCarrierName(); if (Name(route.getToName()).isRooted()) { if (Name(route.getFromName()).isRooted()) { YARP_INFO(Logger::get(),msg); } } // Report the new connection PortInfo info; info.message = msg.c_str(); info.tag = yarp::os::PortInfo::PORTINFO_CONNECTION; info.incoming = false; info.created = true; info.sourceName = route.getFromName().c_str(); info.targetName = route.getToName().c_str(); info.portName = info.sourceName; info.carrierName = route.getCarrierName().c_str(); getOwner().report(info); } // no thread component running = false; return; }
std::string Protocol::getSenderSpecifier() const { Route r = getRoute(); // We pull the sender name from the route. std::string from = r.getFromName(); // But we need to add any qualifiers looking in the carrier // name. Ideally, we wouldn't need to bundle that in with // the sender name, but we do it for now in the name of // backwards compatibility. std::string carrier = r.getCarrierName(); size_t start = carrier.find('+'); if (start != std::string::npos) { from += " ("; for (size_t i = start + 1; i < (size_t)carrier.length(); i++) { char ch = carrier[i]; if (ch == '+') { from += ") ("; } else if (ch == '.') { from += " "; } else { from += ch; } } from += ")"; } return from; }
bool Protocol::open(const Route& route) { setRoute(route); setCarrier(route.getCarrierName()); if (delegate==NULL) return false; // We are the initiator of the connection, so we // send a header (carrier-dependent). bool ok = sendHeader(); if (!ok) return false; // Expect a resonse to the header (carrier-dependent). return expectReplyToHeader(); }
void Protocol::setRoute(const Route& route) { Route r = route; // We reorganize the route to reduce variation in naming. // If there are qualifiers in the source port name, propagate // those qualifiers to the carrier. std::string from = r.getFromName(); std::string carrier = r.getCarrierName(); if (from.find(' ') != std::string::npos) { Bottle b(from); if (b.size() > 1) { r.setFromName(b.get(0).toString()); for (size_t i = 1; i < b.size(); i++) { Value& v = b.get(i); Bottle* lst = v.asList(); if (lst != nullptr) { carrier.append("+").append(lst->get(0).toString()).append(".").append(lst->get(1).toString()); } else { carrier.append("+").append(v.toString()); } } r.setCarrierName(carrier); } } // Record canonicalized route. this->route = r; // Check if we have a receiver modifier. if (!recv_delegate) { Bottle b(getSenderSpecifier()); if (b.check("recv")) { need_recv_delegate = true; } } // Check if we have a sender modifier. if (!send_delegate) { Bottle b(getSenderSpecifier()); if (b.check("send")) { need_send_delegate = true; } } }
void PortCoreInputUnit::run() { running = true; phase.post(); Route route; bool wasNoticed = false; bool posted = false; bool done = false; YARP_ASSERT(ip!=NULL); PortCommand cmd; if (autoHandshake) { bool ok = true; if (!reversed) { ip->open(getName().c_str()); } if (!ok) { YARP_DEBUG(Logger::get(),String("new input connection to ")+ getOwner().getName()+ " is broken"); done = true; } else { route = ip->getRoute(); // just before going official, tag any lurking inputs from // the same source as undesired if (Name(route.getFromName()).isRooted()) { YARP_SPRINTF3(Logger::get(), debug, "Port %s starting up, flushing routes %s->*->%s", getOwner().getName().c_str(), route.getFromName().c_str(), route.getToName().c_str()); getOwner().removeIO(Route(route.getFromName(), route.getToName(),"*"),true); } officialRoute = route; setMode(); getOwner().reportUnit(this,true); String msg = String("Receiving input from ") + route.getFromName() + " to " + route.getToName() + " using " + route.getCarrierName(); if (Name(route.getFromName()).isRooted()) { if (reversed||ip->getConnection().isPush()) { YARP_INFO(Logger::get(),msg); posted = true; } else { YARP_DEBUG(Logger::get(),msg); } } else { YARP_DEBUG(Logger::get(),msg); } // Report the new connection PortInfo info; info.message = msg.c_str(); info.tag = yarp::os::PortInfo::PORTINFO_CONNECTION; info.incoming = true; info.created = true; info.sourceName = route.getFromName().c_str(); info.targetName = route.getToName().c_str(); info.portName = info.targetName; info.carrierName = route.getCarrierName().c_str(); if (info.sourceName!="admin"&&info.sourceName!="null") { getOwner().report(info); wasNoticed = true; } } } else { bool ok = ip->open(""); // anonymous connection route = ip->getRoute(); if (!ok) { done = true; } } if (!reversed) { if (!ip->getConnection().isPush()) { /* IP=OP */ OutputProtocol *op = &(ip->getOutput()); Route r = op->getRoute(); // reverse route op->rename(Route().addFromName(r.getToName()).addToName(r.getFromName()).addCarrierName(r.getCarrierName())); getOwner().addOutput(op); ip = NULL; done = true; } } if (closing) { done = true; } void *id = (void *)this; while (!done) { ConnectionReader& br = ip->beginRead(); if (br.getReference()!=NULL) { //printf("HAVE A REFERENCE\n"); if (localReader!=NULL) { bool ok = localReader->read(br); if (!br.isActive()) { done = true; break; } if (!ok) continue; } else { PortManager& man = getOwner(); bool ok = man.readBlock(br,id,NULL); if (!br.isActive()) { done = true; break; } if (!ok) continue; } //printf("DONE WITH A REFERENCE\n"); if (ip!=NULL) { ip->endRead(); } continue; } if (autoHandshake&&(ip->getConnection().canEscape())) { bool ok = cmd.read(br); if (!br.isActive()) { done = true; break; } if (!ok) continue; } else { cmd = PortCommand('d',""); if (!ip->checkStreams()) { done = true; break; } } if (closing||isDoomed()) { done = true; break; } char key = cmd.getKey(); //ACE_OS::printf("Port command is [%c:%d/%s]\n", // (key>=32)?key:'?', key, cmd.getText().c_str()); PortManager& man = getOwner(); OutputStream *os = NULL; if (br.isTextMode()) { os = &(ip->getOutputStream()); } switch (key) { case '/': YARP_SPRINTF3(Logger::get(), debug, "Port command (%s): %s should add connection: %s", route.toString().c_str(), getOwner().getName().c_str(), cmd.getText().c_str()); man.addOutput(cmd.getText(),id,os); break; case '!': YARP_SPRINTF3(Logger::get(), debug, "Port command (%s): %s should remove output: %s", route.toString().c_str(), getOwner().getName().c_str(), cmd.getText().c_str()); man.removeOutput(cmd.getText().substr(1,String::npos),id,os); break; case '~': YARP_SPRINTF3(Logger::get(), debug, "Port command (%s): %s should remove input: %s", route.toString().c_str(), getOwner().getName().c_str(), cmd.getText().c_str()); man.removeInput(cmd.getText().substr(1,String::npos),id,os); break; case '*': man.describe(id,os); break; case 'D': case 'd': { bool suppressed = false; // this will be the new way to signal that // replies are not expected. if (key=='D') { ip->suppressReply(); } String env = cmd.getText(); if (env.length()>1) { if (!suppressed) { // This is the backwards-compatible // method for signalling replies are // not expected. To be used until // YARP 2.1.2 is a "long time ago". if (env[1]=='o') { ip->suppressReply(); } } if (env.length()>2) { //YARP_ERROR(Logger::get(), //"***** received an envelope! [%s]", env.c_str()); String env2 = env.substr(2,env.length()); man.setEnvelope(env2); ip->setEnvelope(env2); } } if (localReader) { localReader->read(br); if (!br.isActive()) { done = true; break; } } else { if (ip->getReceiver().acceptIncomingData(br)) { man.readBlock(ip->getReceiver().modifyIncomingData(br),id,os); } else { skipIncomingData(br); } if (!br.isActive()) { done = true; break; } } } break; case 'a': { man.adminBlock(br,id,os); } break; case 'r': /* In YARP implementation, OP=IP. (This information is used rarely, and when used is tagged with OP=IP keyword) If it were not true, memory alloc would need to reorganized here */ { OutputProtocol *op = &(ip->getOutput()); ip->endRead(); Route r = op->getRoute(); // reverse route op->rename(Route().addFromName(r.getToName()).addToName(r.getFromName()).addCarrierName(r.getCarrierName())); getOwner().addOutput(op); ip = NULL; done = true; } break; case 'q': done = true; break; case 'i': printf("Interrupt requested\n"); //ACE_OS::kill(0,2); // SIGINT //ACE_OS::kill(Logger::get().getPid(),2); // SIGINT ACE_OS::kill(Logger::get().getPid(),15); // SIGTERM break; case '?': case 'h': if (os!=NULL) { BufferedConnectionWriter bw(true); bw.appendLine("This is a YARP port. Here are the commands it responds to:"); bw.appendLine("* Gives a description of this port"); bw.appendLine("d Signals the beginning of input for the port's owner"); bw.appendLine("do The same as \"d\" except replies should be suppressed (\"data-only\")"); bw.appendLine("q Disconnects"); bw.appendLine("i Interrupt parent process (unix only)"); bw.appendLine("r Reverse connection type to be a reader"); bw.appendLine("/port Requests to send output to /port"); bw.appendLine("!/port Requests to stop sending output to /port"); bw.appendLine("~/port Requests to stop receiving input from /port"); bw.appendLine("a Signals the beginning of an administrative message"); bw.appendLine("? Gives this help"); bw.write(*os); } break; default: if (os!=NULL) { BufferedConnectionWriter bw(true); bw.appendLine("Port command not understood."); bw.appendLine("Type d to send data to the port's owner."); bw.appendLine("Type ? for help."); bw.write(*os); } break; } if (ip!=NULL) { ip->endRead(); } if (ip==NULL) { done = true; break; } if (closing||isDoomed()||(!ip->checkStreams())) { done = true; break; } } setDoomed(true); YARP_DEBUG(Logger::get(),"PortCoreInputUnit closing ip"); access.wait(); if (ip!=NULL) { ip->close(); } access.post(); YARP_DEBUG(Logger::get(),"PortCoreInputUnit closed ip"); if (autoHandshake) { String msg = String("Removing input from ") + route.getFromName() + " to " + route.getToName(); if (Name(route.getFromName()).isRooted()) { if (posted) { YARP_INFO(Logger::get(),msg); } } else { YARP_DEBUG(Logger::get(),"PortCoreInputUnit (unrooted) shutting down"); } getOwner().reportUnit(this,false); if (wasNoticed) { // Report the disappearing connection PortInfo info; info.message = msg.c_str(); info.tag = yarp::os::PortInfo::PORTINFO_CONNECTION; info.incoming = true; info.created = false; info.sourceName = route.getFromName().c_str(); info.targetName = route.getToName().c_str(); info.portName = info.targetName; info.carrierName = route.getCarrierName().c_str(); if (info.sourceName!="admin") { getOwner().report(info); } } } else { YARP_DEBUG(Logger::get(),"PortCoreInputUnit shutting down"); } if (localReader!=NULL) { delete localReader; localReader = NULL; } running = false; finished = true; // it would be nice to get my entry removed from the port immediately, // but it would be a bit dodgy to delete this object and join this // thread within and from themselves }
void PortCoreOutputUnit::closeBasic() { bool waitForOther = false; if (op!=NULL) { op->getConnection().prepareDisconnect(); Route route = op->getRoute(); if (op->getConnection().isConnectionless()|| op->getConnection().isBroadcast()) { YARP_SPRINTF1(Logger::get(), debug, "output for route %s asking other side to close by out-of-band means", route.toString().c_str()); Companion::disconnectInput(route.getToName().c_str(), route.getFromName().c_str(),true); } else { if (op->getConnection().canEscape()) { BufferedConnectionWriter buf(op->getConnection().isTextMode()); PortCommand pc('\0',String("q")); pc.write(buf); //printf("Asked for %s to close...\n", // op->getRoute().toString().c_str()); waitForOther = op->write(buf); } } String msg = String("Removing output from ") + route.getFromName() + " to " + route.getToName(); if (Name(route.getToName()).isRooted()) { if (Name(route.getFromName()).isRooted()) { YARP_INFO(Logger::get(), msg); } } getOwner().reportUnit(this,false); // Report the disappearing connection PortInfo info; info.message = msg.c_str(); info.tag = yarp::os::PortInfo::PORTINFO_CONNECTION; info.incoming = false; info.created = false; info.sourceName = route.getFromName().c_str(); info.targetName = route.getToName().c_str(); info.portName = info.sourceName; info.carrierName = route.getCarrierName().c_str(); getOwner().report(info); } if (op!=NULL) { if (waitForOther) { // quit is only acknowledged in certain conditions if (op->getConnection().isTextMode()&& op->getConnection().supportReply()) { InputStream& is = op->getInputStream(); ManagedBytes dummy(1); is.read(dummy.bytes()); } } op->close(); delete op; op = NULL; } }