diff --git a/slsDetectorSoftware/src/DetectorImpl.cpp b/slsDetectorSoftware/src/DetectorImpl.cpp index 5ff20d219..6be175391 100644 --- a/slsDetectorSoftware/src/DetectorImpl.cpp +++ b/slsDetectorSoftware/src/DetectorImpl.cpp @@ -1670,7 +1670,9 @@ void DetectorImpl::updateRxUDPDatastreamMetadata() { } } - modules[0]->updateRxUDPPortDisableMetadata(disable); + if (modules[0]->getUseReceiverFlag()) { + modules[0]->updateRxUDPPortDisableMetadata(disable); + } } std::vector DetectorImpl::getRxDisabledUDPPortIndices() const { diff --git a/slsDetectorSoftware/src/Module.cpp b/slsDetectorSoftware/src/Module.cpp index 64be1d6e7..62874e0f8 100644 --- a/slsDetectorSoftware/src/Module.cpp +++ b/slsDetectorSoftware/src/Module.cpp @@ -541,39 +541,15 @@ void Module::setSynchronization(const bool value) { } std::vector Module::getBadChannels() const { - auto client = DetectorSocket(shm()->hostname, shm()->controlPort); - client.Send(F_GET_BAD_CHANNELS); - client.setFnum(F_GET_BAD_CHANNELS); - if (client.Receive() == FAIL) { - throw DetectorError("Detector " + std::to_string(moduleIndex) + - " returned error: " + client.readErrorMessage()); + auto retval = sendToDetectorVarVector(F_GET_BAD_CHANNELS); + for (size_t i = 0; i < retval.size(); ++i) { + LOG(logDEBUG1) << i << ":" << retval[i]; } - // receive badchannels - auto nch = client.Receive(); - std::vector badchannels(nch); - if (nch > 0) { - client.Receive(badchannels); - for (size_t i = 0; i < badchannels.size(); ++i) { - LOG(logDEBUG1) << i << ":" << badchannels[i]; - } - } - return badchannels; + return retval; } void Module::setBadChannels(std::vector list) { - auto nch = static_cast(list.size()); - LOG(logDEBUG1) << "Sending bad channels to detector, nch:" << nch; - auto client = DetectorSocket(shm()->hostname, shm()->controlPort); - client.Send(F_SET_BAD_CHANNELS); - client.setFnum(F_SET_BAD_CHANNELS); - client.Send(nch); - if (nch > 0) { - client.Send(list); - } - if (client.Receive() == FAIL) { - throw DetectorError("Detector " + std::to_string(moduleIndex) + - " returned error: " + client.readErrorMessage()); - } + sendToDetectorVarVector(F_SET_BAD_CHANNELS, list); } int Module::getRow() const { return sendToDetector(F_GET_ROW); } @@ -833,21 +809,17 @@ bool Module::isPowerEnabled(defs::powerIndex index) const { void Module::setPowerEnabled(const std::vector &indices, bool enable) { - auto client = DetectorSocket(shm()->hostname, shm()->controlPort); - client.Send(F_SET_POWER); - client.setFnum(F_SET_POWER); - int count = indices.size(); - client.Send(count); + int count = static_cast(indices.size()); std::vector indices_int(count); - for (size_t i = 0; i < indices.size(); ++i) { + for (int i = 0; i < count; ++i) { indices_int[i] = static_cast(indices[i]); } + // sends a variable vector and an enable + auto client = createDetectorSocket(); + client.sendCommand(F_SET_POWER, &count, sizeof(count)); client.Send(indices_int); client.Send(static_cast(enable)); - if (client.Receive() == FAIL) { - throw DetectorError("Detector " + std::to_string(moduleIndex) + - " returned error: " + client.readErrorMessage()); - } + client.readReply(nullptr, 0); } int Module::getPowerADC(defs::powerIndex index) const { @@ -1022,72 +994,15 @@ double Module::getReceiverProgress() const { } std::vector Module::getFramesCaughtByReceiver() const { - // TODO!(Erik) Refactor - LOG(logDEBUG1) << "Getting frames caught"; - if (shm()->useReceiverFlag) { - auto client = ReceiverSocket(shm()->rxHostname, shm()->rxTCPPort); - client.Send(F_GET_RECEIVER_FRAMES_CAUGHT); - client.setFnum(F_GET_RECEIVER_FRAMES_CAUGHT); - if (client.Receive() == FAIL) { - throw ReceiverError( - "Receiver " + std::to_string(moduleIndex) + - " returned error: " + client.readErrorMessage()); - } else { - auto nports = client.Receive(); - std::vector retval(nports); - client.Receive(retval); - LOG(logDEBUG1) << "Frames caught of Receiver" << moduleIndex << ": " - << ToString(retval); - return retval; - } - } - throw RuntimeError("No receiver to get frames caught."); + return sendToReceiverVarVector(F_GET_RECEIVER_FRAMES_CAUGHT); } std::vector Module::getNumMissingPackets() const { - // TODO!(Erik) Refactor - LOG(logDEBUG1) << "Getting num missing packets"; - if (shm()->useReceiverFlag) { - auto client = ReceiverSocket(shm()->rxHostname, shm()->rxTCPPort); - client.Send(F_GET_NUM_MISSING_PACKETS); - client.setFnum(F_GET_NUM_MISSING_PACKETS); - if (client.Receive() == FAIL) { - throw ReceiverError( - "Receiver " + std::to_string(moduleIndex) + - " returned error: " + client.readErrorMessage()); - } else { - auto nports = client.Receive(); - std::vector retval(nports); - client.Receive(retval); - LOG(logDEBUG1) << "Missing packets of Receiver" << moduleIndex - << ": " << ToString(retval); - return retval; - } - } - throw RuntimeError("No receiver to get missing packets."); + return sendToReceiverVarVector(F_GET_NUM_MISSING_PACKETS); } std::vector Module::getReceiverCurrentFrameIndex() const { - // TODO!(Erik) Refactor - LOG(logDEBUG1) << "Getting frame index"; - if (shm()->useReceiverFlag) { - auto client = ReceiverSocket(shm()->rxHostname, shm()->rxTCPPort); - client.Send(F_GET_RECEIVER_FRAME_INDEX); - client.setFnum(F_GET_RECEIVER_FRAME_INDEX); - if (client.Receive() == FAIL) { - throw ReceiverError( - "Receiver " + std::to_string(moduleIndex) + - " returned error: " + client.readErrorMessage()); - } else { - auto nports = client.Receive(); - std::vector retval(nports); - client.Receive(retval); - LOG(logDEBUG1) << "Frame index of Receiver" << moduleIndex << ": " - << ToString(retval); - return retval; - } - } - throw RuntimeError("No receiver to get frame index."); + return sendToReceiverVarVector(F_GET_RECEIVER_FRAME_INDEX); } uint64_t Module::getNextFrameNumber() const { @@ -1435,46 +1350,11 @@ void Module::setUDPDataStream(const portPosition port, const bool enable) { } void Module::updateRxUDPPortDisableMetadata(const std::vector &disable) { - if (!shm()->useReceiverFlag) { - return; - } - LOG(logDEBUG) << "Updating UDP port disable metadata in Receiver 0"; - auto client = ReceiverSocket(shm()->rxHostname, shm()->rxTCPPort); - - client.Send(F_RECEIVER_SET_UDP_PORT_DISABLE_META); - client.setFnum(F_RECEIVER_SET_UDP_PORT_DISABLE_META); - - auto nports = static_cast(disable.size()); - client.Send(nports); - if (nports > 0) { - client.Send(disable); - } - if (client.Receive() == FAIL) { - throw ReceiverError("Receiver " + std::to_string(moduleIndex) + - " returned error: " + client.readErrorMessage()); - } + sendToReceiverVarVector(F_RECEIVER_SET_UDP_PORT_DISABLE_META, disable); } std::vector Module::getRxUDPPortDisableMetadata() const { - if (!shm()->useReceiverFlag) { - throw RuntimeError("No receiver to get disabled udp port indices."); - } - - LOG(logDEBUG) << "Getting UDP port disable metadata in Receiver 0"; - auto client = ReceiverSocket(shm()->rxHostname, shm()->rxTCPPort); - - client.Send(F_RECEIVER_GET_UDP_PORT_DISABLE_META); - client.setFnum(F_RECEIVER_GET_UDP_PORT_DISABLE_META); - if (client.Receive() == FAIL) { - throw ReceiverError("Receiver " + std::to_string(moduleIndex) + - " returned error: " + client.readErrorMessage()); - } - auto nports = client.Receive(); - std::vector retval(nports); - if (nports > 0) { - client.Receive(retval); - } - return retval; + return sendToReceiverVarVector(F_RECEIVER_GET_UDP_PORT_DISABLE_META); } // Receiver Config @@ -1638,93 +1518,39 @@ void Module::setRxArping(bool enable) { } std::vector Module::getRxROI() const { - LOG(logDEBUG1) << "Getting receiver ROI for Module " << moduleIndex; - // check number of ports - if (!shm()->useReceiverFlag) { - throw RuntimeError("No receiver to get ROI."); - } - auto client = ReceiverSocket(shm()->rxHostname, shm()->rxTCPPort); - client.Send(F_RECEIVER_GET_RECEIVER_ROI); - client.setFnum(F_RECEIVER_GET_RECEIVER_ROI); - auto nPorts = client.Receive(); - std::vector retval(nPorts); - if (nPorts > 0) - client.Receive(retval); - if (nPorts != shm()->numUDPInterfaces) { + auto retval = sendToReceiverVarVector(F_RECEIVER_GET_RECEIVER_ROI); + auto nPorts = retval.size(); + if (static_cast(nPorts) != shm()->numUDPInterfaces) { throw RuntimeError( "Invalid number of rois: " + std::to_string(nPorts) + ". Expected: " + std::to_string(shm()->numUDPInterfaces)); } - LOG(logDEBUG1) << "ROI of Receiver" << moduleIndex << ": " - << ToString(retval); return retval; } void Module::setRxROI(const std::vector &portRois) { - LOG(logDEBUG) << "Sending to receiver " << moduleIndex - << " [roi: " << ToString(portRois) << ']'; - if (!shm()->useReceiverFlag) { - throw RuntimeError("No receiver to set ROI."); - } if ((int)portRois.size() != shm()->numUDPInterfaces) { throw RuntimeError( "Invalid number of ROIs: " + std::to_string(portRois.size()) + ". Expected: " + std::to_string(shm()->numUDPInterfaces)); } - // check number of ports - auto client = ReceiverSocket(shm()->rxHostname, shm()->rxTCPPort); - client.Send(F_RECEIVER_SET_RECEIVER_ROI); - client.setFnum(F_RECEIVER_SET_RECEIVER_ROI); - int size = static_cast(portRois.size()); - client.Send(size); - if (size > 0) - client.Send(portRois); - if (client.Receive() == FAIL) { - throw ReceiverError("Receiver " + std::to_string(moduleIndex) + - " returned error: " + client.readErrorMessage()); - } + sendToReceiverVarVector(F_RECEIVER_SET_RECEIVER_ROI, portRois); } std::vector Module::getRxROIMetadata() const { - LOG(logDEBUG1) << "Getting receiver ROI metadata for Module " - << moduleIndex; - // check number of ports - if (!shm()->useReceiverFlag) { - throw RuntimeError("No receiver to get ROI metadata."); - } - auto client = ReceiverSocket(shm()->rxHostname, shm()->rxTCPPort); - client.Send(F_RECEIVER_GET_ROI_METADATA); - client.setFnum(F_RECEIVER_GET_ROI_METADATA); - auto size = client.Receive(); - std::vector retval(size); - if (size > 0) - client.Receive(retval); - if (size == 0) { - throw RuntimeError("Invalid number of ROI metadata: " + - std::to_string(size) + ". Min: 1."); - } + auto retval = sendToReceiverVarVector(F_RECEIVER_GET_ROI_METADATA); + if (retval.size() == 0) + throw RuntimeError("Invalid number of ROI metadata: 0. Min: 1."); LOG(logDEBUG1) << "ROI metadata of Receiver: " << ToString(retval); return retval; } void Module::setRxROIMetadata(const std::vector &args) { - LOG(logDEBUG) << "Sending to receiver " << moduleIndex - << " [roi metadata: " << ToString(args) << ']'; - auto receiver = ReceiverSocket(shm()->rxHostname, shm()->rxTCPPort); - receiver.Send(F_RECEIVER_SET_RECEIVER_ROI_METADATA); - receiver.setFnum(F_RECEIVER_SET_RECEIVER_ROI_METADATA); - int size = static_cast(args.size()); - receiver.Send(size); - if (size > 0) - receiver.Send(args); - if (size < 1) { + if (args.size() < 1) { throw RuntimeError("Invalid number of ROI metadata: " + - std::to_string(size) + ". Min: 1."); - } - if (receiver.Receive() == FAIL) { - throw ReceiverError("Receiver " + std::to_string(moduleIndex) + - " returned error: " + receiver.readErrorMessage()); + std::to_string(args.size()) + ". Min: 1."); } + sendToReceiverVarVector(F_RECEIVER_SET_RECEIVER_ROI_METADATA, args); } // File @@ -1935,17 +1761,7 @@ void Module::setRateCorrection(int64_t t) { } void Module::sendReceiverRateCorrections(const std::vector &t) { - LOG(logDEBUG) << "Sending to receiver 0 [rate corrections: " << ToString(t) - << ']'; - auto receiver = ReceiverSocket(shm()->rxHostname, shm()->rxTCPPort); - receiver.Send(F_SET_RECEIVER_RATE_CORRECT); - receiver.setFnum(F_SET_RECEIVER_RATE_CORRECT); - receiver.Send(static_cast(t.size())); - receiver.Send(t); - if (receiver.Receive() == FAIL) { - throw ReceiverError("Receiver " + std::to_string(moduleIndex) + - " returned error: " + receiver.readErrorMessage()); - } + sendToReceiverVarVector(F_SET_RECEIVER_RATE_CORRECT, t); } bool Module::getInterruptSubframe() const { @@ -2189,51 +2005,42 @@ void Module::sendVetoPhoton(const int chipIndex, const std::vector &gainIndices, const std::vector &values) { const int nch = gainIndices.size(); - if (gainIndices.size() != values.size()) { - throw RuntimeError("Number of Gain Indices and values do not match! " - "Gain Indices size: " + - std::to_string(gainIndices.size()) + - ", values size: " + std::to_string(values.size())); + if (nch != static_cast(values.size())) { + std::ostringstream oss; + oss << "Number of Gain Indices and values do not match! Gain Indices " + "size: " + << nch << ", values size: " << values.size(); + throw RuntimeError(oss.str()); } LOG(logDEBUG1) << "Sending veto photon/file to detector [chip:" << chipIndex << ", nch:" << nch << "]"; - const int args[]{chipIndex, nch}; - auto client = DetectorSocket(shm()->hostname, shm()->controlPort); - client.Send(F_SET_VETO_PHOTON); - client.setFnum(F_SET_VETO_PHOTON); - client.Send(args); + auto client = createDetectorSocket(); + client.sendCommand(F_SET_VETO_PHOTON, args, sizeof(args)); client.Send(gainIndices); client.Send(values); - if (client.Receive() == FAIL) { - throw DetectorError("Detector " + std::to_string(moduleIndex) + - " returned error: " + client.readErrorMessage()); - } + client.readReply(nullptr, 0); } void Module::getVetoPhoton(const int chipIndex, const std::string &fname) const { LOG(logDEBUG1) << "Getting veto photon [" << chipIndex << "]\n"; - auto client = DetectorSocket(shm()->hostname, shm()->controlPort); - client.Send(F_GET_VETO_PHOTON); - client.setFnum(F_GET_VETO_PHOTON); - client.Send(chipIndex); - if (client.Receive() == FAIL) { - throw DetectorError("Detector " + std::to_string(moduleIndex) + - " returned error: " + client.readErrorMessage()); - } - - auto nch = client.Receive(); - if (nch != shm()->nChan.x) { - throw DetectorError("Could not get veto photon. Expected " + - std::to_string(shm()->nChan.x) + " channels, got " + - std::to_string(nch)); - } + auto client = createDetectorSocket(); + client.sendCommand(F_GET_VETO_PHOTON, &chipIndex, sizeof(chipIndex)); + int nch = 0; + client.readReply(&nch, sizeof(nch)); std::vector gainIndices(nch); std::vector values(nch); client.Receive(gainIndices); client.Receive(values); + if (nch != shm()->nChan.x) { + std::ostringstream oss; + oss << "Could not get veto photon. Expected " << shm()->nChan.x + << " channels, got " << nch; + throw DetectorError(oss.str()); + } + // save to file std::ofstream outfile(fname); if (!outfile) { @@ -2313,10 +2120,10 @@ void Module::setVetoPhoton(const int chipIndex, const int numPhotons, } // check size if ((int)gainIndices.size() != shm()->nChan.x) { - throw RuntimeError("Could not set veto photon. Invalid number of " - "entries in file. Expected " + - std::to_string(shm()->nChan.x) + ", read " + - std::to_string(gainIndices.size())); + std::ostringstream oss; + oss << "Could not set veto photon. Invalid number of entries in file. " + << "Expected " << shm()->nChan.x << ", read " << gainIndices.size(); + throw RuntimeError(oss.str()); } sendVetoPhoton(chipIndex, gainIndices, values); @@ -2733,17 +2540,13 @@ std::string Module::getPatternFileName() const { } void Module::setPattern(const Pattern &pat, const std::string &fname) { - auto client = DetectorSocket(shm()->hostname, shm()->controlPort); - client.Send(F_SET_PATTERN); - client.setFnum(F_SET_PATTERN); - client.Send(pat.data(), pat.size()); char args[MAX_STR_LENGTH]{}; strcpy_safe(args, fname.c_str()); + + auto client = createDetectorSocket(); + client.sendCommand(F_SET_PATTERN, pat.data(), pat.size()); client.Send(args); - if (client.Receive() == FAIL) { - throw DetectorError("Detector " + std::to_string(moduleIndex) + - " returned error: " + client.readErrorMessage()); - } + client.readReply(nullptr, 0); } Pattern Module::getPattern() { @@ -2846,69 +2649,44 @@ void Module::startPattern() { sendToDetector(F_START_PATTERN); } // Json Header specific std::map Module::getAdditionalJsonHeader() const { - // TODO, refactor this function with a more robust sending. - // Now assuming whitespace separated key value - if (!shm()->useReceiverFlag) { - throw RuntimeError("Set rx_hostname first to use receiver parameters " - "(zmq json header)"); - } - auto client = ReceiverSocket(shm()->rxHostname, shm()->rxTCPPort); - client.Send(F_GET_ADDITIONAL_JSON_HEADER); - client.setFnum(F_GET_ADDITIONAL_JSON_HEADER); - if (client.Receive() == FAIL) { - throw ReceiverError("Receiver " + std::to_string(moduleIndex) + - " returned error: " + client.readErrorMessage()); - } else { - auto size = client.Receive(); - std::string buff(size, '\0'); - std::map retval; - if (size > 0) { - client.Receive(&buff[0], buff.size()); - std::istringstream iss(buff); - std::string key, value; - while (iss >> key) { - iss >> value; - retval[key] = value; - } - } - LOG(logDEBUG) << "Getting additional json header " << ToString(retval); - return retval; + auto vec = sendToReceiverVarVector(F_GET_ADDITIONAL_JSON_HEADER); + + // convert vector to string + std::string longString(vec.begin(), vec.end()); + // convert string (space separated) to map of key-value pairs + std::map retval; + std::istringstream iss(longString); + std::string key, value; + while (iss >> key) { + iss >> value; + retval[key] = value; } + LOG(logDEBUG) << "Getting additional json header " << ToString(retval); + return retval; } void Module::setAdditionalJsonHeader( const std::map &jsonHeader) { - if (!shm()->useReceiverFlag) { - throw RuntimeError("Set rx_hostname first to use receiver parameters " - "(zmq json header)"); - } + // validate for (auto &it : jsonHeader) { - if (it.first.empty() || it.first.length() > SHORT_STR_LENGTH || - it.second.length() > SHORT_STR_LENGTH) { - throw RuntimeError( - it.first + " or " + it.second + - " pair has invalid size. " - "Key cannot be empty. Both can have max 20 characters"); + auto key = it.first; + auto value = it.second; + if (key.empty() || key.length() > SHORT_STR_LENGTH || + value.length() > SHORT_STR_LENGTH) { + throw RuntimeError(key + " or " + value + + " pair has invalid size. Key cannot be empty. " + "Both can have max 20 characters"); } } + // convert map to string (space separated) std::ostringstream oss; for (auto &it : jsonHeader) oss << it.first << ' ' << it.second << ' '; - auto buff = oss.str(); - const auto size = static_cast(buff.size()); - LOG(logDEBUG) << "Sending to receiver additional json header " - << ToString(jsonHeader); - auto client = ReceiverSocket(shm()->rxHostname, shm()->rxTCPPort); - client.Send(F_SET_ADDITIONAL_JSON_HEADER); - client.setFnum(F_SET_ADDITIONAL_JSON_HEADER); - client.Send(size); - if (size > 0) - client.Send(&buff[0], buff.size()); + auto longString = oss.str(); + // convert string to vector to send over socket (variable vector impl) + std::vector args(longString.begin(), longString.end()); - if (client.Receive() == FAIL) { - throw ReceiverError("Receiver " + std::to_string(moduleIndex) + - " returned error: " + client.readErrorMessage()); - } + sendToReceiverVarVector(F_SET_ADDITIONAL_JSON_HEADER, args); } std::string Module::getAdditionalJsonParameter(const std::string &key) const { @@ -3090,23 +2868,12 @@ IpAddr Module::getLastClientIP() const { } std::string Module::executeCommand(const std::string &cmd) { - char arg[MAX_STR_LENGTH]{}; - char retval[MAX_STR_LENGTH]{}; - strcpy_safe(arg, cmd.c_str()); LOG(logINFO) << "Module " << moduleIndex << " (" << shm()->hostname << "): Sending command " << cmd; - auto client = DetectorSocket(shm()->hostname, shm()->controlPort); - client.Send(F_EXEC_COMMAND); - client.setFnum(F_EXEC_COMMAND); - client.Send(arg); - if (client.Receive() == FAIL) { - std::cout << '\n'; - std::ostringstream os; - os << "Module " << moduleIndex << " (" << shm()->hostname << ")" - << " returned error: " << client.readErrorMessage(); - throw DetectorError(os.str()); - } - client.Receive(retval); + char args[MAX_STR_LENGTH]{}; + char retval[MAX_STR_LENGTH]{}; + strcpy_safe(args, cmd.c_str()); + sendToDetector(F_EXEC_COMMAND, args, retval); LOG(logINFO) << "Module " << moduleIndex << " (" << shm()->hostname << "): command executed"; return retval; @@ -3126,14 +2893,18 @@ int64_t Module::getMeasurementTime() const { // private -void Module::checkArgs(const void *args, size_t args_size, void *retval, - size_t retval_size) const { +void Module::checkArgs(const void *args, size_t args_size) const { if (args == nullptr && args_size != 0) throw RuntimeError( "Passed nullptr as args to Send function but size is not 0"); if (args != nullptr && args_size == 0) throw RuntimeError( "Passed size 0 to Send function but args is not nullptr"); +} + +void Module::checkArgs(const void *args, size_t args_size, void *retval, + size_t retval_size) const { + checkArgs(args, args_size); if (retval == nullptr && retval_size != 0) throw RuntimeError( "Passed nullptr as retval to Send function but size is not 0"); @@ -3150,13 +2921,42 @@ void Module::checkArgs(const void *args, size_t args_size, void *retval, static_assert(!std::is_same::value, \ "nullptr_t type is incompatible with templated " DST); +DetectorSocket Module::createDetectorSocket() const { + return DetectorSocket(shm()->hostname, shm()->controlPort); +} + +template +void Module::sendToDetectorVarVector(int fnum, + const std::vector &args) const { + LOG(logDEBUG1) << "Sending to Detector: [" + << getFunctionNameFromEnum(static_cast(fnum)) + << ", std::vector<" << typeid(Arg).name() << ">, nullptr, 0," + << "]"; + auto client = createDetectorSocket(); + client.sendCommandVariableSize(fnum, args, nullptr, 0); + client.close(); +} + +template +std::vector Module::sendToDetectorVarVector(int fnum) const { + LOG(logDEBUG1) << "Sending to Detector: [" + << getFunctionNameFromEnum(static_cast(fnum)) + << ", nullptr, 0, std::vector<" << typeid(Ret).name() + << ">]"; + std::vector retval; + auto client = createDetectorSocket(); + client.sendCommandVariableSize(fnum, nullptr, 0, retval); + client.close(); + return retval; +} + void Module::sendToDetector(int fnum, const void *args, size_t args_size, void *retval, size_t retval_size) const { // This is the only function that actually sends data to the detector // the other versions use templates to deduce sizes and create // the return type checkArgs(args, args_size, retval, retval_size); - auto client = DetectorSocket(shm()->hostname, shm()->controlPort); + auto client = createDetectorSocket(); client.sendCommandThenRead(fnum, args, args_size, retval, retval_size); client.close(); } @@ -3379,6 +3179,47 @@ Ret Module::sendToDetectorStop(int fnum, const Arg &args) { //-------------------------------------------------------------- sendToReceiver +ReceiverSocket Module::createReceiverSocket() const { + return ReceiverSocket(shm()->rxHostname, shm()->rxTCPPort); +} + +template +void Module::sendToReceiverVarVector(int fnum, + const std::vector &args) const { + LOG(logDEBUG1) << "Sending to Receiver: [" + << getFunctionNameFromEnum(static_cast(fnum)) + << ", std::vector<" << typeid(Arg).name() << ">, nullptr, 0," + << "]"; + if (!shm()->useReceiverFlag) { + std::ostringstream oss; + oss << "Set rx_hostname first to use receiver parameters, "; + oss << getFunctionNameFromEnum(static_cast(fnum)); + throw RuntimeError(oss.str()); + } + auto receiver = createReceiverSocket(); + receiver.sendCommandVariableSize(fnum, args, nullptr, 0); + receiver.close(); +} + +template +std::vector Module::sendToReceiverVarVector(int fnum) const { + LOG(logDEBUG1) << "Sending to Receiver: [" + << getFunctionNameFromEnum(static_cast(fnum)) + << ", nullptr, 0, std::vector<" << typeid(Ret).name() + << ">]"; + if (!shm()->useReceiverFlag) { + std::ostringstream oss; + oss << "Set rx_hostname first to use receiver parameters, "; + oss << getFunctionNameFromEnum(static_cast(fnum)); + throw RuntimeError(oss.str()); + } + std::vector retval; + auto receiver = createReceiverSocket(); + receiver.sendCommandVariableSize(fnum, nullptr, 0, retval); + receiver.close(); + return retval; +} + void Module::sendToReceiver(int fnum, const void *args, size_t args_size, void *retval, size_t retval_size) const { // This is the only function that actually sends data to the receiver @@ -3391,7 +3232,7 @@ void Module::sendToReceiver(int fnum, const void *args, size_t args_size, throw RuntimeError(oss.str()); } checkArgs(args, args_size, retval, retval_size); - auto receiver = ReceiverSocket(shm()->rxHostname, shm()->rxTCPPort); + auto receiver = createReceiverSocket(); receiver.sendCommandThenRead(fnum, args, args_size, retval, retval_size); receiver.close(); } @@ -3707,26 +3548,18 @@ void Module::setModule(sls_detector_module &module, bool trimbits) { "these have been replaced with 0/200 or 2800/2400."; } } - auto client = DetectorSocket(shm()->hostname, shm()->controlPort); - client.Send(F_SET_MODULE); - client.setFnum(F_SET_MODULE); + auto client = createDetectorSocket(); + client.sendCommand(F_SET_MODULE, nullptr, 0); sendModule(&module, client); - if (client.Receive() == FAIL) { - throw DetectorError("Module " + std::to_string(moduleIndex) + - " returned error: " + client.readErrorMessage()); - } + client.readReply(nullptr, 0); } sls_detector_module Module::getModule() { LOG(logDEBUG1) << "Getting module"; sls_detector_module module(shm()->detType); - auto client = DetectorSocket(shm()->hostname, shm()->controlPort); - client.Send(F_GET_MODULE); - client.setFnum(F_GET_MODULE); - if (client.Receive() == FAIL) { - throw DetectorError("Module " + std::to_string(moduleIndex) + - " returned error: " + client.readErrorMessage()); - } + auto client = createDetectorSocket(); + client.sendCommand(F_GET_MODULE, nullptr, 0); + client.readReply(nullptr, 0); receiveModule(&module, client); return module; } @@ -4063,7 +3896,7 @@ void Module::sendProgram(bool blackfin, std::vector buffer, << "): Sending " << functionType; // send fnum and filesize - auto client = DetectorSocket(shm()->hostname, shm()->controlPort); + auto client = createDetectorSocket(); client.Send(functionEnum); uint64_t filesize = buffer.size(); client.Send(filesize); @@ -4187,47 +4020,22 @@ void Module::simulatingActivityinDetector(const std::string &functionType, std::vector Module::readSpi(int chip_id, int register_id, int n_bytes) const { - auto client = DetectorSocket(shm()->hostname, shm()->controlPort); - client.Send(F_SPI_READ); - client.setFnum(F_SPI_READ); - client.Send(chip_id); - client.Send(register_id); - client.Send(n_bytes); - - if (client.Receive() == FAIL) { - std::ostringstream os; - os << "Module " << moduleIndex << " (" << shm()->hostname << ")" - << " returned error: " << client.readErrorMessage(); - throw DetectorError(os.str()); - } - - std::vector data(n_bytes); - client.Receive(data); - return data; + int args[] = {chip_id, register_id, n_bytes}; + return sendToDetector>(F_SPI_READ, args); } std::vector Module::writeSpi(int chip_id, int register_id, const std::vector &data) { - auto client = DetectorSocket(shm()->hostname, shm()->controlPort); - client.Send(F_SPI_WRITE); - client.setFnum(F_SPI_WRITE); - client.Send(chip_id); - client.Send(register_id); - client.Send(static_cast(data.size())); + int count = static_cast(data.size()); + int args[] = {chip_id, register_id, count}; + auto client = createDetectorSocket(); + client.sendCommand(F_SPI_WRITE, args, sizeof(args)); client.Send(data); - - if (client.Receive() == FAIL) { - std::ostringstream os; - os << "Module " << moduleIndex << " (" << shm()->hostname << ")" - << " returned error: " << client.readErrorMessage(); - throw DetectorError(os.str()); - } - // Read the output from the SPI write. This contains the data before the - // write. - std::vector ret(data.size()); - client.Receive(ret); - return ret; + // write + std::vector retval(data.size()); + client.readReply(retval.data(), retval.size()); + return retval; } } // namespace sls diff --git a/slsDetectorSoftware/src/Module.h b/slsDetectorSoftware/src/Module.h index 1f5097530..c1bfa046d 100644 --- a/slsDetectorSoftware/src/Module.h +++ b/slsDetectorSoftware/src/Module.h @@ -626,9 +626,18 @@ class Module : public virtual slsDetectorDefs { private: std::string getReceiverLongVersion() const; + void checkArgs(const void *args, size_t args_size) const; void checkArgs(const void *args, size_t args_size, void *retval, size_t retval_size) const; + DetectorSocket createDetectorSocket() const; + + template + void sendToDetectorVarVector(int fnum, const std::vector &args) const; + + template + std::vector sendToDetectorVarVector(int fnum) const; + /** * Send function parameters to detector (control server) * @param fnum function enum @@ -674,6 +683,9 @@ class Module : public virtual slsDetectorDefs { Ret sendToDetector(int fnum, const Arg &args) const; /** Send function parameters to detector (stop server) */ + + DetectorSocket createDetectorStopSocket() const; + void sendToDetectorStop(int fnum, const void *args, size_t args_size, void *retval, size_t retval_size); @@ -713,6 +725,15 @@ class Module : public virtual slsDetectorDefs { Ret sendToDetectorStop(int fnum, const Arg &args) const; /** Send function parameters to receiver */ + + ReceiverSocket createReceiverSocket() const; + + template + void sendToReceiverVarVector(int fnum, const std::vector &args) const; + + template + std::vector sendToReceiverVarVector(int fnum) const; + void sendToReceiver(int fnum, const void *args, size_t args_size, void *retval, size_t retval_size); diff --git a/slsReceiverSoftware/src/ClientInterface.cpp b/slsReceiverSoftware/src/ClientInterface.cpp index 4b14004c7..9cc94ef3b 100644 --- a/slsReceiverSoftware/src/ClientInterface.cpp +++ b/slsReceiverSoftware/src/ClientInterface.cpp @@ -831,32 +831,17 @@ int ClientInterface::get_file_index(Interface &socket) { int ClientInterface::get_frame_index(Interface &socket) { auto retval = impl()->getCurrentFrameIndex(); - LOG(logDEBUG1) << "frames index:" << ToString(retval); - auto size = static_cast(retval.size()); - socket.Send(OK); - socket.Send(size); - socket.Send(retval); - return OK; + return socket.sendVariableResult(retval); } int ClientInterface::get_missing_packets(Interface &socket) { auto missing_packets = impl()->getNumMissingPackets(); - LOG(logDEBUG1) << "missing packets:" << ToString(missing_packets); - auto size = static_cast(missing_packets.size()); - socket.Send(OK); - socket.Send(size); - socket.Send(missing_packets); - return OK; + return socket.sendVariableResult(missing_packets); } int ClientInterface::get_frames_caught(Interface &socket) { auto retval = impl()->getFramesCaught(); - LOG(logDEBUG1) << "frames caught:" << ToString(retval); - auto size = static_cast(retval.size()); - socket.Send(OK); - socket.Send(size); - socket.Send(retval); - return OK; + return socket.sendVariableResult(retval); } int ClientInterface::set_file_write(Interface &socket) { @@ -1113,37 +1098,39 @@ int ClientInterface::stream_rx_dummy_header(Interface &socket) { } int ClientInterface::set_additional_json_header(Interface &socket) { - std::map json; - auto size = socket.Receive(); - if (size > 0) { - std::string buff(size, '\0'); - socket.Receive(&buff[0], buff.size()); - std::istringstream iss(buff); - std::string key, value; - while (iss >> key) { - iss >> value; - json[key] = value; - } - } // verifyIdle(socket); allowing it to be set on the fly - LOG(logDEBUG1) << "Setting additional json header: " << ToString(json); - impl()->setAdditionalJsonHeader(json); + + auto vec = socket.receiveVariableArgs>(); + // convert vector to string (space separated) + std::string longString(vec.begin(), vec.end()); + // convert string to map of key-value pairs + std::map args; + std::istringstream iss(longString); + std::string key, value; + while (iss >> key) { + iss >> value; + args[key] = value; + } + LOG(logDEBUG1) << "Setting additional json header: " << ToString(args); + + impl()->setAdditionalJsonHeader(args); return socket.Send(OK); } int ClientInterface::get_additional_json_header(Interface &socket) { std::map json = impl()->getAdditionalJsonHeader(); LOG(logDEBUG1) << "additional json header:" << ToString(json); + + // convert map to string (space separated) to send over socket std::ostringstream oss; for (auto &it : json) { oss << it.first << ' ' << it.second << ' '; } - auto buff = oss.str(); - auto size = static_cast(buff.size()); - socket.sendResult(size); - if (size > 0) - socket.Send(buff); - return OK; + auto longString = oss.str(); + + // conver to vector to send over socket (variable vector length impl) + std::vector retval(longString.begin(), longString.end()); + return socket.sendVariableResult(retval); } int ClientInterface::set_udp_socket_buffer_size(Interface &socket) { @@ -1612,16 +1599,13 @@ int ClientInterface::set_streaming_start_fnum(Interface &socket) { } int ClientInterface::set_rate_correct(Interface &socket) { - auto index = socket.Receive(); - if (index <= 0) { - throw RuntimeError("Invalid number of rate correction values: " + - std::to_string(index)); - } - LOG(logDEBUG) << "Number of detectors for rate correction: " << index; - std::vector t(index); - socket.Receive(t); verifyIdle(socket); - LOG(logINFO) << "Setting rate corrections[" << index << ']'; + + auto t = socket.receiveVariableArgs>(); + if (t.size() <= 0) + throw RuntimeError("Invalid number of rate correction values: " + + std::to_string(t.size())); + LOG(logINFO) << "Setting rate corrections[" << t.size() << ']'; impl()->setRateCorrections(t); return socket.Send(OK); } @@ -1748,58 +1732,41 @@ int ClientInterface::set_arping(Interface &socket) { int ClientInterface::get_receiver_roi(Interface &socket) { auto retvals = impl()->getPortROIs(); LOG(logDEBUG1) << "Receiver roi retval:" << ToString(retvals); - auto size = static_cast(retvals.size()); - if (size != impl()->getNumberofUDPInterfaces()) { - throw RuntimeError("Invalid number of ROIs received: " + - std::to_string(size) + ". Expected: " + - std::to_string(impl()->getNumberofUDPInterfaces())); - } - socket.Send(size); - if (size > 0) - socket.Send(retvals); - return OK; + return socket.sendVariableResult(retvals); } int ClientInterface::set_receiver_roi(Interface &socket) { - auto roiSize = socket.Receive(); - std::vector args(roiSize); - if (roiSize > 0) { - socket.Receive(args); - } - if (roiSize != impl()->getNumberofUDPInterfaces()) { - throw RuntimeError("Invalid number of ROIs received: " + - std::to_string(roiSize) + ". Expected: " + - std::to_string(impl()->getNumberofUDPInterfaces())); - } if (detType == CHIPTESTBOARD || detType == XILINX_CHIPTESTBOARD) functionNotImplemented(); - LOG(logDEBUG1) << "Set Receiver ROI: " << ToString(args); verifyIdle(socket); + + auto args = socket.receiveVariableArgs>(); + auto numInterfaces = impl()->getNumberofUDPInterfaces(); + if (static_cast(args.size()) != numInterfaces) { + std::ostringstream oss; + oss << "Invalid number of ROIs received: " << args.size() + << ". Expected: " << numInterfaces; + throw RuntimeError(oss.str()); + } + LOG(logDEBUG1) << "Set Receiver ROI: " << ToString(args); try { impl()->setPortROIs(args); } catch (const std::exception &e) { throw RuntimeError("Could not set Receiver ROI [" + std::string(e.what()) + ']'); } - return socket.Send(OK); } int ClientInterface::set_receiver_roi_metadata(Interface &socket) { - auto roiSize = socket.Receive(); - LOG(logDEBUG1) << "Number of ReceiverROI metadata: " << roiSize; - if (roiSize < 1) { - throw RuntimeError("Invalid number of ROIs received: " + - std::to_string(roiSize) + ". Min: 1."); - } - std::vector rois(roiSize); - if (roiSize > 0) { - socket.Receive(rois); - } if (detType == CHIPTESTBOARD || detType == XILINX_CHIPTESTBOARD) functionNotImplemented(); verifyIdle(socket); - LOG(logINFO) << "Setting ReceiverROI metadata[" << roiSize << ']'; + + auto rois = socket.receiveVariableArgs>(); + if (rois.size() < 1) + throw RuntimeError("Invalid number of ROI metadata: " + + std::to_string(rois.size()) + ". Min: 1."); try { impl()->setMultiROIMetadata(rois); } catch (const std::exception &e) { @@ -1896,12 +1863,7 @@ int ClientInterface::get_roi_metadata(Interface &socket) { if (detType == CHIPTESTBOARD || detType == XILINX_CHIPTESTBOARD) functionNotImplemented(); auto retvals = impl()->getMultiROIMetadata(); - LOG(logDEBUG1) << "Receiver ROI metadata retval:" << ToString(retvals); - auto size = static_cast(retvals.size()); - socket.Send(size); - if (size > 0) - socket.Send(retvals); - return OK; + return socket.sendVariableResult(retvals); } int ClientInterface::set_readout_speed(Interface &socket) { @@ -1934,16 +1896,9 @@ int ClientInterface::set_readout_speed(Interface &socket) { } int ClientInterface::set_udp_port_disable_meta(Interface &socket) { - auto nports = socket.Receive(); - std::vector portsDisabled; - if (nports > 0) { - portsDisabled.resize(nports); - socket.Receive(portsDisabled); - LOG(logDEBUG1) << "Disabled Ports Metadata:" << ToString(portsDisabled); - } verifyIdle(socket); + auto portsDisabled = socket.receiveVariableArgs>(); try { - impl()->setUDPPortsDisabledMetadata(portsDisabled); } catch (const std::exception &e) { throw RuntimeError("Could not update UDP ports disabled metadata [" + @@ -1954,14 +1909,7 @@ int ClientInterface::set_udp_port_disable_meta(Interface &socket) { int ClientInterface::get_udp_port_disable_meta(Interface &socket) { auto retvals = impl()->getUDPPortsDisabledMetadata(); - LOG(logDEBUG1) << "Receiver disabled udp ports retval:" - << ToString(retvals); - socket.Send(OK); - auto size = static_cast(retvals.size()); - socket.Send(size); - if (size > 0) - socket.Send(retvals); - return OK; + return socket.sendVariableResult(retvals); } } // namespace sls diff --git a/slsSupportLib/include/sls/ClientSocket.h b/slsSupportLib/include/sls/ClientSocket.h index 4ef8e5da4..1e9bedd8f 100644 --- a/slsSupportLib/include/sls/ClientSocket.h +++ b/slsSupportLib/include/sls/ClientSocket.h @@ -14,13 +14,36 @@ class ClientSocket : public DataSocket { ClientSocket(std::string stype, const std::string &hostname, uint16_t port_number); ClientSocket(std::string stype, struct sockaddr_in addr); - int sendCommandThenRead(int fnum, const void *args, size_t args_size, - void *retval, size_t retval_size); - + void sendCommandThenRead(int fnum, const void *args, size_t args_size, + void *retval, size_t retval_size); std::string readErrorMessage(); + template + void sendCommandVariableSize(int fnum, const std::vector &args, + void *retval, size_t retval_size) { + int count = args.size(); + sendCommand(fnum, &count, sizeof(count)); + if (count > 0) { + Send(args); + } + readReply(retval, retval_size); + } + + template + void sendCommandVariableSize(int fnum, const void *args, size_t args_size, + std::vector &retval) { + sendCommand(fnum, args, args_size); + int count = 0; + readReply(&count, sizeof(count)); + retval.resize(count); + if (count > 0) { + Receive(retval); + } + } + void sendCommand(int fnum, const void *args, size_t args_size); + void readReply(void *retval, size_t retval_size); + private: - void readReply(int &ret, void *retval, size_t retval_size); [[noreturn]] void throwError(const std::string &msg) const; struct sockaddr_in serverAddr {}; std::string socketType; diff --git a/slsSupportLib/include/sls/ServerInterface.h b/slsSupportLib/include/sls/ServerInterface.h index d4ed04576..70f30debc 100644 --- a/slsSupportLib/include/sls/ServerInterface.h +++ b/slsSupportLib/include/sls/ServerInterface.h @@ -30,6 +30,25 @@ class ServerInterface : public DataSocket { Send(retval); return defs::OK; } + + template int sendVariableResult(T &&retval) { + int count = static_cast(retval.size()); + Send(defs::OK); + Send(count); + if (count > 0) + Send(retval); + return defs::OK; + } + + template T receiveVariableArgs() { + int count = 0; + Receive(count); + T retval(static_cast(count)); + if (count > 0) { + Receive(retval); + } + return retval; + } }; } // namespace sls \ No newline at end of file diff --git a/slsSupportLib/src/ClientSocket.cpp b/slsSupportLib/src/ClientSocket.cpp index fe62d8208..62dfb2d19 100644 --- a/slsSupportLib/src/ClientSocket.cpp +++ b/slsSupportLib/src/ClientSocket.cpp @@ -73,20 +73,23 @@ void ClientSocket::throwError(const std::string &msg) const { } } -int ClientSocket::sendCommandThenRead(int fnum, const void *args, - size_t args_size, void *retval, - size_t retval_size) { - int ret = slsDetectorDefs::FAIL; - Send(&fnum, sizeof(fnum)); - setFnum(fnum); - Send(args, args_size); - readReply(ret, retval, retval_size); - return ret; +void ClientSocket::sendCommandThenRead(int fnum, const void *args, + size_t args_size, void *retval, + size_t retval_size) { + sendCommand(fnum, args, args_size); + readReply(retval, retval_size); } -void ClientSocket::readReply(int &ret, void *retval, size_t retval_size) { +void ClientSocket::sendCommand(int fnum, const void *args, size_t args_size) { + Send(fnum); + setFnum(fnum); + Send(args, args_size); +} + +void ClientSocket::readReply(void *retval, size_t retval_size) { try { + int ret = slsDetectorDefs::FAIL; Receive(&ret, sizeof(ret)); if (ret == slsDetectorDefs::FAIL) { std::string mess = readErrorMessage(); diff --git a/slsSupportLib/tests/test-Sockets.cpp b/slsSupportLib/tests/test-Sockets.cpp index 897ed4e65..01c53877a 100644 --- a/slsSupportLib/tests/test-Sockets.cpp +++ b/slsSupportLib/tests/test-Sockets.cpp @@ -231,14 +231,13 @@ TEST_CASE("Using DetectorSocket to talk to a Server Socket", "[support]") { auto client = DetectorSocket("localhost", port); int retval = 0; - int ret = client.sendCommandThenRead(fnum, &arg, sizeof(arg), &retval, - sizeof(retval)); + CHECK_NOTHROW(client.sendCommandThenRead(fnum, &arg, sizeof(arg), &retval, + sizeof(retval))); client.close(); auto server_received = s.get(); // Client got OK and the expected return value back from the server - CHECK(ret == slsDetectorDefs::OK); CHECK(retval == arg * 2); // Server received the function number and argument we sent CHECK(server_received.first == fnum);