bool RequestURI::process(const VirtualHost *vhost, Transport *transport, const string &sourceRoot, const string &pathTranslation, const char *url) { splitURL(url, m_originalURL, m_queryString); m_originalURL = StringUtil::UrlDecode(m_originalURL, false); m_rewritten = false; // Fast path for files that exist unless VirtualHost option StaticFastPath is false, in // which case rewrite rules are applied even if the original path points to an existing static file. String canon(Util::canonicalize(m_originalURL.c_str(), m_originalURL.size()), AttachString); if ( vhost->staticfastpath() ) { if (virtualFileExists(vhost, sourceRoot, pathTranslation, canon)) { m_rewrittenURL = canon; m_resolvedURL = canon; return true; } } if (!rewriteURL(vhost, transport, pathTranslation, sourceRoot)) { // Redirection m_done = true; return true; } if (!resolveURL(vhost, pathTranslation, sourceRoot)) { // Can't find return false; } return true; }
bool RequestURI::process(const VirtualHost *vhost, Transport *transport, const string &sourceRoot, const string &pathTranslation, const char *url) { splitURL(url, m_originalURL, m_queryString); m_originalURL = StringUtil::UrlDecode(m_originalURL, false); // Fast path for files that exist String canon = Util::canonicalize(string(m_originalURL.c_str(), m_originalURL.size())); String relUrl(canon.charAt(0) == '/' ? canon.substr(1) : canon); if (virtualFileExists(vhost, sourceRoot, pathTranslation, relUrl)) { m_rewrittenURL = relUrl; m_resolvedURL = relUrl; PrependSlash(m_resolvedURL); return true; } if (!rewriteURL(vhost, transport, pathTranslation, sourceRoot)) { // Redirection m_done = true; return true; } if (!resolveURL(vhost, pathTranslation, sourceRoot)) { // Can't find return false; } return true; }
/*********************************************************************** * Launch the server **********************************************************************/ static int runServer(void) { std::string url; if (optarg != NULL) url = optarg; if (url.empty()) url = combineURL("tcp", "::", ""); //default url parameters when not specified std::string scheme, node, service; splitURL(url, scheme, node, service); url = combineURL(scheme.empty()?"tcp":scheme, node, service.empty()?SOAPY_REMOTE_DEFAULT_SERVICE:service); std::cout << uniqueProcessId() << std::endl; std::cout << "Launching the server... " << url << std::endl; SoapySocketSession sess; SoapyRPCSocket s; if (s.bind(url) != 0) { std::cerr << "Server socket bind FAIL: " << s.lastErrorMsg() << std::endl; return EXIT_FAILURE; } std::cout << "Server bound to " << s.getsockname() << std::endl; s.listen(SOAPY_REMOTE_LISTEN_BACKLOG); auto serverListener = new SoapyServerListener(s); std::cout << "Press Ctrl+C to stop the server" << std::endl; signal(SIGINT, sigIntHandler); while (not serverDone) serverListener->handleOnce(); std::cout << "Shutdown client handler threads" << std::endl; delete serverListener; s.close(); std::cout << "Cleanup complete, exiting" << std::endl; return EXIT_SUCCESS; }
PhysicsCollisionObject::ScriptListener* PhysicsCollisionObject::ScriptListener::create(const char* url) { std::string scriptPath, func; splitURL(url, &scriptPath, &func); if (func.empty()) { // Only a function was specified func = scriptPath; scriptPath = ""; } Script* script = NULL; if (!scriptPath.empty()) { script = Game::getInstance()->getScriptController()->loadScript(scriptPath.c_str(), Script::GLOBAL); if (!script) { // Failed to load script return NULL; } } ScriptListener* listener = new ScriptListener(); listener->url = url; listener->script = script; listener->function = func; return listener; }
bool RequestURI::process(const VirtualHost *vhost, Transport *transport, const string &sourceRoot, const string &pathTranslation, const char *url) { splitURL(url, m_originalURL, m_queryString); m_originalURL = StringUtil::UrlDecode(m_originalURL, false); m_rewritten = false; // Fast path for files that exist if (vhost->checkExistenceBeforeRewrite()) { String canon( Util::canonicalize(m_originalURL.c_str(), m_originalURL.size()), AttachString); if (virtualFileExists(vhost, sourceRoot, pathTranslation, canon)) { m_rewrittenURL = canon; m_resolvedURL = canon; return true; } } if (!rewriteURL(vhost, transport, pathTranslation, sourceRoot)) { // Redirection m_done = true; return true; } if (!resolveURL(vhost, pathTranslation, sourceRoot)) { // Can't find return false; } return true; }
bool Game::startup() { if (_state != UNINITIALIZED) return false; setViewport(Rectangle(0.0f, 0.0f, (float)_width, (float)_height)); RenderState::initialize(); FrameBuffer::initialize(); _animationController = new AnimationController(); _animationController->initialize(); _audioController = new AudioController(); _audioController->initialize(); _physicsController = new PhysicsController(); _physicsController->initialize(); _aiController = new AIController(); _aiController->initialize(); _scriptController = new ScriptController(); _scriptController->initialize(); // Load any gamepads, ui or physical. loadGamepads(); // Set the script callback functions. if (_properties) { Properties* scripts = _properties->getNamespace("scripts", true); if (scripts) { const char* callback; while ((callback = scripts->getNextProperty()) != NULL) { std::string url = scripts->getString(); std::string file; std::string id; splitURL(url, &file, &id); if (file.size() <= 0 || id.size() <= 0) { GP_ERROR("Invalid %s script callback function '%s'.", callback, url.c_str()); } else { _scriptController->loadScript(file.c_str()); _scriptController->registerCallback(callback, id.c_str()); } } } } _state = RUNNING; return true; }
/** * Precondition: m_originalURL and m_queryString are set * Postcondition: Output is false and we are redirecting OR * m_rewrittenURL is set and m_queryString is updated if needed */ bool RequestURI::rewriteURL(const VirtualHost *vhost, Transport *transport, const string &pathTranslation, const string &sourceRoot) { bool qsa = false; int redirect = 0; string host = transport->getHeader("host"); m_rewrittenURL = m_originalURL; if (vhost->rewriteURL(host, m_rewrittenURL, qsa, redirect)) { m_rewritten = true; if (qsa && !m_queryString.empty()) { m_rewrittenURL += (m_rewrittenURL.find('?') < 0) ? "?" : "&"; m_rewrittenURL += m_queryString; } if (redirect) { if (m_rewrittenURL.substr(0, 7) != s_http && m_rewrittenURL.substr(0, 8) != s_https) { PrependSlash(m_rewrittenURL); } transport->redirect(m_rewrittenURL.c_str(), redirect, "rewriteURL"); return false; } splitURL(m_rewrittenURL, m_rewrittenURL, m_queryString); } m_rewrittenURL = String( Util::canonicalize(m_rewrittenURL.c_str(), m_rewrittenURL.size()), AttachString); if (!m_rewritten && m_rewrittenURL.charAt(0) == '/') { // A un-rewritten URL is always relative, so remove prepending / m_rewrittenURL = m_rewrittenURL.substr(1); } // If the URL refers to a folder but does not end // with a slash, then we need to redictect String url = m_rewrittenURL; if (!url.empty() && url.charAt(url.length() - 1) != '/') { if (virtualFolderExists(vhost, sourceRoot, pathTranslation, url)) { url += "/"; m_rewritten = true; String queryStr; m_rewrittenURL = m_originalURL; m_rewrittenURL += "/"; if (!m_queryString.empty()) { m_rewrittenURL += "?"; m_rewrittenURL += m_queryString; } if (m_rewrittenURL.substr(0, 7) != s_http && m_rewrittenURL.substr(0, 8) != s_https) { PrependSlash(m_rewrittenURL); } transport->redirect(m_rewrittenURL.c_str(), 301, "rewriteURL"); return false; } } return true; }
void QGpgMECryptoConfigEntry::setURLValue( const KUrl& url ) { QString str = splitURL( mRealArgType, url ); if ( str.isEmpty() && !isOptional() ) mSet = false; else mSet = true; mValue = str; mDirty = true; }
bool RequestURI::process(const VirtualHost *vhost, Transport *transport, const std::string &sourceRoot, const std::string &pathTranslation, const char *url) { splitURL(url, m_originalURL, m_queryString); m_originalURL = StringUtil::UrlDecode(m_originalURL, false); m_rewritten = false; auto scriptFilename = transport->getScriptFilename(); if (!scriptFilename.empty()) { // The transport is overriding everything and just handing us the filename m_originalURL = scriptFilename; if (!resolveURL(vhost, pathTranslation, sourceRoot)) { return false; } if (m_origPathInfo.empty()) { // PATH_INFO wasn't filled by resolveURL() because m_originalURL // didn't contain it. We set it now, based on PATH_TRANSLATED. m_origPathInfo = transport->getPathTranslated(); if (!m_origPathInfo.empty() && m_origPathInfo.charAt(0) != '/') { m_origPathInfo = "/" + m_origPathInfo; } } if (transport->isPathInfoSet()) { m_pathInfo =transport->getPathInfo(); } else { m_pathInfo = m_origPathInfo; } return true; } // Fast path for files that exist if (vhost->checkExistenceBeforeRewrite()) { String canon = FileUtil::canonicalize(m_originalURL); if (virtualFileExists(vhost, sourceRoot, pathTranslation, canon)) { m_rewrittenURL = canon; m_resolvedURL = canon; return true; } } if (!rewriteURL(vhost, transport, pathTranslation, sourceRoot)) { // Redirection m_done = true; return true; } if (!resolveURL(vhost, pathTranslation, sourceRoot)) { // Can't find return false; } return true; }
void QGpgMECryptoConfigEntry::setURLValueList( const KUrl::List& urls ) { QStringList lst; for( KUrl::List::const_iterator it = urls.constBegin(); it != urls.constEnd(); ++it ) { lst << splitURL( mRealArgType, *it ); } mValue = lst; if ( lst.isEmpty() && !isOptional() ) mSet = false; else mSet = true; mDirty = true; }
std::string ScriptController::loadUrl(const char* url) { std::string file; std::string id; splitURL(url, &file, &id); if (id.size() <= 0) { // The url does not reference a script - only a function return file; } // Ensure the script is loaded. if (file.size() > 0) Game::getInstance()->getScriptController()->loadScript(file.c_str()); // Return the function name. return id; }
void URLParser::parseURL(const std::string &url) { size_t length = url.length(); if (length < 7) //过短的URL可以认为是无效的 { assert(false); return; } else { std::string protocal = url.substr(0,7); std::string format_url = url; if (_strcmpi(protocal.c_str(),"http://") == 0) { format_url = url.substr(7,length-7); } splitURL(format_url); } }
std::string ScriptController::loadUrl(const char* url) { std::string file; std::string id; splitURL(url, &file, &id); // Make sure the function isn't empty. if (id.size() <= 0) { GP_ERROR("Got an empty function name when parsing function url '%s'.", url); return std::string(); } // Ensure the script is loaded. if (file.size() > 0) Game::getInstance()->getScriptController()->loadScript(file.c_str()); // Return the function name. return id; }
bool RequestURI::process(const VirtualHost *vhost, Transport *transport, const std::string &sourceRoot, const std::string &pathTranslation, const char *url) { splitURL(url, m_originalURL, m_queryString); m_originalURL = StringUtil::UrlDecode(m_originalURL, false); m_rewritten = false; auto pathTranslated = transport->getPathTranslated(); if (!pathTranslated.empty()) { // The transport is overriding everything and just handing us the filename m_path = m_absolutePath = pathTranslated; processExt(); return true; } // Fast path for files that exist if (vhost->checkExistenceBeforeRewrite()) { String canon( Util::canonicalize(m_originalURL.c_str(), m_originalURL.size()), AttachString); if (virtualFileExists(vhost, sourceRoot, pathTranslation, canon)) { m_rewrittenURL = canon; m_resolvedURL = canon; return true; } } if (!rewriteURL(vhost, transport, pathTranslation, sourceRoot)) { // Redirection m_done = true; return true; } if (!resolveURL(vhost, pathTranslation, sourceRoot)) { // Can't find return false; } return true; }
void ScriptTarget::addScriptCallback(const Event* event, const char* function) { GP_ASSERT(event); GP_ASSERT(function); // Parse the script name (if it exists) and function out std::string scriptPath, func; splitURL(function, &scriptPath, &func); if (func.length() == 0) { // The url doesn't reference a script, only a function func = scriptPath; scriptPath = ""; } // Have we already loaded this global script? bool loaded = true; Script* script = NULL; if (!scriptPath.empty()) { loaded = false; ScriptEntry* se = _scripts; while (se) { if (scriptPath == se->script->getPath() && se->script->getScope() == Script::GLOBAL) { // Script is already loaded script = se->script; loaded = true; break; } se = se->next; } } if (!loaded) { // The specified global script is not yet loaded, so do so script = Game::getInstance()->getScriptController()->loadScript(scriptPath.c_str(), Script::GLOBAL); if (script) { loaded = true; ScriptEntry* se = new ScriptEntry(script); if (_scripts) { ScriptEntry* last = _scripts; while (last->next) last = last->next; last->next = se; se->prev = last; } else { _scripts = se; } } else { GP_WARN("Failed to load script '%s' for script target while registering for function: %s", scriptPath.c_str(), function); } } if (loaded) { // Store the callback if (!_scriptCallbacks) _scriptCallbacks = new std::map<const Event*, std::vector<CallbackFunction>>(); (*_scriptCallbacks)[event].push_back(CallbackFunction(script, func.c_str())); } }
void ScriptTarget::removeScriptCallback(const Event* event, const char* function) { // Parse the script name (if it exists) and function out std::string scriptPath, func; splitURL(function, &scriptPath, &func); if (func.length() == 0) { // The url doesn't reference a script, only a function func = scriptPath; scriptPath = ""; } // Find the script entry for this callback ScriptEntry* scriptEntry = NULL; if (!scriptPath.empty()) { ScriptEntry* se = _scripts; while (se) { if (scriptPath == se->script->getPath() && se->script->getScope() == Script::GLOBAL) { scriptEntry = se; break; } se = se->next; } } Script* script = scriptEntry ? scriptEntry->script : NULL; // Remove any registered callback functions that match the specified one int removedCallbacks = 0; int totalCallbacks = 0; if (_scriptCallbacks) { std::map<const Event*, std::vector<CallbackFunction>>::iterator itr = _scriptCallbacks->begin(); for (; itr != _scriptCallbacks->end(); ++itr) { // Erase matching callback functions for this event bool forEvent = itr->first == event; std::vector<CallbackFunction>& callbacks = itr->second; std::vector<CallbackFunction>::iterator itr2 = callbacks.begin(); while (itr2 != callbacks.end()) { if (itr2->script == script) { ++totalCallbacks; // sum total number of callbacks found for this script if (forEvent && itr2->function == func) { itr2 = callbacks.erase(itr2); ++removedCallbacks; // sum number of callbacks removed } else ++itr2; } } } } // Cleanup the script if there are no remaining callbacks for it if (scriptEntry && (totalCallbacks - removedCallbacks) <= 0) { removeScript(scriptEntry); } }
/** * Precondition: m_originalURL and m_queryString are set * Postcondition: Output is false and we are redirecting OR * m_rewrittenURL is set and m_queryString is updated if needed */ bool RequestURI::rewriteURL(const VirtualHost *vhost, Transport *transport, const std::string &pathTranslation, const std::string &sourceRoot) { bool qsa = false; int redirect = 0; std::string host = transport->getHeader("host"); m_rewrittenURL = m_originalURL; if (vhost->rewriteURL(host, m_rewrittenURL, qsa, redirect)) { m_rewritten = true; if (qsa && !m_queryString.empty()) { m_rewrittenURL += (m_rewrittenURL.find('?') < 0) ? "?" : "&"; m_rewrittenURL += m_queryString; } if (redirect) { if (m_rewrittenURL.substr(0, 7) != s_http && m_rewrittenURL.substr(0, 8) != s_https) { PrependSlash(m_rewrittenURL); } if (redirect < 0) { std::string error; StringBuffer response; int code = 0; HttpProtocol::ProxyRequest(transport, true, m_rewrittenURL.toCppString(), code, error, response); if (!code) { transport->sendString(error, 500, false, false, "proxyRequest"); } else { const char* respData = response.data(); if (!respData) respData = ""; transport->sendRaw(const_cast<char*>(respData), response.size(), code); } transport->onSendEnd(); } else { transport->redirect(m_rewrittenURL.c_str(), redirect); } return false; } splitURL(m_rewrittenURL, m_rewrittenURL, m_queryString); } m_rewrittenURL = FileUtil::canonicalize(m_rewrittenURL); if (!m_rewritten && m_rewrittenURL.charAt(0) == '/') { // A un-rewritten URL is always relative, so remove prepending / m_rewrittenURL = m_rewrittenURL.substr(1); } // If the URL refers to a folder but does not end // with a slash, then we need to redictect String url = m_rewrittenURL; if (!url.empty() && url.charAt(url.length() - 1) != '/') { if (virtualFolderExists(vhost, sourceRoot, pathTranslation, url)) { if (m_originalURL.find("..") != String::npos) { transport->sendString(getDefault404(), 404); transport->onSendEnd(); return false; } url += "/"; m_rewritten = true; String queryStr; m_rewrittenURL = m_originalURL; m_rewrittenURL += "/"; if (!m_queryString.empty()) { m_rewrittenURL += "?"; m_rewrittenURL += m_queryString; } if (m_rewrittenURL.substr(0, 7) != s_http && m_rewrittenURL.substr(0, 8) != s_https) { PrependSlash(m_rewrittenURL); } transport->redirect(m_rewrittenURL.c_str(), 301); return false; } } return true; }
/*********************************************************************** * Handler dispatcher implementation **********************************************************************/ bool SoapyClientHandler::handleOnce(SoapyRPCUnpacker &unpacker, SoapyRPCPacker &packer) { SoapyRemoteCalls call; unpacker & call; switch (call) { //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_FIND: //////////////////////////////////////////////////////////////////// { SoapySDR::Kwargs args; unpacker & args; packer & SoapySDR::Device::enumerate(args); } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_MAKE: //////////////////////////////////////////////////////////////////// { SoapySDR::Kwargs args; unpacker & args; std::lock_guard<std::mutex> lock(factoryMutex); if (_dev == nullptr) _dev = SoapySDR::Device::make(args); packer & SOAPY_REMOTE_VOID; } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_UNMAKE: //////////////////////////////////////////////////////////////////// { std::lock_guard<std::mutex> lock(factoryMutex); if (_dev != nullptr) SoapySDR::Device::unmake(_dev); _dev = nullptr; packer & SOAPY_REMOTE_VOID; } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_HANGUP: //////////////////////////////////////////////////////////////////// { packer & SOAPY_REMOTE_VOID; } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_GET_SERVER_ID: //////////////////////////////////////////////////////////////////// { packer & uniqueProcessId(); } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_START_LOG_FORWARDING: //////////////////////////////////////////////////////////////////// { if (_logForwarder == nullptr) _logForwarder = new SoapyLogForwarder(_sock); packer & SOAPY_REMOTE_VOID; } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_STOP_LOG_FORWARDING: //////////////////////////////////////////////////////////////////// { if (_logForwarder != nullptr) delete _logForwarder; _logForwarder = nullptr; packer & SOAPY_REMOTE_VOID; } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_GET_DRIVER_KEY: //////////////////////////////////////////////////////////////////// { packer & _dev->getDriverKey(); } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_GET_HARDWARE_KEY: //////////////////////////////////////////////////////////////////// { packer & _dev->getHardwareKey(); } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_GET_HARDWARE_INFO: //////////////////////////////////////////////////////////////////// { packer & _dev->getHardwareInfo(); } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_SET_FRONTEND_MAPPING: //////////////////////////////////////////////////////////////////// { char direction = 0; std::string mapping; unpacker & direction; unpacker & mapping; _dev->setFrontendMapping(direction, mapping); packer & SOAPY_REMOTE_VOID; } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_GET_FRONTEND_MAPPING: //////////////////////////////////////////////////////////////////// { char direction = 0; unpacker & direction; packer & _dev->getFrontendMapping(direction); } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_GET_NUM_CHANNELS: //////////////////////////////////////////////////////////////////// { char direction = 0; unpacker & direction; packer & int(_dev->getNumChannels(direction)); } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_GET_FULL_DUPLEX: //////////////////////////////////////////////////////////////////// { char direction = 0; int channel = 0; unpacker & direction; unpacker & channel; packer & _dev->getFullDuplex(direction, channel); } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_SETUP_STREAM: //////////////////////////////////////////////////////////////////// { char direction = 0; std::string format; std::vector<size_t> channels; SoapySDR::Kwargs args; std::string clientBindPort; std::string statusBindPort; unpacker & direction; unpacker & format; unpacker & channels; unpacker & args; unpacker & clientBindPort; unpacker & statusBindPort; //parse args for buffer configuration size_t mtu = SOAPY_REMOTE_DEFAULT_ENDPOINT_MTU; const auto mtuIt = args.find(SOAPY_REMOTE_KWARG_MTU); if (mtuIt != args.end()) mtu = size_t(std::stod(mtuIt->second)); size_t window = SOAPY_REMOTE_DEFAULT_ENDPOINT_WINDOW; const auto windowIt = args.find(SOAPY_REMOTE_KWARG_WINDOW); if (windowIt != args.end()) window = size_t(std::stod(windowIt->second)); double priority = SOAPY_REMOTE_DEFAULT_THREAD_PRIORITY; const auto priorityIt = args.find(SOAPY_REMOTE_KWARG_PRIORITY); if (priorityIt != args.end()) priority = std::stod(priorityIt->second); //create stream auto stream = _dev->setupStream(direction, format, channels, args); //load data structure auto &data = _streamData[_nextStreamId]; data.streamId = _nextStreamId++; data.device = _dev; data.stream = stream; data.format = format; for (const auto chan : channels) data.chanMask |= (1 << chan); data.priority = priority; //extract socket node information std::string serverBindPort; std::string localNode, remoteNode; std::string scheme, node, service; splitURL(_sock.getsockname(), scheme, localNode, service); splitURL(_sock.getpeername(), scheme, remoteNode, service); //bind the stream socket to an automatic port const auto bindURL = combineURL("udp", localNode, "0"); int ret = data.streamSock.bind(bindURL); if (ret != 0) { const std::string errorMsg = data.streamSock.lastErrorMsg(); _streamData.erase(data.streamId); throw std::runtime_error("SoapyRemote::setupStream("+bindURL+") -- bind FAIL: " + errorMsg); } SoapySDR::logf(SOAPY_SDR_INFO, "Server side stream bound to %s", data.streamSock.getsockname().c_str()); splitURL(data.streamSock.getsockname(), scheme, node, serverBindPort); //connect the stream socket to the specified port auto connectURL = combineURL("udp", remoteNode, clientBindPort); ret = data.streamSock.connect(connectURL); if (ret != 0) { const std::string errorMsg = data.streamSock.lastErrorMsg(); _streamData.erase(data.streamId); throw std::runtime_error("SoapyRemote::setupStream("+connectURL+") -- connect FAIL: " + errorMsg); } SoapySDR::logf(SOAPY_SDR_INFO, "Server side stream connected to %s", data.streamSock.getpeername().c_str()); //connect the status socket to the specified port connectURL = combineURL("udp", remoteNode, statusBindPort); ret = data.statusSock.connect(connectURL); if (ret != 0) { const std::string errorMsg = data.statusSock.lastErrorMsg(); _streamData.erase(data.streamId); throw std::runtime_error("SoapyRemote::setupStream("+connectURL+") -- connect FAIL: " + errorMsg); } SoapySDR::logf(SOAPY_SDR_INFO, "Server side status connected to %s", data.statusSock.getpeername().c_str()); //create endpoint data.endpoint = new SoapyStreamEndpoint(data.streamSock, data.statusSock, direction == SOAPY_SDR_TX, channels.size(), formatToSize(format), mtu, window); //start worker thread, this is not backwards, //receive from device means using a send endpoint //transmit to device means using a recv endpoint if (direction == SOAPY_SDR_RX) data.startSendThread(); if (direction == SOAPY_SDR_TX) data.startRecvThread(); data.startStatThread(); packer & data.streamId; packer & serverBindPort; } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_CLOSE_STREAM: //////////////////////////////////////////////////////////////////// { int streamId = 0; unpacker & streamId; //cleanup data and stop worker thread auto &data = _streamData.at(streamId); data.stopThreads(); _dev->closeStream(data.stream); _streamData.erase(streamId); packer & SOAPY_REMOTE_VOID; } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_ACTIVATE_STREAM: //////////////////////////////////////////////////////////////////// { int streamId = 0; int flags = 0; long long timeNs = 0; int numElems = 0; unpacker & streamId; unpacker & flags; unpacker & timeNs; unpacker & numElems; auto &data = _streamData.at(streamId); packer & _dev->activateStream(data.stream, flags, timeNs, size_t(numElems)); } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_DEACTIVATE_STREAM: //////////////////////////////////////////////////////////////////// { int streamId = 0; int flags = 0; long long timeNs = 0; unpacker & streamId; unpacker & flags; unpacker & timeNs; auto &data = _streamData.at(streamId); packer & _dev->deactivateStream(data.stream, flags, timeNs); } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_LIST_ANTENNAS: //////////////////////////////////////////////////////////////////// { char direction = 0; int channel = 0; unpacker & direction; unpacker & channel; packer & _dev->listAntennas(direction, channel); } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_SET_ANTENNA: //////////////////////////////////////////////////////////////////// { char direction = 0; int channel = 0; std::string name; unpacker & direction; unpacker & channel; unpacker & name; _dev->setAntenna(direction, channel, name); packer & SOAPY_REMOTE_VOID; } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_GET_ANTENNA: //////////////////////////////////////////////////////////////////// { char direction = 0; int channel = 0; unpacker & direction; unpacker & channel; packer & _dev->getAntenna(direction, channel); } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_HAS_DC_OFFSET_MODE: //////////////////////////////////////////////////////////////////// { char direction = 0; int channel = 0; unpacker & direction; unpacker & channel; packer & _dev->hasDCOffsetMode(direction, channel); } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_SET_DC_OFFSET_MODE: //////////////////////////////////////////////////////////////////// { char direction = 0; int channel = 0; bool automatic = false; unpacker & direction; unpacker & channel; unpacker & automatic; _dev->setDCOffsetMode(direction, channel, automatic); packer & SOAPY_REMOTE_VOID; } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_GET_DC_OFFSET_MODE: //////////////////////////////////////////////////////////////////// { char direction = 0; int channel = 0; unpacker & direction; unpacker & channel; packer & _dev->getDCOffsetMode(direction, channel); } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_HAS_DC_OFFSET: //////////////////////////////////////////////////////////////////// { char direction = 0; int channel = 0; unpacker & direction; unpacker & channel; packer & _dev->hasDCOffset(direction, channel); } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_SET_DC_OFFSET: //////////////////////////////////////////////////////////////////// { char direction = 0; int channel = 0; std::complex<double> offset; unpacker & direction; unpacker & channel; unpacker & offset; _dev->setDCOffset(direction, channel, offset); packer & SOAPY_REMOTE_VOID; } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_GET_DC_OFFSET: //////////////////////////////////////////////////////////////////// { char direction = 0; int channel = 0; unpacker & direction; unpacker & channel; packer & _dev->getDCOffset(direction, channel); } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_HAS_IQ_BALANCE_MODE: //////////////////////////////////////////////////////////////////// { char direction = 0; int channel = 0; unpacker & direction; unpacker & channel; packer & _dev->hasIQBalance(direction, channel); } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_SET_IQ_BALANCE_MODE: //////////////////////////////////////////////////////////////////// { char direction = 0; int channel = 0; std::complex<double> balance; unpacker & direction; unpacker & channel; unpacker & balance; _dev->setIQBalance(direction, channel, balance); packer & SOAPY_REMOTE_VOID; } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_GET_IQ_BALANCE_MODE: //////////////////////////////////////////////////////////////////// { char direction = 0; int channel = 0; unpacker & direction; unpacker & channel; packer & _dev->getIQBalance(direction, channel); } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_LIST_GAINS: //////////////////////////////////////////////////////////////////// { char direction = 0; int channel = 0; unpacker & direction; unpacker & channel; packer & _dev->listGains(direction, channel); } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_SET_GAIN_MODE: //////////////////////////////////////////////////////////////////// { char direction = 0; int channel = 0; bool automatic = false; unpacker & direction; unpacker & channel; unpacker & automatic; _dev->setGainMode(direction, channel, automatic); packer & SOAPY_REMOTE_VOID; } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_GET_GAIN_MODE: //////////////////////////////////////////////////////////////////// { char direction = 0; int channel = 0; unpacker & direction; unpacker & channel; packer & _dev->getGainMode(direction, channel); } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_SET_GAIN: //////////////////////////////////////////////////////////////////// { char direction = 0; int channel = 0; double value = 0; unpacker & direction; unpacker & channel; unpacker & value; _dev->setGain(direction, channel, value); packer & SOAPY_REMOTE_VOID; } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_SET_GAIN_ELEMENT: //////////////////////////////////////////////////////////////////// { char direction = 0; int channel = 0; std::string name; double value = 0; unpacker & direction; unpacker & channel; unpacker & name; unpacker & value; _dev->setGain(direction, channel, name, value); packer & SOAPY_REMOTE_VOID; } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_GET_GAIN: //////////////////////////////////////////////////////////////////// { char direction = 0; int channel = 0; unpacker & direction; unpacker & channel; packer & _dev->getGain(direction, channel); } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_GET_GAIN_ELEMENT: //////////////////////////////////////////////////////////////////// { char direction = 0; int channel = 0; std::string name; unpacker & direction; unpacker & channel; unpacker & name; packer & _dev->getGain(direction, channel, name); } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_GET_GAIN_RANGE: //////////////////////////////////////////////////////////////////// { char direction = 0; int channel = 0; unpacker & direction; unpacker & channel; packer & _dev->getGainRange(direction, channel); } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_GET_GAIN_RANGE_ELEMENT: //////////////////////////////////////////////////////////////////// { char direction = 0; int channel = 0; std::string name; unpacker & direction; unpacker & channel; unpacker & name; packer & _dev->getGainRange(direction, channel, name); } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_SET_FREQUENCY: //////////////////////////////////////////////////////////////////// { char direction = 0; int channel = 0; double value = 0; SoapySDR::Kwargs args; unpacker & direction; unpacker & channel; unpacker & value; unpacker & args; _dev->setFrequency(direction, channel, value, args); packer & SOAPY_REMOTE_VOID; } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_SET_FREQUENCY_COMPONENT: //////////////////////////////////////////////////////////////////// { char direction = 0; int channel = 0; std::string name; double value = 0; SoapySDR::Kwargs args; unpacker & direction; unpacker & channel; unpacker & name; unpacker & value; unpacker & args; _dev->setFrequency(direction, channel, name, value, args); packer & SOAPY_REMOTE_VOID; } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_GET_FREQUENCY: //////////////////////////////////////////////////////////////////// { char direction = 0; int channel = 0; unpacker & direction; unpacker & channel; packer & _dev->getFrequency(direction, channel); } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_GET_FREQUENCY_COMPONENT: //////////////////////////////////////////////////////////////////// { char direction = 0; int channel = 0; std::string name; unpacker & direction; unpacker & channel; unpacker & name; packer & _dev->getFrequency(direction, channel, name); } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_LIST_FREQUENCIES: //////////////////////////////////////////////////////////////////// { char direction = 0; int channel = 0; unpacker & direction; unpacker & channel; packer & _dev->listFrequencies(direction, channel); } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_GET_FREQUENCY_RANGE: //////////////////////////////////////////////////////////////////// { char direction = 0; int channel = 0; unpacker & direction; unpacker & channel; packer & _dev->getFrequencyRange(direction, channel); } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_GET_FREQUENCY_RANGE_COMPONENT: //////////////////////////////////////////////////////////////////// { char direction = 0; int channel = 0; std::string name; unpacker & direction; unpacker & channel; unpacker & name; packer & _dev->getFrequencyRange(direction, channel, name); } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_SET_SAMPLE_RATE: //////////////////////////////////////////////////////////////////// { char direction = 0; int channel = 0; double rate = 0; unpacker & direction; unpacker & channel; unpacker & rate; _dev->setSampleRate(direction, channel, rate); packer & SOAPY_REMOTE_VOID; } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_GET_SAMPLE_RATE: //////////////////////////////////////////////////////////////////// { char direction = 0; int channel = 0; unpacker & direction; unpacker & channel; packer & _dev->getSampleRate(direction, channel); } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_LIST_SAMPLE_RATES: //////////////////////////////////////////////////////////////////// { char direction = 0; int channel = 0; unpacker & direction; unpacker & channel; packer & _dev->listSampleRates(direction, channel); } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_SET_BANDWIDTH: //////////////////////////////////////////////////////////////////// { char direction = 0; int channel = 0; double bw = 0; unpacker & direction; unpacker & channel; unpacker & bw; _dev->setBandwidth(direction, channel, bw); packer & SOAPY_REMOTE_VOID; } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_GET_BANDWIDTH: //////////////////////////////////////////////////////////////////// { char direction = 0; int channel = 0; unpacker & direction; unpacker & channel; packer & _dev->getBandwidth(direction, channel); } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_LIST_BANDWIDTHS: //////////////////////////////////////////////////////////////////// { char direction = 0; int channel = 0; unpacker & direction; unpacker & channel; packer & _dev->listBandwidths(direction, channel); } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_SET_MASTER_CLOCK_RATE: //////////////////////////////////////////////////////////////////// { double rate = 0; unpacker & rate; _dev->setMasterClockRate(rate); packer & SOAPY_REMOTE_VOID; } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_GET_MASTER_CLOCK_RATE: //////////////////////////////////////////////////////////////////// { packer & _dev->getMasterClockRate(); } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_LIST_CLOCK_SOURCES: //////////////////////////////////////////////////////////////////// { packer & _dev->listClockSources(); } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_SET_CLOCK_SOURCE: //////////////////////////////////////////////////////////////////// { std::string source; unpacker & source; _dev->setClockSource(source); packer & SOAPY_REMOTE_VOID; } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_GET_CLOCK_SOURCE: //////////////////////////////////////////////////////////////////// { packer & _dev->getClockSource(); } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_LIST_TIME_SOURCES: //////////////////////////////////////////////////////////////////// { packer & _dev->listTimeSources(); } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_SET_TIME_SOURCE: //////////////////////////////////////////////////////////////////// { std::string source; unpacker & source; _dev->setTimeSource(source); packer & SOAPY_REMOTE_VOID; } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_GET_TIME_SOURCE: //////////////////////////////////////////////////////////////////// { packer & _dev->getTimeSource(); } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_HAS_HARDWARE_TIME: //////////////////////////////////////////////////////////////////// { std::string what; unpacker & what; packer & _dev->hasHardwareTime(what); } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_GET_HARDWARE_TIME: //////////////////////////////////////////////////////////////////// { std::string what; unpacker & what; packer & _dev->getHardwareTime(what); } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_SET_HARDWARE_TIME: //////////////////////////////////////////////////////////////////// { long long timeNs = 0; std::string what; unpacker & timeNs; unpacker & what; _dev->setHardwareTime(timeNs, what); packer & SOAPY_REMOTE_VOID; } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_SET_COMMAND_TIME: //////////////////////////////////////////////////////////////////// { long long timeNs = 0; std::string what; unpacker & timeNs; unpacker & what; _dev->setCommandTime(timeNs, what); packer & SOAPY_REMOTE_VOID; } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_LIST_SENSORS: //////////////////////////////////////////////////////////////////// { packer & _dev->listSensors(); } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_READ_SENSOR: //////////////////////////////////////////////////////////////////// { std::string name; unpacker & name; packer & _dev->readSensor(name); } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_LIST_CHANNEL_SENSORS: //////////////////////////////////////////////////////////////////// { char direction = 0; int channel = 0; unpacker & direction; unpacker & channel; packer & _dev->listSensors(direction, channel); } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_READ_CHANNEL_SENSOR: //////////////////////////////////////////////////////////////////// { char direction = 0; int channel = 0; std::string name; unpacker & direction; unpacker & channel; unpacker & name; packer & _dev->readSensor(direction, channel, name); } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_WRITE_REGISTER: //////////////////////////////////////////////////////////////////// { int addr = 0; int value = 0; unpacker & addr; unpacker & value; _dev->writeRegister(unsigned(addr), unsigned(value)); packer & SOAPY_REMOTE_VOID; } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_READ_REGISTER: //////////////////////////////////////////////////////////////////// { int addr = 0; unpacker & addr; packer & int(_dev->readRegister(unsigned(addr))); } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_WRITE_SETTING: //////////////////////////////////////////////////////////////////// { std::string key; std::string value; unpacker & key; unpacker & value; _dev->writeSetting(key, value); packer & SOAPY_REMOTE_VOID; } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_READ_SETTING: //////////////////////////////////////////////////////////////////// { std::string key; unpacker & key; packer & _dev->readSetting(key); } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_LIST_GPIO_BANKS: //////////////////////////////////////////////////////////////////// { packer & _dev->listGPIOBanks(); } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_WRITE_GPIO: //////////////////////////////////////////////////////////////////// { std::string bank; int value = 0; unpacker & bank; unpacker & value; _dev->writeGPIO(bank, unsigned(value)); packer & SOAPY_REMOTE_VOID; } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_WRITE_GPIO_MASKED: //////////////////////////////////////////////////////////////////// { std::string bank; int value = 0; int mask = 0; unpacker & bank; unpacker & value; unpacker & mask; _dev->writeGPIO(bank, unsigned(value), unsigned(mask)); packer & SOAPY_REMOTE_VOID; } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_READ_GPIO: //////////////////////////////////////////////////////////////////// { std::string bank; unpacker & bank; packer & int(_dev->readGPIO(bank)); } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_WRITE_GPIO_DIR: //////////////////////////////////////////////////////////////////// { std::string bank; int dir = 0; unpacker & bank; unpacker & dir; _dev->writeGPIODir(bank, unsigned(dir)); packer & SOAPY_REMOTE_VOID; } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_WRITE_GPIO_DIR_MASKED: //////////////////////////////////////////////////////////////////// { std::string bank; int dir = 0; int mask = 0; unpacker & bank; unpacker & dir; unpacker & mask; _dev->writeGPIODir(bank, unsigned(dir), unsigned(mask)); packer & SOAPY_REMOTE_VOID; } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_READ_GPIO_DIR: //////////////////////////////////////////////////////////////////// { std::string bank; unpacker & bank; packer & int(_dev->readGPIODir(bank)); } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_WRITE_I2C: //////////////////////////////////////////////////////////////////// { int addr = 0; std::string data; unpacker & addr; unpacker & data; _dev->writeI2C(addr, data); packer & SOAPY_REMOTE_VOID; } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_READ_I2C: //////////////////////////////////////////////////////////////////// { int addr = 0; int numBytes = 0; unpacker & addr; unpacker & numBytes; packer & _dev->readI2C(addr, unsigned(numBytes)); } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_TRANSACT_SPI: //////////////////////////////////////////////////////////////////// { int addr = 0; int data = 0; int numBits = 0; unpacker & addr; unpacker & data; unpacker & numBits; packer & int(_dev->transactSPI(addr, unsigned(data), size_t(numBits))); } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_LIST_UARTS: //////////////////////////////////////////////////////////////////// { packer & _dev->listUARTs(); } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_WRITE_UART: //////////////////////////////////////////////////////////////////// { std::string which; std::string data; unpacker & which; unpacker & data; _dev->writeUART(which, data); packer & SOAPY_REMOTE_VOID; } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_READ_UART: //////////////////////////////////////////////////////////////////// { std::string which; int timeoutUs = 0; unpacker & which; unpacker & timeoutUs; packer & _dev->readUART(which, long(timeoutUs)); } break; default: throw std::runtime_error( "SoapyClientHandler::handleOnce("+std::to_string(int(call))+") unknown call"); } return call != SOAPY_REMOTE_HANGUP; }
SoapySDR::Stream *SoapyRemoteDevice::setupStream( const int direction, const std::string &localFormat, const std::vector<size_t> &channels, const SoapySDR::Kwargs &args) { //extract remote endpoint format using special remoteFormat keyword //use the client's local format when the remote format is not specified auto remoteFormat = localFormat; const auto remoteFormatIt = args.find(SOAPY_REMOTE_KWARG_FORMAT); if (remoteFormatIt != args.end()) remoteFormat = remoteFormatIt->second; double scaleFactor = SOAPY_REMOTE_DEFAULT_SCALING; const auto scaleFactorIt = args.find(SOAPY_REMOTE_KWARG_SCALAR); if (scaleFactorIt != args.end()) scaleFactor = std::stod(scaleFactorIt->second); size_t mtu = SOAPY_REMOTE_DEFAULT_ENDPOINT_MTU; const auto mtuIt = args.find(SOAPY_REMOTE_KWARG_MTU); if (mtuIt != args.end()) mtu = size_t(std::stod(mtuIt->second)); size_t window = SOAPY_REMOTE_DEFAULT_ENDPOINT_WINDOW; const auto windowIt = args.find(SOAPY_REMOTE_KWARG_WINDOW); if (windowIt != args.end()) window = size_t(std::stod(windowIt->second)); SoapySDR::logf(SOAPY_SDR_INFO, "SoapyRemote::setup%sStream(remoteFormat=%s, localFormat=%s, scaleFactor=%g, mtu=%d, window=%d)", (direction == SOAPY_SDR_RX)?"Rx":"Tx", remoteFormat.c_str(), localFormat.c_str(), scaleFactor, int(mtu), int(window)); //check supported formats ConvertTypes convertType = CONVERT_MEMCPY; if (localFormat == remoteFormat) convertType = CONVERT_MEMCPY; else if (localFormat == "CF32" and remoteFormat == "CS16") convertType = CONVERT_CF32_CS16; else throw std::runtime_error( "SoapyRemote::setupStream() conversion not supported;" "localFormat="+localFormat+", remoteFormat="+remoteFormat); //allocate new local stream data ClientStreamData *data = new ClientStreamData(); data->localFormat = localFormat; data->remoteFormat = remoteFormat; data->recvBuffs.resize(channels.size()); data->sendBuffs.resize(channels.size()); data->convertType = convertType; data->scaleFactor = scaleFactor; //extract socket node information std::string clientBindPort, statusBindPort; std::string localNode, remoteNode; std::string scheme, node, service; splitURL(_sock.getsockname(), scheme, localNode, service); splitURL(_sock.getpeername(), scheme, remoteNode, service); //bind the stream socket to an automatic port const auto bindURL = combineURL("udp", localNode, "0"); int ret = data->streamSock.bind(bindURL); if (ret != 0) { const std::string errorMsg = data->streamSock.lastErrorMsg(); delete data; throw std::runtime_error("SoapyRemote::setupStream("+bindURL+") -- bind FAIL: " + errorMsg); } SoapySDR::logf(SOAPY_SDR_INFO, "Client side stream bound to %s", data->streamSock.getsockname().c_str()); splitURL(data->streamSock.getsockname(), scheme, node, clientBindPort); //bind the status socket to an automatic port ret = data->statusSock.bind(bindURL); if (ret != 0) { const std::string errorMsg = data->statusSock.lastErrorMsg(); delete data; throw std::runtime_error("SoapyRemote::setupStream("+bindURL+") -- bind FAIL: " + errorMsg); } SoapySDR::logf(SOAPY_SDR_INFO, "Client side status bound to %s", data->streamSock.getsockname().c_str()); splitURL(data->statusSock.getsockname(), scheme, node, statusBindPort); //setup the remote end of the stream std::lock_guard<std::mutex> lock(_mutex); SoapyRPCPacker packer(_sock); packer & SOAPY_REMOTE_SETUP_STREAM; packer & char(direction); packer & remoteFormat; packer & channels; packer & args; packer & clientBindPort; packer & statusBindPort; packer(); SoapyRPCUnpacker unpacker(_sock); std::string serverBindPort; unpacker & data->streamId; unpacker & serverBindPort; //connect the stream socket to the specified port const auto connectURL = combineURL("udp", remoteNode, serverBindPort); ret = data->streamSock.connect(connectURL); if (ret != 0) { const std::string errorMsg = data->streamSock.lastErrorMsg(); delete data; throw std::runtime_error("SoapyRemote::setupStream("+connectURL+") -- connect FAIL: " + errorMsg); } SoapySDR::logf(SOAPY_SDR_INFO, "Client side stream connected to %s", data->streamSock.getpeername().c_str()); //create endpoint data->endpoint = new SoapyStreamEndpoint(data->streamSock, data->statusSock, direction == SOAPY_SDR_RX, channels.size(), formatToSize(remoteFormat), mtu, window); return (SoapySDR::Stream *)data; }