From cf8b0de433fc4d4533e4776b7e139bed875fad9d Mon Sep 17 00:00:00 2001 From: Dhanya Thattil Date: Mon, 28 May 2018 19:11:34 +0200 Subject: [PATCH] slsReceiver, slsDetector, eiger and jungfrau server: client checks firmware and software an dreceiver compatibility for each time shared memory is cleaned up --- slsDetectorSoftware/commonFiles/error_defs.h | 4 + .../commonFiles/sls_detector_defs.h | 4 +- .../commonFiles/sls_detector_funcs.h | 2 + slsDetectorSoftware/commonFiles/versionAPI.h | 6 +- .../bin/eigerDetectorServer_developer | Bin 297773 -> 302050 bytes .../eigerDetectorServer/gitInfo.txt | 10 +- .../eigerDetectorServer/gitInfoEiger.h | 8 +- .../slsDetectorFunctionList.c | 76 +++++++--- .../eigerDetectorServer/updateAPIVersion.sh | 4 +- .../eigerDetectorServer/versionAPI.h | 1 + .../updateAPIVersion.sh | 4 +- .../gotthardDetectorServer/versionAPI.h | 1 + .../bin/jungfrauDetectorServer_developer | Bin 114264 -> 116212 bytes .../jungfrauDetectorServer/gitInfo.txt | 10 +- .../jungfrauDetectorServer/gitInfoJungfrau.h | 8 +- .../slsDetectorFunctionList.c | 91 +++++++++--- .../slsDetectorServer_defs.h | 2 +- .../updateAPIVersion.sh | 4 +- .../jungfrauDetectorServer/versionAPI.h | 1 + .../multiSlsDetector/multiSlsDetector.cpp | 39 +++++ .../multiSlsDetector/multiSlsDetector.h | 8 + .../slsDetector/slsDetector.cpp | 138 +++++++++++++++++- slsDetectorSoftware/slsDetector/slsDetector.h | 19 ++- .../slsDetector/slsDetectorCommand.cpp | 36 +++++ .../slsDetector/slsDetectorUtils.h | 8 + .../slsDetectorFunctionList.h | 5 + .../slsDetectorServer_funcs.c | 101 ++++++++++++- .../slsDetectorServer_funcs.h | 1 + .../receiverInterface.cpp | 43 ++++-- slsDetectorSoftware/threadFiles/Task.h | 6 +- .../include/slsReceiverTCPIPInterface.h | 4 + .../include/sls_receiver_funcs.h | 2 +- slsReceiverSoftware/include/versionAPI.h | 1 + .../src/UDPStandardImplementation.cpp | 2 +- .../src/slsReceiverTCPIPInterface.cpp | 82 +++++++++-- slsReceiverSoftware/updateAPIVersion.sh | 7 + 36 files changed, 633 insertions(+), 105 deletions(-) create mode 120000 slsDetectorSoftware/eigerDetectorServer/versionAPI.h create mode 120000 slsDetectorSoftware/gotthardDetectorServer/versionAPI.h create mode 120000 slsDetectorSoftware/jungfrauDetectorServer/versionAPI.h create mode 120000 slsReceiverSoftware/include/versionAPI.h create mode 100755 slsReceiverSoftware/updateAPIVersion.sh diff --git a/slsDetectorSoftware/commonFiles/error_defs.h b/slsDetectorSoftware/commonFiles/error_defs.h index 740125b06..880a9e154 100644 --- a/slsDetectorSoftware/commonFiles/error_defs.h +++ b/slsDetectorSoftware/commonFiles/error_defs.h @@ -51,6 +51,7 @@ #define PREPARE_ACQUISITION 0x0000100000000000ULL #define CLEANUP_ACQUISITION 0x0000080000000000ULL #define REGISER_WRITE_READ 0x0000040000000000ULL +#define VERSION_COMPATIBILITY 0x0000020000000000ULL // 0xFFFFFF0000000000ULL // 0x000000FFFFFFFFFFULL @@ -170,6 +171,9 @@ public: if(slsErrorMask®ISER_WRITE_READ) retval.append("Could not read/write register in detector\n"); + if(slsErrorMask&VERSION_COMPATIBILITY) + retval.append("Incompatible versions with detector or receiver. Please check log for more details.\n"); + if(slsErrorMask&COULD_NOT_CONFIGURE_MAC) diff --git a/slsDetectorSoftware/commonFiles/sls_detector_defs.h b/slsDetectorSoftware/commonFiles/sls_detector_defs.h index 465ee4956..292a2f415 100755 --- a/slsDetectorSoftware/commonFiles/sls_detector_defs.h +++ b/slsDetectorSoftware/commonFiles/sls_detector_defs.h @@ -291,7 +291,9 @@ enum idMode{ DETECTOR_SOFTWARE_VERSION, /**1y(_!=2{)zFTHrKN>k?ZJW$6n4=t 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 MC7#4;$JEIG1)~Img#Z8m delta 61048 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 diff --git a/slsDetectorSoftware/eigerDetectorServer/gitInfo.txt b/slsDetectorSoftware/eigerDetectorServer/gitInfo.txt index 661df0b14..c6a6c8e0e 100644 --- a/slsDetectorSoftware/eigerDetectorServer/gitInfo.txt +++ b/slsDetectorSoftware/eigerDetectorServer/gitInfo.txt @@ -1,9 +1,9 @@ Path: slsDetectorsPackage/slsDetectorSoftware/eigerDetectorServer URL: origin git@github.com:slsdetectorgroup/slsDetectorPackage.git Repository Root: origin git@github.com:slsdetectorgroup/slsDetectorPackage.git -Repsitory UUID: cb635d800a5e1de6cf3330f03a98ffc382879cf3 -Revision: 339 -Branch: mergevirtual +Repsitory UUID: 4d4e4a4ce7a91af094251ed0903575ba7e73ef5f +Revision: 341 +Branch: versioning Last Changed Author: Dhanya_Thattil -Last Changed Rev: 3832 -Last Changed Date: 2018-05-23 11:11:12.000000002 +0200 ./Makefile.virtual +Last Changed Rev: 3847 +Last Changed Date: 2018-05-28 18:02:50.000000002 +0200 ./xparameters.h diff --git a/slsDetectorSoftware/eigerDetectorServer/gitInfoEiger.h b/slsDetectorSoftware/eigerDetectorServer/gitInfoEiger.h index 5f8f69d4f..4b229b7c6 100644 --- a/slsDetectorSoftware/eigerDetectorServer/gitInfoEiger.h +++ b/slsDetectorSoftware/eigerDetectorServer/gitInfoEiger.h @@ -1,6 +1,6 @@ #define GITURL "git@github.com:slsdetectorgroup/slsDetectorPackage.git" -#define GITREPUUID "cb635d800a5e1de6cf3330f03a98ffc382879cf3" +#define GITREPUUID "4d4e4a4ce7a91af094251ed0903575ba7e73ef5f" #define GITAUTH "Dhanya_Thattil" -#define GITREV 0x3832 -#define GITDATE 0x20180523 -#define GITBRANCH "mergevirtual" +#define GITREV 0x3847 +#define GITDATE 0x20180528 +#define GITBRANCH "versioning" diff --git a/slsDetectorSoftware/eigerDetectorServer/slsDetectorFunctionList.c b/slsDetectorSoftware/eigerDetectorServer/slsDetectorFunctionList.c index 9fad0fde6..4249cc815 100644 --- a/slsDetectorSoftware/eigerDetectorServer/slsDetectorFunctionList.c +++ b/slsDetectorSoftware/eigerDetectorServer/slsDetectorFunctionList.c @@ -14,6 +14,7 @@ #include "gitInfoEiger.h" #include "FebControl.h" #include "Beb.h" +#include "versionAPI.h" #endif int default_tau_from_file= -1; @@ -89,18 +90,32 @@ int normal = 0; uint32_t detid = 0; #endif - - - - /* basic tests */ +int firmware_compatibility = OK; +int firmware_check_done = 0; +char firmware_message[MAX_STR_LENGTH]; + + +int isFirmwareCheckDone() { + return firmware_check_done; +} + +int getFirmwareCheckResult(char** mess) { + *mess = firmware_message; + return firmware_compatibility; +} + void checkFirmwareCompatibility(int flag){ + firmware_compatibility = OK; + firmware_check_done = 0; + memset(firmware_message, 0, MAX_STR_LENGTH); #ifdef VIRTUAL cprintf(BLUE,"\n\n" "********************************************************\n" "***************** EIGER Virtual Server *****************\n" "********************************************************\n"); + firmware_check_done = 1; return; #endif uint32_t ipadd = getDetectorIP(); @@ -108,6 +123,7 @@ void checkFirmwareCompatibility(int flag){ int64_t fwversion = getDetectorId(DETECTOR_FIRMWARE_VERSION); int64_t swversion = getDetectorId(DETECTOR_SOFTWARE_VERSION); int64_t sw_fw_apiversion = getDetectorId(SOFTWARE_FIRMWARE_API_VERSION); + int64_t client_sw_apiversion = getDetectorId(CLIENT_SOFTWARE_API_VERSION); cprintf(BLUE,"\n\n" "********************************************************\n" @@ -120,37 +136,61 @@ void checkFirmwareCompatibility(int flag){ "Firmware Version:\t\t %lld\n" "Software Version:\t\t %llx\n" "F/w-S/w API Version:\t\t %lld\n" - "Required Firmware Version:\t %d\n\n" + "Required Firmware Version:\t %d\n" + "Client-Software API Version:\t 0x%llx\n" + "\n" "********************************************************\n", (unsigned int)ipadd, (long long unsigned int)macadd, (long long int)fwversion, (long long int)swversion, (long long int)sw_fw_apiversion, - REQUIRED_FIRMWARE_VERSION); + REQUIRED_FIRMWARE_VERSION, + (long long int)client_sw_apiversion); + + // return if flag is not zero, debug mode + if (flag) { + firmware_check_done = 1; + return; + } //cant read versions if(!fwversion || !sw_fw_apiversion){ - cprintf(RED,"FATAL ERROR: Cant read versions from FPGA. Please update firmware\n"); - cprintf(RED,"Exiting Server. Goodbye!\n\n"); - exit(-1); + strcpy(firmware_message, + "FATAL ERROR: Cant read versions from FPGA. Please update firmware.\n"); + cprintf(RED,"%s\n\n", firmware_message); + firmware_compatibility = FAIL; + firmware_check_done = 1; + return; } //check for API compatibility - old server if(sw_fw_apiversion > REQUIRED_FIRMWARE_VERSION){ - cprintf(RED,"FATAL ERROR: This software version is incompatible.\n" - "Please update it to be compatible with this firmware\n\n"); - cprintf(RED,"Exiting Server. Goodbye!\n\n"); - exit(-1); + sprintf(firmware_message, + "FATAL ERROR: This detector software software version (%lld) is incompatible.\n" + "Please update detector software (min. %lld) to be compatible with this firmware.\n", + (long long int)sw_fw_apiversion, + (long long int)REQUIRED_FIRMWARE_VERSION); + cprintf(RED,"%s\n\n", firmware_message); + firmware_compatibility = FAIL; + firmware_check_done = 1; + return; } //check for firmware compatibility - old firmware if( REQUIRED_FIRMWARE_VERSION > fwversion){ - cprintf(RED,"FATAL ERROR: This firmware version is incompatible.\n" - "Please update it to v%d to be compatible with this server\n\n", REQUIRED_FIRMWARE_VERSION); - cprintf(RED,"Exiting Server. Goodbye!\n\n"); - exit(-1); + sprintf(firmware_message, + "FATAL ERROR: This firmware version (%lld) is incompatible.\n" + "Please update firmware (min. %lld) to be compatible with this server.\n", + (long long int)fwversion, + (long long int)REQUIRED_FIRMWARE_VERSION); + cprintf(RED,"%s\n\n", firmware_message); + firmware_compatibility = FAIL; + firmware_check_done = 1; + return; } + printf("Compatibility - success\n"); + firmware_check_done = 1; } @@ -175,6 +215,8 @@ int64_t getDetectorId(enum idMode arg){ return (int64_t)Beb_GetFirmwareSoftwareAPIVersion(); case DETECTOR_SOFTWARE_VERSION: return (GITDATE & 0xFFFFFF); + case CLIENT_SOFTWARE_API_VERSION: + return APIEIGER; default: break; } diff --git a/slsDetectorSoftware/eigerDetectorServer/updateAPIVersion.sh b/slsDetectorSoftware/eigerDetectorServer/updateAPIVersion.sh index 2dbea8493..618a9b601 100755 --- a/slsDetectorSoftware/eigerDetectorServer/updateAPIVersion.sh +++ b/slsDetectorSoftware/eigerDetectorServer/updateAPIVersion.sh @@ -1,7 +1,7 @@ SRCFILE=gitInfoEiger.h -DSTFILE=../commonFiles/versionAPI.h +DSTFILE=versionAPI.h SRCPATTERN=GITDATE DSTPATTERN=APIEIGER -awk -v a="$SRCFILE" -v b="$DSTFILE" -v c="$SRCPATTERN" -v d="$DSTPATTERN" 'FNR==NR&&$2==c{x=$3} NR!=FNR{if($2==d){$3=x}print > b}' $SRCFILE $DSTFILE \ No newline at end of file +awk -v a="$SRCFILE" -v b="$DSTFILE" -v c="$SRCPATTERN" -v d="$DSTPATTERN" 'FNR==NR&&$2==c{x=$3} NR!=FNR{if($2==d){$3="0x"substr(x,5)}print > b}' $SRCFILE $DSTFILE \ No newline at end of file diff --git a/slsDetectorSoftware/eigerDetectorServer/versionAPI.h b/slsDetectorSoftware/eigerDetectorServer/versionAPI.h new file mode 120000 index 000000000..d3bf8d6cf --- /dev/null +++ b/slsDetectorSoftware/eigerDetectorServer/versionAPI.h @@ -0,0 +1 @@ +../commonFiles/versionAPI.h \ No newline at end of file diff --git a/slsDetectorSoftware/gotthardDetectorServer/updateAPIVersion.sh b/slsDetectorSoftware/gotthardDetectorServer/updateAPIVersion.sh index 3d1b12d3a..2d5d8d04d 100755 --- a/slsDetectorSoftware/gotthardDetectorServer/updateAPIVersion.sh +++ b/slsDetectorSoftware/gotthardDetectorServer/updateAPIVersion.sh @@ -1,7 +1,7 @@ SRCFILE=gitInfoGotthard.h -DSTFILE=../commonFiles/versionAPI.h +DSTFILE=versionAPI.h SRCPATTERN=GITDATE DSTPATTERN=APIGOTTHARD -awk -v a="$SRCFILE" -v b="$DSTFILE" -v c="$SRCPATTERN" -v d="$DSTPATTERN" 'FNR==NR&&$2==c{x=$3} NR!=FNR{if($2==d){$3=x}print > b}' $SRCFILE $DSTFILE \ No newline at end of file +awk -v a="$SRCFILE" -v b="$DSTFILE" -v c="$SRCPATTERN" -v d="$DSTPATTERN" 'FNR==NR&&$2==c{x=$3} NR!=FNR{if($2==d){$3="0x"substr(x,5)}print > b}' $SRCFILE $DSTFILE \ No newline at end of file diff --git a/slsDetectorSoftware/gotthardDetectorServer/versionAPI.h b/slsDetectorSoftware/gotthardDetectorServer/versionAPI.h new file mode 120000 index 000000000..d3bf8d6cf --- /dev/null +++ b/slsDetectorSoftware/gotthardDetectorServer/versionAPI.h @@ -0,0 +1 @@ +../commonFiles/versionAPI.h \ No newline at end of file diff --git a/slsDetectorSoftware/jungfrauDetectorServer/bin/jungfrauDetectorServer_developer b/slsDetectorSoftware/jungfrauDetectorServer/bin/jungfrauDetectorServer_developer index c47cd1c9a27afc691760665cb696e572a80414db..a3822e486e467682c18dfca61cfe463db40c1585 100755 GIT binary patch delta 49963 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�dr;46^z3aOdYgydX5iZle7h2>aR3kcl`L0kCm8?!)2&b|Mz!0q6D3t`Kc2!f zcn9zLIX%VC>1ntU3(^Mfk1Ls<^aX_^Y?g%0)yUt?NAMV)!wYx~uls;P zEZ-H&j+q{usM0+{rF%B^;$E+uYrKoDL!SGD=X&H=j~wfngL82)W@Dl8-&1UZt9rPq zhlM>X?CHmWDBL?7!o6d0v7el$GjXw}7UNYqMEB#o52N5XJ~fka9KYyTFP*S`gdX1i zaQhSu(q$T=8+0?SG4_+&Hb!Wa?zu6JCeS2`r>T@cGbxdhXdb0dDlMc8T1?r*h`G6x zPX)A!il~H2shldPiZ(a;r8EA|=s0N}<%a*qTFhj84!XohNOq(e9c?jjlODr|1l6c+J(g*xFul<67s| zx_Pae*ScoyUfM_d=|Eg;Q!Q0c6>X-)lua3wOZikprBpyAltZhiT>LjR+32QTYN74a zMH=3ukxdU9VaTRV()gxrw2K(Ash*C}MH-@ebel$Kl+Ms)x=Dj{p03gjIzgwzzg6R{ z8gKRRRu65}P%8skHPVtxtEhzXsfdnH0o{v>z4!2(dt2Ps!q}Drbcj5wWr#G~!l0HB rVo-~QTQAc6xY*VN%1-r96?M@Ga>KSbN+OMKtDsIgMjrUvh?4#vVuYI* delta 47989 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 @@ -33,6 +33,19 @@ int virtual_stop = 0; /* basic tests */ +int firmware_compatibility = OK; +int firmware_check_done = 0; +char firmware_message[MAX_STR_LENGTH]; + +int isFirmwareCheckDone() { + return firmware_check_done; +} + +int getFirmwareCheckResult(char** mess) { + *mess = firmware_message; + return firmware_compatibility; +} + void checkFirmwareCompatibility(int flag) { #ifdef VIRTUAL cprintf(BLUE,"\n\n" @@ -40,23 +53,36 @@ void checkFirmwareCompatibility(int flag) { "************** Jungfrau Virtual Server *****************\n" "********************************************************\n\n"); if (mapCSP0() == FAIL) { - cprintf(BG_RED, "Dangerous to continue. Goodbye!\n"); - exit(EXIT_FAILURE); + strcpy(firmware_message, + "FATAL ERROR: Could not map to memory. Dangerous to continue.\n"); + cprintf(RED,"%s\n\n", firmware_message); + firmware_compatibility = FAIL; + firmware_check_done = 1; + return; } + firmware_check_done = 1; return; #endif defineGPIOpins(); resetFPGA(); if (mapCSP0() == FAIL) { - cprintf(BG_RED, "Dangerous to continue. Goodbye!\n"); - exit(EXIT_FAILURE); + strcpy(firmware_message, + "FATAL ERROR: Could not map to memory. Dangerous to continue.\n"); + cprintf(RED,"%s\n\n", firmware_message); + firmware_compatibility = FAIL; + firmware_check_done = 1; + return; } // does check only if flag is 0 (by default), set by command line if ((!flag) && ((checkType() == FAIL) || (testFpga() == FAIL) || (testBus() == FAIL))) { - cprintf(BG_RED, "Dangerous to continue. Goodbye!\n"); - exit(EXIT_FAILURE); + strcpy(firmware_message, + "FATAL ERROR: Could not pass basic tests of FPGA and bus. Dangerous to continue.\n"); + cprintf(RED,"%s\n\n", firmware_message); + firmware_compatibility = FAIL; + firmware_check_done = 1; + return; } uint16_t hversion = getHardwareVersionNumber(); @@ -66,6 +92,9 @@ void checkFirmwareCompatibility(int flag) { int64_t fwversion = getDetectorId(DETECTOR_FIRMWARE_VERSION); int64_t swversion = getDetectorId(DETECTOR_SOFTWARE_VERSION); int64_t sw_fw_apiversion = 0; + int64_t client_sw_apiversion = getDetectorId(CLIENT_SOFTWARE_API_VERSION); + + if (fwversion >= MIN_REQRD_VRSN_T_RD_API) sw_fw_apiversion = getDetectorId(SOFTWARE_FIRMWARE_API_VERSION); cprintf(BLUE,"\n\n" @@ -82,6 +111,7 @@ void checkFirmwareCompatibility(int flag) { "Software Version:\t\t 0x%llx\n" "F/w-S/w API Version:\t\t 0x%llx\n" "Required Firmware Version:\t 0x%x\n" + "Client-Software API Version:\t 0x%llx\n" "\n" "********************************************************\n", hversion, hsnumber, @@ -90,38 +120,55 @@ void checkFirmwareCompatibility(int flag) { (long long int)fwversion, (long long int)swversion, (long long int)sw_fw_apiversion, - REQRD_FRMWR_VRSN + REQRD_FRMWR_VRSN, + (long long int)client_sw_apiversion ); // return if flag is not zero, debug mode - if (flag) - return; + if (flag) { + firmware_check_done = 1; + return; + } //cant read versions printf("Testing Firmware-software compatibility ...\n"); if(!fwversion || !sw_fw_apiversion){ - cprintf(RED,"FATAL ERROR: Cant read versions from FPGA. Please update firmware\n"); - cprintf(RED,"Exiting Server. Goodbye!\n\n"); - exit(EXIT_FAILURE); + strcpy(firmware_message, + "FATAL ERROR: Cant read versions from FPGA. Please update firmware.\n"); + cprintf(RED,"%s\n\n", firmware_message); + firmware_compatibility = FAIL; + firmware_check_done = 1; + return; } //check for API compatibility - old server if(sw_fw_apiversion > REQRD_FRMWR_VRSN){ - cprintf(RED,"FATAL ERROR: This software version is incompatible.\n" - "Please update it to be compatible with this firmware\n\n"); - cprintf(RED,"Exiting Server. Goodbye!\n\n"); - exit(EXIT_FAILURE); + sprintf(firmware_message, + "FATAL ERROR: This detector software software version (0x%llx) is incompatible.\n" + "Please update detector software (min. 0x%llx) to be compatible with this firmware.\n", + (long long int)sw_fw_apiversion, + (long long int)REQRD_FRMWR_VRSN); + cprintf(RED,"%s\n\n", firmware_message); + firmware_compatibility = FAIL; + firmware_check_done = 1; + return; } //check for firmware compatibility - old firmware if( REQRD_FRMWR_VRSN > fwversion){ - cprintf(RED,"FATAL ERROR: This firmware version is incompatible.\n" - "Please update it to v%d to be compatible with this server\n\n", REQRD_FRMWR_VRSN); - cprintf(RED,"Exiting Server. Goodbye!\n\n"); - exit(EXIT_FAILURE); + sprintf(firmware_message, + "FATAL ERROR: This firmware version (0x%llx) is incompatible.\n" + "Please update firmware (min. 0x%llx) to be compatible with this server.\n", + (long long int)fwversion, + (long long int)REQRD_FRMWR_VRSN); + cprintf(RED,"%s\n\n", firmware_message); + firmware_compatibility = FAIL; + firmware_check_done = 1; + return; } printf("Compatibility - success\n"); + firmware_check_done = 1; } @@ -222,6 +269,8 @@ int64_t getDetectorId(enum idMode arg){ return getFirmwareAPIVersion(); case DETECTOR_SOFTWARE_VERSION: return (GITDATE & 0xFFFFFF); + case CLIENT_SOFTWARE_API_VERSION: + return APIJUNGFRAU; default: return retval; } diff --git a/slsDetectorSoftware/jungfrauDetectorServer/slsDetectorServer_defs.h b/slsDetectorSoftware/jungfrauDetectorServer/slsDetectorServer_defs.h index e98896d43..3fd667120 100644 --- a/slsDetectorSoftware/jungfrauDetectorServer/slsDetectorServer_defs.h +++ b/slsDetectorSoftware/jungfrauDetectorServer/slsDetectorServer_defs.h @@ -10,7 +10,7 @@ #define GOODBYE (-200) #define PROGRAMMING_MODE (-200) #define MIN_REQRD_VRSN_T_RD_API 0x171220 -#define REQRD_FRMWR_VRSN 0x180226 +#define REQRD_FRMWR_VRSN 0x20180226 /* Struct Definitions */ diff --git a/slsDetectorSoftware/jungfrauDetectorServer/updateAPIVersion.sh b/slsDetectorSoftware/jungfrauDetectorServer/updateAPIVersion.sh index b671637c6..ef65ec7e7 100755 --- a/slsDetectorSoftware/jungfrauDetectorServer/updateAPIVersion.sh +++ b/slsDetectorSoftware/jungfrauDetectorServer/updateAPIVersion.sh @@ -1,7 +1,7 @@ SRCFILE=gitInfoJungfrau.h -DSTFILE=../commonFiles/versionAPI.h +DSTFILE=versionAPI.h SRCPATTERN=GITDATE DSTPATTERN=APIJUNGFRAU -awk -v a="$SRCFILE" -v b="$DSTFILE" -v c="$SRCPATTERN" -v d="$DSTPATTERN" 'FNR==NR&&$2==c{x=$3} NR!=FNR{if($2==d){$3=x}print > b}' $SRCFILE $DSTFILE \ No newline at end of file +awk -v a="$SRCFILE" -v b="$DSTFILE" -v c="$SRCPATTERN" -v d="$DSTPATTERN" 'FNR==NR&&$2==c{x=$3} NR!=FNR{if($2==d){$3="0x"substr(x,5)}print > b}' $SRCFILE $DSTFILE \ No newline at end of file diff --git a/slsDetectorSoftware/jungfrauDetectorServer/versionAPI.h b/slsDetectorSoftware/jungfrauDetectorServer/versionAPI.h new file mode 120000 index 000000000..d3bf8d6cf --- /dev/null +++ b/slsDetectorSoftware/jungfrauDetectorServer/versionAPI.h @@ -0,0 +1 @@ +../commonFiles/versionAPI.h \ No newline at end of file diff --git a/slsDetectorSoftware/multiSlsDetector/multiSlsDetector.cpp b/slsDetectorSoftware/multiSlsDetector/multiSlsDetector.cpp index bea8ff9ef..bce099245 100644 --- a/slsDetectorSoftware/multiSlsDetector/multiSlsDetector.cpp +++ b/slsDetectorSoftware/multiSlsDetector/multiSlsDetector.cpp @@ -7021,3 +7021,42 @@ bool multiSlsDetector::isAcquireReady() { thisMultiDetector->acquiringFlag = true; return OK; } + + + +int multiSlsDetector::checkVersionCompatibility(portType t) { + int ret=-100; + + if(!threadpool){ + cout << "Error in creating threadpool. Exiting" << endl; + return -1; + }else{ + //return storage values + int* iret[thisMultiDetector->numberOfDetectors]; + for(int idet=0; idetnumberOfDetectors; ++idet){ + if(detectors[idet]){ + iret[idet]= new int(-1); + Task* task = new Task(new func1_t(&slsDetector::checkVersionCompatibility, + detectors[idet],t,iret[idet])); + threadpool->add_task(task); + } + } + threadpool->startExecuting(); + threadpool->wait_for_tasks_to_complete(); + for(int idet=0; idetnumberOfDetectors; ++idet){ + if(detectors[idet]){ + if(iret[idet] != NULL){ + if (ret==-100) + ret=*iret[idet]; + else if (ret!=*iret[idet]) + ret=-1; + delete iret[idet]; + }else ret=-1; + if(detectors[idet]->getErrorMask()) + setErrorMask(getErrorMask()|(1< #include #include "gitInfoLib.h" +#include "versionAPI.h" + using namespace std; int slsDetector::initSharedMemory(detectorType type, int id) { @@ -806,6 +808,10 @@ int slsDetector::initializeDetectorSize(detectorType type) { thisDetector->receiver_read_freq = 0; thisDetector->receiver_framesPerFile = -1; + thisDetector->detectorControlAPIVersion = 0; + thisDetector->detectorStopAPIVersion = 0; + thisDetector->receiverAPIVersion = 0; + for (int ia=0; iaactionScript[ia],"none"); strcpy(thisDetector->actionParameter[ia],"none"); @@ -1430,7 +1436,6 @@ int slsDetector::activate(int const enable){ */ int slsDetector::setTCPSocket(string const name, int const control_port, int const stop_port){ - char thisName[MAX_STR_LENGTH]; int thisCP, thisSP; int retval=OK; @@ -1511,6 +1516,22 @@ int slsDetector::setTCPSocket(string const name, int const control_port, int con } if (retval!=FAIL) { checkOnline(); + + // check for version compatibility + switch (thisDetector->myDetectorType) { + case EIGER: + case JUNGFRAU: + case GOTTHARD: + if ((thisDetector->detectorControlAPIVersion == 0) || + (thisDetector->detectorStopAPIVersion == 0)) { + if (checkVersionCompatibility(CONTROL_PORT) == FAIL) + thisDetector->onlineFlag=OFFLINE_FLAG; + } + break; + default: + break; + } + } else { thisDetector->onlineFlag=OFFLINE_FLAG; #ifdef VERBOSE @@ -8364,15 +8385,28 @@ int slsDetector::setReceiverTCPSocket(string const name, int const receiver_port } //check if it connects if (retval!=FAIL) { - if(checkReceiverOnline().empty()) - retval=FAIL; + checkReceiverOnline(); + thisReceiver->setSocket(dataSocket); + // check for version compatibility + switch (thisDetector->myDetectorType) { + case EIGER: + case JUNGFRAU: + case GOTTHARD: + if (thisDetector->receiverAPIVersion == 0){ + if (checkVersionCompatibility(DATA_PORT) == FAIL) + thisDetector->receiverOnlineFlag=OFFLINE_FLAG; + } + break; + default: + break; + } + } else { thisDetector->receiverOnlineFlag=OFFLINE_FLAG; #ifdef VERBOSE std::cout<< "offline!" << std::endl; #endif } - thisReceiver->setSocket(dataSocket); return retval; }; @@ -9821,3 +9855,99 @@ int slsDetector::restreamStopFromReceiver(){ return ret; } + + +int slsDetector::checkVersionCompatibility(portType t) { + int fnum = F_CHECK_VERSION; + if (t == DATA_PORT) + fnum = F_RECEIVER_CHECK_VERSION; + int ret = FAIL; + char mess[MAX_STR_LENGTH]; + memset(mess, 0, MAX_STR_LENGTH); + int64_t arg = 0; + + // detector + if (t == CONTROL_PORT) { + + switch (thisDetector->myDetectorType) { + case EIGER: arg = APIEIGER; break; + case JUNGFRAU: arg = APIJUNGFRAU; break; + case GOTTHARD: arg = APIGOTTHARD; break; + default: + std::cout<< "Check version compatibility is not implemented for this detector" << std::endl; + setErrorMask((getErrorMask())|(VERSION_COMPATIBILITY)); + return FAIL; + } + +#ifdef VERBOSE + std::cout<< std::endl<< "Checking version compatibility with detector with value " << hex << arg << std::endl; +#endif + if (thisDetector->onlineFlag==ONLINE_FLAG) { + // control port + if (connectControl() == OK){ + controlSocket->SendDataOnly(&fnum,sizeof(fnum)); + controlSocket->SendDataOnly(&arg,sizeof(arg)); + controlSocket->ReceiveDataOnly(&ret,sizeof(ret)); + if (ret == FAIL) { + controlSocket->ReceiveDataOnly(mess,sizeof(mess)); + cprintf(RED, "Detector returned error: (Control Server) %s", mess); + if(strstr(mess,"Unrecognized Function")!=NULL) + std::cout << "The detector server is too old to get API version. Please update detector server!" << std::endl; + setErrorMask((getErrorMask())|(VERSION_COMPATIBILITY)); + thisDetector->detectorControlAPIVersion = 0; + } else { + thisDetector->detectorControlAPIVersion = arg; + } + disconnectControl(); + } + if (ret!= FAIL) { + ret = FAIL; + + // stop port + if (connectStop() == OK){ + stopSocket->SendDataOnly(&fnum,sizeof(fnum)); + stopSocket->SendDataOnly(&arg,sizeof(arg)); + stopSocket->ReceiveDataOnly(&ret,sizeof(ret)); + if (ret == FAIL) { + stopSocket->ReceiveDataOnly(mess,sizeof(mess)); + cprintf(RED, "Detector returned error: (Stop Server) %s", mess); + if(strstr(mess,"Unrecognized Function")!=NULL) + std::cout << "The detector server is too old to get API version. Please update detector server!" << std::endl; + setErrorMask((getErrorMask())|(VERSION_COMPATIBILITY)); + thisDetector->detectorStopAPIVersion = 0; + } else { + thisDetector->detectorStopAPIVersion = arg; + } + disconnectStop(); + } + } + } + } + + // receiver + else { + arg = APIRECEIVER; +#ifdef VERBOSE + std::cout<< std::endl<< "Checking version compatibility with receiver with value " << hex << arg << std::endl; +#endif + if (thisDetector->receiverOnlineFlag==ONLINE_FLAG) { + // data port + if (connectData() == OK){ + // ignoring retval + int64_t retval = -1; + ret=thisReceiver->sendInt(fnum,retval,arg); + if (ret==FAIL){ + setErrorMask((getErrorMask())|(VERSION_COMPATIBILITY)); + if(strstr(mess,"Unrecognized Function")!=NULL) + std::cout << "The receiver software is too old to get API version. Please update receiver software!" << std::endl; + thisDetector->receiverAPIVersion = 0; + } else { + thisDetector->receiverAPIVersion = arg; + } + disconnectData(); + } + } + } + + return ret; +} diff --git a/slsDetectorSoftware/slsDetector/slsDetector.h b/slsDetectorSoftware/slsDetector/slsDetector.h index 5bf6bd447..bcab250c8 100644 --- a/slsDetectorSoftware/slsDetector/slsDetector.h +++ b/slsDetectorSoftware/slsDetector/slsDetector.h @@ -290,11 +290,12 @@ class slsDetector : public slsDetectorUtils, public energyConversion { /** frames per file in receiver */ int receiver_framesPerFile; - /** detector software API version */ - int detector_software_api_version; - - /** receiver API version */ - int receiver_api_version; + /** detector control server software API version */ + int64_t detectorControlAPIVersion; + /** detector stop server software API version */ + int64_t detectorStopAPIVersion; + /** receiver server software API version */ + int64_t receiverAPIVersion; } sharedSlsDetector; @@ -2059,6 +2060,14 @@ class slsDetector : public slsDetectorUtils, public energyConversion { */ int restreamStopFromReceiver(); + /** + * Check version compatibility with detector/receiver software + * (if hostname/rx_hostname has been set/ sockets created) + * \param p port type control port or receiver port + * \returns FAIL for incompatibility, OK for compatibility + */ + int checkVersionCompatibility(portType t); + protected: diff --git a/slsDetectorSoftware/slsDetector/slsDetectorCommand.cpp b/slsDetectorSoftware/slsDetector/slsDetectorCommand.cpp index aa71dd50d..fea9b7cbf 100644 --- a/slsDetectorSoftware/slsDetector/slsDetectorCommand.cpp +++ b/slsDetectorSoftware/slsDetector/slsDetectorCommand.cpp @@ -507,6 +507,22 @@ slsDetectorCommand::slsDetectorCommand(slsDetectorUtils *det) { Commands to check versions of each subsystem */ + /*! \page config + - checkdetversion Checks the version compatibility with detector software (if hostname is in shared memory). Only get! Only for Eiger, Jungfrau & Gotthard. \c Returns \c ("compatible", "incompatible") + */ + descrToFuncMap[i].m_pFuncName="checkdetversion"; // + descrToFuncMap[i].m_pFuncPtr=&slsDetectorCommand::cmdSN; + ++i; + + + /*! \page config + - checkrecversion Checks the version compatibility with receiver software (if rx_hostname is in shared memory). Only get! Only for Eiger, Jungfrau & Gotthard. \c Returns \c ("compatible", "incompatible") + */ + descrToFuncMap[i].m_pFuncName="checkrecversion"; // + descrToFuncMap[i].m_pFuncPtr=&slsDetectorCommand::cmdSN; + ++i; + + /*! \page config - moduleversion:[i] Gets the firmware version of module i. Used for MYTHEN only. Only get! \c Returns \c (long int) in hexadecimal or "undefined module number" */ @@ -4895,6 +4911,24 @@ string slsDetectorCommand::cmdSN(int narg, char *args[], int action) { sprintf(answer,"0x%lx", retval); return string(answer); } + + if (cmd=="checkdetversion") { + int retval = myDet->checkVersionCompatibility(CONTROL_PORT); + if (retval < 0) + sprintf(answer, "%d", -1); + sprintf(answer,"%s", retval == OK ? "compatible" : "incompatible"); + return string(answer); + } + + if (cmd=="checkrecversion") { + myDet->setReceiverOnline(ONLINE_FLAG); + int retval = myDet->checkVersionCompatibility(DATA_PORT); + if (retval < 0) + sprintf(answer, "%d", -1); + sprintf(answer,"%s", retval == OK ? "compatible" : "incompatible"); + return string(answer); + } + return string("unknown id mode ")+cmd; } @@ -4903,6 +4937,8 @@ string slsDetectorCommand::helpSN(int narg, char *args[], int action) { ostringstream os; if (action==GET_ACTION || action==HELP_ACTION) { + os << "checkdetversion \n gets the version compatibility with detector software (if hostname is in shared memory). Only for Eiger, Jungfrau & Gotthard. Prints compatible/ incompatible."<< std::endl; + os << "checkrecversion \n gets the version compatibility with receiver software (if rx_hostname is in shared memory). Only for Eiger, Jungfrau & Gotthard. Prints compatible/ incompatible."<< std::endl; os << "moduleversion:i \n gets the firmwareversion of the module i"<< std::endl; os << "modulenumber:i \n gets the serial number of the module i"<< std::endl; os << "detectornumber \n gets the serial number of the detector (MAC)"<< std::endl; diff --git a/slsDetectorSoftware/slsDetector/slsDetectorUtils.h b/slsDetectorSoftware/slsDetector/slsDetectorUtils.h index ba183e275..1dbf5840e 100644 --- a/slsDetectorSoftware/slsDetector/slsDetectorUtils.h +++ b/slsDetectorSoftware/slsDetector/slsDetectorUtils.h @@ -1029,6 +1029,14 @@ virtual int setReceiverSilentMode(int i = -1)=0; virtual bool isAcquireReady() = 0; + /** + * Check version compatibility with detector/receiver software + * (if hostname/rx_hostname has been set/ sockets created) + * \param p port type control port or data (receiver) port + * \returns FAIL for incompatibility, OK for compatibility + */ + virtual int checkVersionCompatibility(portType t) = 0; + protected: diff --git a/slsDetectorSoftware/slsDetectorServer/slsDetectorFunctionList.h b/slsDetectorSoftware/slsDetectorServer/slsDetectorFunctionList.h index 8611ffbcd..6c990b5f6 100644 --- a/slsDetectorSoftware/slsDetectorServer/slsDetectorFunctionList.h +++ b/slsDetectorSoftware/slsDetectorServer/slsDetectorFunctionList.h @@ -17,6 +17,11 @@ Here are the definitions, but the actual implementation should be done for each // basic tests +#if defined(EIGERD) || defined(JUNGFRAUD) || defined(GOTTHARD) +int isFirmwareCheckDone(); +int getFirmwareCheckResult(char** mess); +#endif + void checkFirmwareCompatibility(int flag); #if defined(MYTHEN3D) || defined(JUNGFRAUD) int checkType(); diff --git a/slsDetectorSoftware/slsDetectorServer/slsDetectorServer_funcs.c b/slsDetectorSoftware/slsDetectorServer/slsDetectorServer_funcs.c index 98387b19f..0fb87ea2e 100755 --- a/slsDetectorSoftware/slsDetectorServer/slsDetectorServer_funcs.c +++ b/slsDetectorSoftware/slsDetectorServer/slsDetectorServer_funcs.c @@ -209,6 +209,7 @@ const char* getFunctionName(enum detFuncs func) { case F_TEMP_EVENT: return "F_TEMP_EVENT"; case F_AUTO_COMP_DISABLE: return "F_AUTO_COMP_DISABLE"; case F_STORAGE_CELL_START: return "F_STORAGE_CELL_START"; + case F_CHECK_VERSION: return "F_CHECK_VERSION"; default: return "Unknown Function"; } @@ -293,6 +294,7 @@ void function_table() { flist[F_TEMP_EVENT] = &temp_event; flist[F_AUTO_COMP_DISABLE] = &auto_comp_disable; flist[F_STORAGE_CELL_START] = &storage_cell_start; + flist[F_CHECK_VERSION] = &check_version; // check if (NUM_DET_FUNCTIONS >= TOO_MANY_FUNCTIONS_DEFINED) { @@ -5146,9 +5148,10 @@ int program_fpga(int file_des) { printf("Done with program receiving command\n"); #endif - if (isControlServer) + if (isControlServer) { basictests(debugflag); - init_detector(isControlServer); + initControlServer(); + } } #endif if (ret==OK) @@ -5760,3 +5763,97 @@ int storage_cell_start(int file_des) { return ret; } + + + +int check_version(int file_des) { + int ret=OK,ret1=OK; + int n=0; + sprintf(mess,"check version failed\n"); + +#if !defined(EIGERD) && !defined(JUNGFRAUD) && !defined(GOTTHARD) + //to receive any arguments + while (n > 0) + n = receiveData(file_des,mess,MAX_STR_LENGTH,OTHER); + ret=FAIL; + sprintf(mess,"Function (Check Version Compatibility) is not implemented for this detector\n"); + cprintf(RED, "Warning: %s", mess); +#else + + // receive arguments + int64_t arg=-1; + n = receiveData(file_des,&arg,sizeof(arg),INT64); + if (n < 0) return printSocketReadError(); + + // execute action +#ifdef SLS_DETECTOR_FUNCTION_LIST + + // check software- firmware compatibility and basic tests + if (isControlServer) { +#ifdef VERBOSE + printf("Checking software-firmware compatibility and basic test result\n"); +#endif + // check if firmware check is done + if (!isFirmwareCheckDone()) { + usleep(3 * 1000 * 1000); + if (!isFirmwareCheckDone()) { + ret = FAIL; + strcpy(mess,"Firmware Software Compatibility Check (Server Initialization) " + "still not done done in server. Unexpected.\n"); + cprintf(RED, "Warning: %s", mess); + } + } + // check firmware check result + if (ret == OK) { + char* firmware_message = NULL; + if (getFirmwareCheckResult(&firmware_message) == FAIL) { + ret = FAIL; + strcpy(mess, firmware_message); + cprintf(RED, "Warning: %s", mess); + } + } + } + + if (ret == OK) { +#ifdef VERBOSE + printf("Checking versioning compatibility with value %d\n",arg); +#endif + int64_t client_requiredVersion = arg; + int64_t det_apiVersion = getDetectorId(CLIENT_SOFTWARE_API_VERSION); + int64_t det_version = getDetectorId(DETECTOR_SOFTWARE_VERSION); + + // old client + if (det_apiVersion > client_requiredVersion) { + ret = FAIL; + sprintf(mess,"Client's detector SW API version: (0x%llx). " + "Detector's SW API Version: (0x%llx). " + "Incompatible, update client!\n", + client_requiredVersion, det_apiVersion); + cprintf(RED, "Warning: %s", mess); + } + + // old software + else if (client_requiredVersion > det_version) { + ret = FAIL; + sprintf(mess,"Detector SW Version: (0x%llx). " + "Client's detector SW API Version: (0x%llx). " + "Incompatible, update detector software!\n", + det_version, client_requiredVersion); + cprintf(RED, "Warning: %s", mess); + } + } +#endif +#endif + + // ret could be swapped during sendData + ret1 = ret; + // send ok / fail + n = sendData(file_des,&ret1,sizeof(ret),INT32); + // send return argument + if (ret==FAIL) { + n += sendData(file_des,mess,sizeof(mess),OTHER); + } + + // return ok / fail + return ret; +} diff --git a/slsDetectorSoftware/slsDetectorServer/slsDetectorServer_funcs.h b/slsDetectorSoftware/slsDetectorServer/slsDetectorServer_funcs.h index b80a9712f..a8ab6b927 100755 --- a/slsDetectorSoftware/slsDetectorServer/slsDetectorServer_funcs.h +++ b/slsDetectorSoftware/slsDetectorServer/slsDetectorServer_funcs.h @@ -95,5 +95,6 @@ int temp_control(int); int temp_event(int); int auto_comp_disable(int); int storage_cell_start(int); +int check_version(int); #endif diff --git a/slsDetectorSoftware/slsReceiverInterface/receiverInterface.cpp b/slsDetectorSoftware/slsReceiverInterface/receiverInterface.cpp index bd5e1cc4a..a8bbd4a0b 100644 --- a/slsDetectorSoftware/slsReceiverInterface/receiverInterface.cpp +++ b/slsDetectorSoftware/slsReceiverInterface/receiverInterface.cpp @@ -21,7 +21,8 @@ receiverInterface::~receiverInterface(){} int receiverInterface::sendString(int fnum, char retval[], char arg[]){ int ret = slsDetectorDefs::FAIL; - char mess[MAX_STR_LENGTH] = ""; + char mess[MAX_STR_LENGTH]; + memset(mess, 0, MAX_STR_LENGTH); dataSocket->SendDataOnly(&fnum,sizeof(fnum)); dataSocket->SendDataOnly(arg,MAX_STR_LENGTH); @@ -30,7 +31,8 @@ int receiverInterface::sendString(int fnum, char retval[], char arg[]){ dataSocket->ReceiveDataOnly(mess,sizeof(mess)); cprintf(RED, "Receiver returned error: %s", mess); } - dataSocket->ReceiveDataOnly(retval,MAX_STR_LENGTH); + if(strstr(mess,"Unrecognized Function")==NULL) + dataSocket->ReceiveDataOnly(retval,MAX_STR_LENGTH); return ret; } @@ -40,7 +42,8 @@ int receiverInterface::sendString(int fnum, char retval[], char arg[]){ int receiverInterface::sendUDPDetails(int fnum, char retval[], char arg[3][MAX_STR_LENGTH]){ char args[3][MAX_STR_LENGTH]; int ret = slsDetectorDefs::FAIL; - char mess[MAX_STR_LENGTH] = ""; + char mess[MAX_STR_LENGTH]; + memset(mess, 0, MAX_STR_LENGTH); dataSocket->SendDataOnly(&fnum,sizeof(fnum)); dataSocket->SendDataOnly(arg,sizeof(args)); @@ -58,7 +61,8 @@ int receiverInterface::sendUDPDetails(int fnum, char retval[], char arg[3][MAX_S int receiverInterface::sendInt(int fnum, int &retval, int arg){ int ret = slsDetectorDefs::FAIL; - char mess[MAX_STR_LENGTH] = ""; + char mess[MAX_STR_LENGTH]; + memset(mess, 0, MAX_STR_LENGTH); dataSocket->SendDataOnly(&fnum,sizeof(fnum)); dataSocket->SendDataOnly(&arg,sizeof(arg)); @@ -67,7 +71,8 @@ int receiverInterface::sendInt(int fnum, int &retval, int arg){ dataSocket->ReceiveDataOnly(mess,sizeof(mess)); cprintf(RED, "Receiver returned error: %s", mess); } - dataSocket->ReceiveDataOnly(&retval,sizeof(retval)); + if(strstr(mess,"Unrecognized Function")==NULL) + dataSocket->ReceiveDataOnly(&retval,sizeof(retval)); return ret; } @@ -76,7 +81,8 @@ int receiverInterface::sendInt(int fnum, int &retval, int arg){ int receiverInterface::getInt(int fnum, int &retval){ int ret = slsDetectorDefs::FAIL; - char mess[MAX_STR_LENGTH] = ""; + char mess[MAX_STR_LENGTH]; + memset(mess, 0, MAX_STR_LENGTH); dataSocket->SendDataOnly(&fnum,sizeof(fnum)); dataSocket->ReceiveDataOnly(&ret,sizeof(ret)); @@ -84,7 +90,8 @@ int receiverInterface::getInt(int fnum, int &retval){ dataSocket->ReceiveDataOnly(mess,sizeof(mess)); cprintf(RED, "Receiver returned error: %s", mess); } - dataSocket->ReceiveDataOnly(&retval,sizeof(retval)); + if(strstr(mess,"Unrecognized Function")==NULL) + dataSocket->ReceiveDataOnly(&retval,sizeof(retval)); return ret; } @@ -93,7 +100,8 @@ int receiverInterface::getInt(int fnum, int &retval){ int receiverInterface::sendInt(int fnum, int64_t &retval, int64_t arg){ int ret = slsDetectorDefs::FAIL; - char mess[MAX_STR_LENGTH] = ""; + char mess[MAX_STR_LENGTH]; + memset(mess, 0, MAX_STR_LENGTH); dataSocket->SendDataOnly(&fnum,sizeof(fnum)); dataSocket->SendDataOnly(&arg,sizeof(arg)); @@ -102,7 +110,8 @@ int receiverInterface::sendInt(int fnum, int64_t &retval, int64_t arg){ dataSocket->ReceiveDataOnly(mess,sizeof(mess)); cprintf(RED, "Receiver returned error: %s", mess); } - dataSocket->ReceiveDataOnly(&retval,sizeof(retval)); + if(strstr(mess,"Unrecognized Function")==NULL) + dataSocket->ReceiveDataOnly(&retval,sizeof(retval)); return ret; } @@ -111,16 +120,18 @@ int receiverInterface::sendInt(int fnum, int64_t &retval, int64_t arg){ int receiverInterface::sendIntArray(int fnum, int64_t &retval, int64_t arg[2], char mess[]){ int64_t args[2]; - char messs[MAX_STR_LENGTH]; int ret = slsDetectorDefs::FAIL; + memset(mess, 0, MAX_STR_LENGTH); + dataSocket->SendDataOnly(&fnum,sizeof(fnum)); dataSocket->SendDataOnly(arg,sizeof(args)); dataSocket->ReceiveDataOnly(&ret,sizeof(ret)); if (ret==slsDetectorDefs::FAIL){ - dataSocket->ReceiveDataOnly(mess,sizeof(messs)); + dataSocket->ReceiveDataOnly(mess,MAX_STR_LENGTH); cprintf(RED, "Receiver returned error: %s", mess); } - dataSocket->ReceiveDataOnly(&retval,sizeof(retval)); + if(strstr(mess,"Unrecognized Function")==NULL) + dataSocket->ReceiveDataOnly(&retval,sizeof(retval)); return ret; } @@ -130,7 +141,9 @@ int receiverInterface::sendIntArray(int fnum, int64_t &retval, int64_t arg[2], c int receiverInterface::sendIntArray(int fnum, int &retval, int arg[2]){ int args[2]; int ret = slsDetectorDefs::FAIL; - char mess[MAX_STR_LENGTH] = ""; + char mess[MAX_STR_LENGTH]; + memset(mess, 0, MAX_STR_LENGTH); + dataSocket->SendDataOnly(&fnum,sizeof(fnum)); dataSocket->SendDataOnly(arg,sizeof(args)); dataSocket->ReceiveDataOnly(&ret,sizeof(ret)); @@ -138,7 +151,8 @@ int receiverInterface::sendIntArray(int fnum, int &retval, int arg[2]){ dataSocket->ReceiveDataOnly(mess,sizeof(mess)); cprintf(RED, "Receiver returned error: %s", mess); } - dataSocket->ReceiveDataOnly(&retval,sizeof(retval)); + if(strstr(mess,"Unrecognized Function")==NULL) + dataSocket->ReceiveDataOnly(&retval,sizeof(retval)); return ret; } @@ -170,6 +184,7 @@ int receiverInterface::getLastClientIP(int fnum, char retval[]){ int receiverInterface::executeFunction(int fnum,char mess[]){ int ret = slsDetectorDefs::FAIL; + memset(mess, 0, MAX_STR_LENGTH); dataSocket->SendDataOnly(&fnum,sizeof(fnum)); dataSocket->ReceiveDataOnly(&ret,sizeof(ret)); diff --git a/slsDetectorSoftware/threadFiles/Task.h b/slsDetectorSoftware/threadFiles/Task.h index b9d6177a5..cbb4118f9 100644 --- a/slsDetectorSoftware/threadFiles/Task.h +++ b/slsDetectorSoftware/threadFiles/Task.h @@ -105,7 +105,7 @@ private: class SuperTask: public virtual slsDetectorDefs { public: SuperTask(): - m1(0),m2(0),m3(0),m4(0),m5(0),m6(0),m7(0),m8(0),m9(0),m10(0),m11(0),m12(0),m13(0),m14(0),m15(0),m16(0),m17(0),m18(0){}; + m1(0),m2(0),m3(0),m4(0),m5(0),m6(0),m7(0),m8(0),m9(0),m10(0),m11(0),m12(0),m13(0),m14(0),m15(0),m16(0),m17(0),m18(0),m19(0){}; virtual ~SuperTask(){}; protected: /** Function signature defined @@ -129,6 +129,7 @@ protected: func4_t * m16; func4_t * m17; func4_t * m18; + func1_t * m19; }; class Task: public virtual SuperTask { @@ -154,6 +155,7 @@ public: Task(func4_t * t): SuperTask(),fnum(16){m16 = t;}; Task(func4_t * t): SuperTask(),fnum(17){m17 = t;}; Task(func4_t * t): SuperTask(),fnum(18){m18 = t;}; + Task(func1_t * t): SuperTask(),fnum(19){m19 = t;}; virtual ~Task(){ switch(fnum) { @@ -175,6 +177,7 @@ public: case 16: delete m16; break; case 17: delete m17; break; case 18: delete m18; break; + case 19: delete m19; break; default: cprintf(RED, "Error: Task not defined. Abort!\n"); break; @@ -202,6 +205,7 @@ public: case 16: (*m16)(); break; case 17: (*m17)(); break; case 18: (*m18)(); break; + case 19: (*m19)(); break; default: cprintf(RED, "Error: Task not defined. Abort!\n"); break; diff --git a/slsReceiverSoftware/include/slsReceiverTCPIPInterface.h b/slsReceiverSoftware/include/slsReceiverTCPIPInterface.h index 42e2e980a..3d48f01d0 100644 --- a/slsReceiverSoftware/include/slsReceiverTCPIPInterface.h +++ b/slsReceiverSoftware/include/slsReceiverTCPIPInterface.h @@ -309,6 +309,10 @@ class slsReceiverTCPIPInterface : private virtual slsReceiverDefs { /** set frames per file */ int set_frames_per_file(); + + /** check version compatibility */ + int check_version_compatibility(); + /** detector type */ detectorType myDetectorType; diff --git a/slsReceiverSoftware/include/sls_receiver_funcs.h b/slsReceiverSoftware/include/sls_receiver_funcs.h index da113cfd5..3f1c06664 100644 --- a/slsReceiverSoftware/include/sls_receiver_funcs.h +++ b/slsReceiverSoftware/include/sls_receiver_funcs.h @@ -67,7 +67,7 @@ enum recFuncs{ F_RECEIVER_UDP_SOCK_BUF_SIZE, /** < UDP socket buffer size */ F_RECEIVER_REAL_UDP_SOCK_BUF_SIZE, /** < real UDP socket buffer size */ F_SET_RECEIVER_FRAMES_PER_FILE, /** < receiver frames per file */ - + F_RECEIVER_CHECK_VERSION, /** < check receiver version compatibility */ /* Always append functions hereafter!!! */ diff --git a/slsReceiverSoftware/include/versionAPI.h b/slsReceiverSoftware/include/versionAPI.h new file mode 120000 index 000000000..a4d75aa2a --- /dev/null +++ b/slsReceiverSoftware/include/versionAPI.h @@ -0,0 +1 @@ +../../slsDetectorSoftware/commonFiles/versionAPI.h \ No newline at end of file diff --git a/slsReceiverSoftware/src/UDPStandardImplementation.cpp b/slsReceiverSoftware/src/UDPStandardImplementation.cpp index 20ab92b03..bef70a6dd 100644 --- a/slsReceiverSoftware/src/UDPStandardImplementation.cpp +++ b/slsReceiverSoftware/src/UDPStandardImplementation.cpp @@ -674,7 +674,7 @@ void UDPStandardImplementation::SetLocalNetworkParameters() { "[/proc/sys/net/core/netdev_max_backlog] modified to %d\n", MAX_SOCKET_INPUT_PACKET_QUEUE); } else { - const char *msg = "Could not change max length of" + const char *msg = "Could not change max length of " "input packet queue [net.core.netdev_max_backlog]. (No Root Privileges?)"; FILE_LOG(logWARNING) << msg; } diff --git a/slsReceiverSoftware/src/slsReceiverTCPIPInterface.cpp b/slsReceiverSoftware/src/slsReceiverTCPIPInterface.cpp index 5b3d2c482..e79590bf6 100644 --- a/slsReceiverSoftware/src/slsReceiverTCPIPInterface.cpp +++ b/slsReceiverSoftware/src/slsReceiverTCPIPInterface.cpp @@ -8,6 +8,7 @@ #include "gitInfoReceiver.h" #include "slsReceiverUsers.h" #include "slsReceiver.h" +#include "versionAPI.h" #include //EXIT #include @@ -153,7 +154,7 @@ void slsReceiverTCPIPInterface::stop(){ int64_t slsReceiverTCPIPInterface::getReceiverVersion(){ - int64_t retval = GITDATE; + int64_t retval = GITDATE & 0xFFFFFF; return retval; } @@ -297,6 +298,7 @@ const char* slsReceiverTCPIPInterface::getFunctionName(enum recFuncs func) { case F_RECEIVER_UDP_SOCK_BUF_SIZE: return "F_RECEIVER_UDP_SOCK_BUF_SIZE"; case F_RECEIVER_REAL_UDP_SOCK_BUF_SIZE: return "F_RECEIVER_REAL_UDP_SOCK_BUF_SIZE"; case F_SET_RECEIVER_FRAMES_PER_FILE:return "F_SET_RECEIVER_FRAMES_PER_FILE"; + case F_RECEIVER_CHECK_VERSION: return "F_RECEIVER_CHECK_VERSION"; default: return "Unknown Function"; } @@ -350,6 +352,7 @@ int slsReceiverTCPIPInterface::function_table(){ flist[F_RECEIVER_UDP_SOCK_BUF_SIZE] = &slsReceiverTCPIPInterface::set_udp_socket_buffer_size; flist[F_RECEIVER_REAL_UDP_SOCK_BUF_SIZE]= &slsReceiverTCPIPInterface::get_real_udp_socket_buffer_size; flist[F_SET_RECEIVER_FRAMES_PER_FILE] = &slsReceiverTCPIPInterface::set_frames_per_file; + flist[F_RECEIVER_CHECK_VERSION] = &slsReceiverTCPIPInterface::check_version_compatibility; #ifdef VERYVERBOSE for (int i = 0; i < NUM_REC_FUNCTIONS ; i++) { @@ -367,20 +370,22 @@ int slsReceiverTCPIPInterface::decode_function(){ ret = FAIL; #ifdef VERYVERBOSE cprintf(RESET,"\n"); - FILE_LOG(logDEBUG1) << "waiting to receive data"; #endif + FILE_LOG(logDEBUG1) << "waiting to receive data"; int n = mySock->ReceiveDataOnly(&fnum,sizeof(fnum)); if (n <= 0) { -#ifdef VERYVERBOSE - FILE_LOG(logDEBUG1) << "ERROR reading from socket. Received " << n << " bytes, fd: " << file_des << " fnum:" << fnum << " (" << getFunctionName((enum recFuncs)fnum) << ")"; -#endif + FILE_LOG(logDEBUG1) << "ERROR reading from socket. " + "Received " << n << " bytes," << + "fnum:" << fnum << " " + "(" << getFunctionName((enum recFuncs)fnum) << ")"; return FAIL; } -#ifdef VERYVERBOSE else FILE_LOG(logDEBUG1) << "Received " << n << " bytes"; - FILE_LOG(logDEBUG1) << "calling function fnum: "<< fnum << " (" << getFunctionName((enum recFuncs)fnum) << ") located at " << flist[fnum]; -#endif + + FILE_LOG(logDEBUG1) << "calling function fnum: "<< fnum << " " + "(" << getFunctionName((enum recFuncs)fnum) << ") " + "located at " << flist[fnum]; if (fnum < REC_FUNC_START_INDEX || fnum >= NUM_REC_FUNCTIONS) { FILE_LOG(logERROR) << "Unknown function enum " << fnum; @@ -429,7 +434,7 @@ void slsReceiverTCPIPInterface::functionNotImplemented() { } -int slsReceiverTCPIPInterface::M_nofunc(){ +int slsReceiverTCPIPInterface::M_nofunc(){printf("111 \n"); ret = FAIL; memset(mess, 0, sizeof(mess)); int n = 0; @@ -438,7 +443,7 @@ int slsReceiverTCPIPInterface::M_nofunc(){ while (n > 0) n = mySock->ReceiveDataOnly(mess,MAX_STR_LENGTH); - sprintf(mess,"Unrecognized Function\n"); + strcpy(mess,"Unrecognized Function. Please do not proceed.\n"); FILE_LOG(logERROR) << mess; // send ok / fail @@ -2758,3 +2763,60 @@ int slsReceiverTCPIPInterface::set_frames_per_file() { return ret; } + + + + + +int slsReceiverTCPIPInterface::check_version_compatibility() { + ret = OK; + memset(mess, 0, sizeof(mess)); + int64_t arg = -1; + int64_t retval = -1; + + // receive arguments + if (mySock->ReceiveDataOnly(&arg,sizeof(arg)) < 0 ) + return printSocketReadError(); + + + // execute action + FILE_LOG(logDEBUG1) << "Checking versioning compatibility with value " << arg; + + int64_t client_requiredVersion = arg; + int64_t rx_apiVersion = APIRECEIVER; + int64_t rx_version = getReceiverVersion(); + + // old client + if (rx_apiVersion > client_requiredVersion) { + ret = FAIL; + sprintf(mess,"This client is incompatible.\n" + "Client's receiver API Version: (0x%llx). Receiver API Version: (0x%llx).\n" + "Incompatible, update client!\n", + client_requiredVersion, rx_apiVersion); + FILE_LOG(logERROR) << mess; + } + + // old software + else if (client_requiredVersion > rx_version) { + ret = FAIL; + sprintf(mess,"This receiver is incompatible.\n" + "Receiver Version: (0x%llx). Client's receiver API Version: (0x%llx).\n" + "Incompatible, update receiver!\n", + rx_version, client_requiredVersion); + FILE_LOG(logERROR) << mess; + } + else FILE_LOG(logINFO) << "Compatibility with Client: Successful"; + + if (ret == OK && mySock->differentClients) + ret = FORCE_UPDATE; + + // send answer + mySock->SendDataOnly(&ret,sizeof(ret)); + if (ret == FAIL) + mySock->SendDataOnly(mess,sizeof(mess)); + mySock->SendDataOnly(&retval,sizeof(retval)); // sending crap (because of thisReceiver interface) + + // return ok/fail + return ret; +} + diff --git a/slsReceiverSoftware/updateAPIVersion.sh b/slsReceiverSoftware/updateAPIVersion.sh new file mode 100755 index 000000000..389b2929e --- /dev/null +++ b/slsReceiverSoftware/updateAPIVersion.sh @@ -0,0 +1,7 @@ +SRCFILE=include/gitInfoReceiver.h +DSTFILE=include/versionAPI.h + +SRCPATTERN=GITDATE +DSTPATTERN=APIRECEIVER + +awk -v a="$SRCFILE" -v b="$DSTFILE" -v c="$SRCPATTERN" -v d="$DSTPATTERN" 'FNR==NR&&$2==c{x=$3} NR!=FNR{if($2==d){$3="0x"substr(x,5)}print > b}' $SRCFILE $DSTFILE \ No newline at end of file