bool Port::open(const Contact& contact, bool registerName, const char *fakeName) { Contact contact2 = contact; if (!NetworkBase::initialized()) { YARP_ERROR(Logger::get(), "YARP not initialized; create a yarp::os::Network object before using ports"); return false; } std::string n = contact2.getName(); NameConfig conf; std::string nenv = std::string("YARP_RENAME") + conf.getSafeString(n); std::string rename = NetworkBase::getEnvironment(nenv.c_str()); if (rename!="") { n = rename; contact2.setName(n); } bool local = false; if (n == "" && contact2.getPort()<=0) { local = true; registerName = false; n = "..."; } NestedContact nc(n); if (nc.getNestedName()!="") { if (nc.getNodeName() == "") { Nodes& nodes = NameClient::getNameClient().getNodes(); nodes.requireActiveName(); std::string node_name = nodes.getActiveName(); if (node_name!="") { n = n + node_name; } } } PortCoreAdapter *currentCore = &(IMPL()); if (currentCore!=nullptr) { currentCore->active = false; if (n!="" && (n[0]!='/'||currentCore->includeNode) && n[0]!='=' && n!="..." && n.substr(0, 3)!="...") { if (fakeName==nullptr) { Nodes& nodes = NameClient::getNameClient().getNodes(); std::string node_name = nodes.getActiveName(); if (node_name!="") { n = (n[0]=='/'?"":"/") + n + "@" + node_name; } } } } if (n!="" && n[0]!='/' && n[0]!='=' && n!="..." && n.substr(0, 3)!="...") { if (fakeName==nullptr) { YARP_SPRINTF1(Logger::get(), error, "Port name '%s' needs to start with a '/' character", n.c_str()); return false; } } if (n!="" && n!="..." && n[0]!='=' && n.substr(0, 3)!="...") { if (fakeName==nullptr) { std::string prefix = NetworkBase::getEnvironment("YARP_PORT_PREFIX"); if (prefix!="") { n = prefix + n; contact2.setName(n); } } } if (currentCore!=nullptr) { NestedContact nc; nc.fromString(n); if (nc.getNestedName()!="") { if (nc.getCategory()=="") { // we need to add in a category std::string cat; if (currentCore->commitToRead) { cat = "-"; } else if (currentCore->commitToWrite) { cat = "+"; } if (cat!="") { if (currentCore->commitToRpc) { cat += "1"; } contact2.setName(nc.getNestedName() + cat + "@" + nc.getNodeName()); } else { YARP_SPRINTF1(Logger::get(), error, "Error: Port '%s' is not committed to being either an input or output port.", n.c_str()); YARP_SPRINTF0(Logger::get(), error, "YARP does not mind, but we are trying to register with a name server that does."); YARP_SPRINTF0(Logger::get(), error, "You can call Port::setWriteOnly() or Port::setReadOnly(), OR rename the port."); NestedContact nc2 = nc; nc2.setCategoryWrite(); YARP_SPRINTF1(Logger::get(), error, "For an output port, call it: %s (+ adds data)", nc2.toString().c_str()); nc2.setCategoryRead(); YARP_SPRINTF1(Logger::get(), error, "For an input port, call it: %s (- takes data)", nc2.toString().c_str()); return false; } } } } // Allow for open() to be called safely many times on the same Port if (currentCore && currentCore->isOpened()) { auto* newCore = new PortCoreAdapter(*this); yAssert(newCore != nullptr); // copy state that should survive in a new open() if (currentCore->checkPortReader() != nullptr) { newCore->configReader(*(currentCore->checkPortReader())); } if (currentCore->checkAdminPortReader() != nullptr) { newCore->configAdminReader(*(currentCore->checkAdminPortReader())); } if (currentCore->checkReadCreator() != nullptr) { newCore->configReadCreator(*(currentCore->checkReadCreator())); } if (currentCore->checkWaitAfterSend() >= 0) { newCore->configWaitAfterSend(currentCore->checkWaitAfterSend()); } if (currentCore->haveCallbackLock) { newCore->configCallbackLock(currentCore->recCallbackLock); } close(); if (owned) delete ((PortCoreAdapter*)implementation); implementation = newCore; owned = true; currentCore = newCore; currentCore->active = false; } PortCoreAdapter& core = IMPL(); core.openable(); if (NetworkBase::localNetworkAllocation()&&contact2.getPort()<=0) { YARP_DEBUG(Logger::get(), "local network allocation needed"); local = true; } bool success = true; Contact address(contact2.getName(), contact2.getCarrier(), contact2.getHost(), contact2.getPort()); address.setNestedContact(contact2.getNested()); core.setReadHandler(core); if (contact2.getPort()>0 && contact2.getHost()!="") { registerName = false; } std::string ntyp = getType().getNameOnWire(); if (ntyp=="") { NestedContact nc; nc.fromString(n); if (nc.getTypeName()!="") ntyp = nc.getTypeName(); } if (ntyp=="") { ntyp = getType().getName(); } if (ntyp!="") { NestedContact nc; nc.fromString(contact2.getName()); nc.setTypeName(ntyp); contact2.setNestedContact(nc); if (getType().getNameOnWire()!=ntyp) { core.promiseType(Type::byNameOnWire(ntyp.c_str())); } } if (registerName&&!local) { address = NetworkBase::registerContact(contact2); } core.setControlRegistration(registerName); success = (address.isValid()||local)&&(fakeName==nullptr); if (success) { // create a node if needed Nodes& nodes = NameClient::getNameClient().getNodes(); nodes.prepare(address.getRegName()); } // If we are a service client, go ahead and connect if (success) { NestedContact nc; nc.fromString(address.getName()); if (nc.getNestedName()!="") { if (nc.getCategory() == "+1") { addOutput(nc.getNestedName()); } } } std::string blame = "invalid address"; if (success) { success = core.listen(address, registerName); blame = "address conflict"; if (success) { success = core.start(); blame = "manager did not start"; } } if (success) { address = core.getAddress(); if (registerName&&local) { contact2.setSocket(address.getCarrier(), address.getHost(), address.getPort()); contact2.setName(address.getRegName()); Contact newName = NetworkBase::registerContact(contact2); core.resetPortName(newName.getName()); address = core.getAddress(); } else if (core.getAddress().getRegName()=="" && !registerName) { core.resetPortName(core.getAddress().toURI(false)); core.setName(core.getAddress().getRegName()); } if (core.getVerbosity()>=1) { if (address.getRegName()=="") { YARP_INFO(Logger::get(), std::string("Anonymous port active at ") + address.toURI()); } else { YARP_INFO(Logger::get(), std::string("Port ") + address.getRegName() + " active at " + address.toURI()); } } } if (fakeName!=nullptr) { success = core.manualStart(fakeName); blame = "unmanaged port failed to start"; } if (!success) { YARP_ERROR(Logger::get(), std::string("Port ") + (address.isValid()?(address.getRegName().c_str()):(contact2.getName().c_str())) + " failed to activate" + (address.isValid()?" at ":"") + (address.isValid()?address.toURI():std::string("")) + " (" + blame + ")"); } if (success) { // create a node if needed Nodes& nodes = NameClient::getNameClient().getNodes(); nodes.add(*this); } if (success && currentCore!=nullptr) currentCore->active = true; return success; }