//| Copyright: (C) 2020-2024 Kevin Larke //| License: GNU GPL version 3.0 or above. See the accompanying LICENSE file. #include "cwCommon.h" #include "cwLog.h" #include "cwCommonImpl.h" #include "cwTest.h" #include "cwMem.h" #include "cwObject.h" #include "cwTime.h" #include "cwThread.h" #include "cwSocket.h" #include "cwUtility.h" #include "cwEuCon.h" #include "cwText.h" #include "cwNumericConvert.h" #include "dns_sd/dns_sd_const.h" #include "cwEuConDecls.h" #define HEART_BEAT "\x04\x00\x00\x00" #define RESPONSE_1 "\x0a\x00\x00\x00\x6d\x62\x70\x31\x39\x00\x00\x00\x44\x45" \ "\x00\x00\x78\x3f\x39\xe5\xfe\x7f\x00\x00\xc0\x32\x17\x49\xe2\x7f" \ "\x00\x00\xe0\x7d\x2e\x01\x00\x60\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x02\x01\xa8\x03\x00\x60\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x8d\x00\x1f\x0a\xbe\xbd\xea\x31\xf9\x88\xc5\x46\xe2\x7f" \ "\x00\x00\x08\x00\x00\x00\x00\x00\x02\x58" #define RESPONSE_2 "\x0c\x00\x1f\x0a" #define RESPONSE_3_A "\x19\x00\x06\x00\x00\x00\x04\x14\x00\x00\x00\x00\x00\x80" \ "\x00\x40\x00\x00\x20\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x54\x02\x00\x02" \ "\x00\x02\x00\x02\x00\x02\x00\x02\x00\x02\x00\x02\x00\x02\x00\x02" \ "\x00\x02\x00\x02\x00\x02\x00\x02\x00\x02\x00\x02\x00\x02\x00\x02" \ "\x00\x02\x00\x02\x00\x02\x00\x02\x00\x02\x00\x02\x00\x02\x00\x02" \ "\x00\x02\x00\x02\x00\x02\x00\x02\x00\x02\x00\x02\x00\x02\x00\x02" \ "\x00\x02\x00\x02\x00\x02\x00\x02\xa8\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0d\x00\x08\x00" \ "\x08\x00\x08\x00\x08\x00\x08\x00\x08\x00\x08\x00\x08\x00\x08\x00" \ "\x08\x00\x08\x00\x08\x00\x08\x00\x08\x00\x08\x00\x08\x00\x08\x00" \ "\x08\x00\x08\x00\x08\x00\x08\x00\x08\x00\x08\x00\x08\x00\x08\x00" \ "\x08\x00\x08\x00\x08\x00\x08\x00\x08\x00\x08\x00\x08\x00\x08\x00" \ "\x08\x00\x08\x00\x08\x00\x08\x00\x0a\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x19\x01\x06\x00\x00\x00\x04\x14\x00\x00" \ "\x00\x00\x00\x80\x00\x40\x00\x00\x20\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" #define RESPONSE_3_B "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x54\x02\x00\x02\x00\x02\x00\x02" \ "\x00\x02\x00\x02\x00\x02\x00\x02\x00\x02\x00\x02\x00\x02\x00\x02" \ "\x00\x02\x00\x02\x00\x02\x00\x02\x00\x02\x00\x02\x00\x02\x00\x02" \ "\x00\x02\x00\x02\x00\x02\x00\x02\x00\x02\x00\x02\x00\x02\x00\x02" \ "\x00\x02\x00\x02\x00\x02\x00\x02\x00\x02\x00\x02\x00\x02\x00\x02" \ "\x00\x02\x00\x02\xa8\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x0d\x00\x08\x00\x08\x00\x08\x00" \ "\x08\x00\x08\x00\x08\x00\x08\x00\x08\x00\x08\x00\x08\x00\x08\x00" \ "\x08\x00\x08\x00\x08\x00\x08\x00\x08\x00\x08\x00\x08\x00\x08\x00" \ "\x08\x00\x08\x00\x08\x00\x08\x00\x08\x00\x08\x00\x08\x00\x08\x00" \ "\x08\x00\x08\x00\x08\x00\x08\x00\x08\x00\x08\x00\x08\x00\x08\x00" \ "\x08\x00\x08\x00\x0a\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00" #define RESPONSE_4_A "\x19\x02\x06\x00\x00\x00\x04\x14\x00\x00\x00\x00\x00\x80" \ "\x00\x40\x00\x00\x20\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x54\x02\x00\x02" \ "\x00\x02\x00\x02\x00\x02\x00\x02\x00\x02\x00\x02\x00\x02\x00\x02" \ "\x00\x02\x00\x02\x00\x02\x00\x02\x00\x02\x00\x02\x00\x02\x00\x02" \ "\x00\x02\x00\x02\x00\x02\x00\x02\x00\x02\x00\x02\x00\x02\x00\x02" \ "\x00\x02\x00\x02\x00\x02\x00\x02\x00\x02\x00\x02\x00\x02\x00\x02" \ "\x00\x02\x00\x02\x00\x02\x00\x02\xa8\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0d\x00\x08\x00" \ "\x08\x00\x08\x00\x08\x00\x08\x00\x08\x00\x08\x00\x08\x00\x08\x00" \ "\x08\x00\x08\x00\x08\x00\x08\x00\x08\x00\x08\x00\x08\x00\x08\x00" \ "\x08\x00\x08\x00\x08\x00\x08\x00\x08\x00\x08\x00\x08\x00\x08\x00" \ "\x08\x00\x08\x00\x08\x00\x08\x00\x08\x00\x08\x00\x08\x00\x08\x00" \ "\x08\x00\x08\x00\x08\x00\x08\x00\x0a\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x19\x03\x06\x00\x00\x00\x04\x14\x00\x00" \ "\x00\x00\x00\x80\x00\x40\x00\x00\x20\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" #define RESPONSE_4_B "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x54\x02\x00\x02\x00\x02\x00\x02" \ "\x00\x02\x00\x02\x00\x02\x00\x02\x00\x02\x00\x02\x00\x02\x00\x02" \ "\x00\x02\x00\x02\x00\x02\x00\x02\x00\x02\x00\x02\x00\x02\x00\x02" \ "\x00\x02\x00\x02\x00\x02\x00\x02\x00\x02\x00\x02\x00\x02\x00\x02" \ "\x00\x02\x00\x02\x00\x02\x00\x02\x00\x02\x00\x02\x00\x02\x00\x02" \ "\x00\x02\x00\x02\xa8\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x0d\x00\x08\x00\x08\x00\x08\x00" \ "\x08\x00\x08\x00\x08\x00\x08\x00\x08\x00\x08\x00\x08\x00\x08\x00" \ "\x08\x00\x08\x00\x08\x00\x08\x00\x08\x00\x08\x00\x08\x00\x08\x00" \ "\x08\x00\x08\x00\x08\x00\x08\x00\x08\x00\x08\x00\x08\x00\x08\x00" \ "\x08\x00\x08\x00\x08\x00\x08\x00\x08\x00\x08\x00\x08\x00\x08\x00" \ "\x08\x00\x08\x00\x0a\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00" namespace cw { namespace eucon { enum { kSendHandshake_0_Id, // send [0x0a, ...] kWaitForHandshake_1_Id, // wait for first heart beat -> then send [0x0c ...] kWaitForHandshake_2_Id, // wait for [0x0d ...] -> then send response_3_a kResponse_3_A_Id, kResponse_3_B_Id, kResponse_4_A_Id, kResponse_4_B_Id, kRunning_Id }; struct eucon_str; typedef struct { bool muteFl; } ch_t; // FBank object typedef struct fbank_str { struct eucon_str* eucon; unsigned fbIndex; unsigned sockUserId; unsigned protoState; unsigned cbCnt; time::spec_t nextRecvHbTs; time::spec_t nextSendHbTs; struct fbank_str* link; uint32_t remoteAddr; ch_t* chA; unsigned chN; } fbank_t; // EuCon manager object typedef struct eucon_str { sock::handle_t sockMgrH; // socket mgr handle fbank_t* fbankL; // List of fader banks unsigned maxFaderBankN; // maximum number of fader banks unsigned sockTimeOutMs; // socket time out unsigned fdrTcpPort; // Fader TCP port TODO: we shouuld be getting this from the MDNS SRV record unsigned heartBeatPeriodMs; } eucon_t; inline eucon_t* _handleToPtr( handle_t h ) { return handleToPtr(h); } rc_t _destroyFBank( eucon_t* p, fbank_t* fb ) { rc_t rc = kOkRC; if((rc = sock::destroy(p->sockMgrH, fb->sockUserId )) != kOkRC ) rc = cwLogError(rc,"Fader bank (index:%i) destroy failed.", fb->fbIndex ); return rc; } rc_t _destroy( eucon_t* p) { rc_t rc = kOkRC; rc_t rc0; fbank_t* fb = p->fbankL; while( fb!=nullptr ) { fbank_t* fb0 = fb->link; if((rc0 = _destroyFBank(p,fb)) != kOkRC ) rc = rc0;; mem::release(fb); fb = fb0; } if( p->sockMgrH.isValid() ) if((rc = sock::destroyMgr(p->sockMgrH)) != kOkRC ) return rc; mem::release(p); return rc; } rc_t _disconnect( fbank_t* fb ) { rc_t rc = kOkRC; //if((rc = sock::destroy(fb->eucon->sockMgrH, fb->sockUserId)) != kOkRC ) // rc = cwLogError(rc,"Socket destroy failed on disconnect attempt on fader bank index:%i.",fb->fbIndex); fb->protoState = kSendHandshake_0_Id; return rc; } rc_t _send_response( fbank_t* fb, const char* buf, unsigned bufByteN ) { rc_t rc = kOkRC; if((rc = sock::send( fb->eucon->sockMgrH, fb->sockUserId, kInvalidId, buf, bufByteN )) != kOkRC ) { rc = cwLogError(rc,"TCP send failed on fader bank index:%i proto:%i Disconnecting.",fb->fbIndex,fb->protoState); _disconnect(fb); } return rc; } rc_t _sendHandshake_0( fbank_t* fb ) { printf("%i : Sent HS-0: 0x0a\n", fb->fbIndex); return _send_response(fb,RESPONSE_1,sizeof(RESPONSE_1)-1); } rc_t _sendHandshake_1( fbank_t* fb ) { return _send_response(fb,RESPONSE_2,sizeof(RESPONSE_2)-1); } rc_t _send_app_msg( fbank_t* fb, uint16_t chIdx, uint16_t msgTypeId, uint16_t value ) { if( fb->protoState != kRunning_Id ) return kOkRC; typedef struct fields_str { uint16_t channel; uint16_t typeId; uint16_t zero; uint16_t value; } fields_t; typedef struct { union { uint8_t buf[8]; fields_t f; } u; } buf_t; uint16_t v = value; buf_t b; b.u.f.channel = chIdx; b.u.f.typeId = msgTypeId; b.u.f.zero = 0; b.u.f.value = ((v & 0xff00) >> 8) + ((v & 0x00ff) << 8); return _send_response(fb,(char*)(b.u.buf),sizeof(b.u.buf)); } fbank_t* _createFBank( eucon_t* p, unsigned fbIndex ) { fbank_t* fb = mem::allocZ(); fb->eucon = p; fb->fbIndex = fbIndex; fb->sockUserId = kBaseSockUserId + fbIndex; fb->protoState = kSendHandshake_0_Id; fb->link = p->fbankL; fb->chN = 8; fb->chA = mem::allocZ(fb->chN); p->fbankL = fb; return fb; } fbank_t* _fbIndexToFBank( eucon_t* p, unsigned fbIndex, bool showErrorFl=true ) { fbank_t* fb = p->fbankL; for(; fb!=nullptr; fb=fb->link) if( fb->fbIndex == fbIndex ) return fb; if( showErrorFl ) cwLogError(kInvalidId,"Fader bank index %i is not valid.", fbIndex ); return nullptr; } fbank_t* _ipAddrToFBank( eucon_t* p, uint32_t ipAddr, bool showErrorFl=true ) { fbank_t* fb = p->fbankL; for(; fb!=nullptr; fb=fb->link) if( fb->remoteAddr == ipAddr ) return fb; if( showErrorFl ) cwLogError(kInvalidId,"Fader bank with dest. addr 0x%x was not found.", ipAddr ); return nullptr; } // Heatbeat: 0x03 0x00 0x00 0x00 // // channel status zero value // --------- --------- --------- --------- // 0x00 0x01 0x00 0x00 0x00 0x00 0x02 0x0b fader // 0x00 0x01 0x02 0x00 0x00 0x00 0x00 0x01 mute // 0x00 0x01 0x00 0x01 0x00 0x00 0x00 0x00 touch // 0x00 0x01 0x04 0x00 0x00 0x00 0x00 0x00 ping void _app_msg_decode(eucon_t* p, fbank_t* fb, const uint8_t* buf, unsigned bufByteN ) { unsigned bi = 0; while( bichA[chIdx].muteFl = !fb->chA[chIdx].muteFl; if(_send_app_msg(fb, chIdx, kEucMuteEuconId, !fb->chA[chIdx].muteFl ) != kOkRC ) cwLogError(kOpFailRC,"Send mute msg failed."); } break; case kPingEuconId: type = 'P'; _send_response(fb,(const char*)(buf+bi),8); break; default: incr = 1; } } if( type != 'H' ) printf("%i %i : %c (0x%x) %i (0x%x)\n",fb->fbIndex, chIdx, type,id,numb,numb); bi += incr; } } void _tcpCallback( void* arg, sock::cbOpId_t cbOpId, unsigned userId, unsigned connId, const void* data, unsigned dataByteCnt, const struct sockaddr_in* fromAddr ) { eucon_t* p = static_cast(arg); fbank_t* fb; switch( cbOpId ) { case sock::kConnectCbId: cwLogInfo("Connected: user:%i conn:%i", userId, connId ); return; case sock::kDisconnectCbId: cwLogInfo("Disconnected: user:%i conn:%i", userId, connId ); return; case sock::kReceiveCbId: break; default: cwLogError(kInvalidIdRC,"An invalid socket callback id (%i) was received.",cbOpId); return; } // get the fader bank this message is intended for if((fb = _ipAddrToFBank( p, fromAddr->sin_addr.s_addr )) == nullptr ) { cwLogError(kOpFailRC,"Fader bank not found. TCP message not delivered."); return; } // if( data!=nullptr && dataByteCnt >= 4 ) { //printHex(data,dataByteCnt); unsigned hdr = *(const unsigned*)data; switch( fb->protoState ) { case kWaitForHandshake_1_Id: if( hdr == kHs1_b_EuProtoId ) { fb->protoState = kWaitForHandshake_2_Id; _sendHandshake_1( fb ); cwLogInfo("%i : Rcvd (0x0b) HS 1 - sent 0x0c\n", fb->fbIndex); } break; case kWaitForHandshake_2_Id: if( hdr == kHs3_d_EuProtoId ) { fb->protoState = kResponse_3_A_Id; cwLogInfo("%i : Rcvd (0x0d) HS 2 - Sending setup data\n",fb->fbIndex); } break; } } switch(fb->protoState) { case kResponse_3_A_Id: _send_response(fb,RESPONSE_3_A,sizeof(RESPONSE_3_A)-1); fb->protoState = kResponse_3_B_Id; break; case kResponse_3_B_Id: _send_response(fb,RESPONSE_3_B,sizeof(RESPONSE_3_B)-1); fb->protoState = kResponse_4_A_Id; break; case kResponse_4_A_Id: _send_response(fb,RESPONSE_4_A,sizeof(RESPONSE_4_A)-1); fb->protoState = kResponse_4_B_Id; break; case kResponse_4_B_Id: _send_response(fb,RESPONSE_4_B,sizeof(RESPONSE_4_B)-1); fb->protoState = kRunning_Id; // set the initial next heart-beat times for this fader bank time::futureMs(fb->nextSendHbTs,fb->eucon->heartBeatPeriodMs); break; case kRunning_Id: { _app_msg_decode(p, fb, (const uint8_t*)data, dataByteCnt ); //printf("%i : Rcv: %i : ",fb->fbIndex, dataByteCnt ); //for(unsigned i=0; ifbIndex,fb->protoState); time::futureMs(fb->nextRecvHbTs,fb->eucon->heartBeatPeriodMs*2); } rc_t _on_McMix_DNS_SD_TXT( eucon_t* p, const char* numberText, unsigned numberTextCharN, const struct sockaddr_in* fromAddr ) { rc_t rc = kOkRC; unsigned tcpFlags = sock::kTcpFl | sock::kBlockingFl | sock::kStreamFl | sock::kReuseAddrFl | sock::kReusePortFl; fbank_t* fb = nullptr; unsigned fbIndex = 0; char fbIP[ INET_ADDRSTRLEN+1 ]; // copy the "MC Mix" suffix number into a zero terminated string char numbBuf[ numberTextCharN + 1 ]; strncpy(numbBuf,numberText,numberTextCharN); numbBuf[numberTextCharN] = '\0'; // convert the "MC Mix" suffix to a number if((rc = string_to_number(numbBuf,fbIndex)) != kOkRC ) return cwLogError(kSyntaxErrorRC,"The 'MC Mix' suffix number could not be parsed."); // validate the value if( !(0 < fbIndex && fbIndex <= p->maxFaderBankN ) ) return cwLogError(kInvalidArgRC,"The fader bank number %i is not valid.", fbIndex ); // convert fbIndex to a zero based index fbIndex -= 1; // If this fader bank does not already exist .... if((fb = _fbIndexToFBank(p,fbIndex,false)) == nullptr ) { // ... then create it if((fb = _createFBank(p,fbIndex)) == nullptr ) return cwLogError(kOpFailRC,"The fader bank index %i failed.", fbIndex ); } if( fb->protoState == kSendHandshake_0_Id ) { // convert the fromAddr to a string if((rc = sock::addrToString( fromAddr, fbIP, INET_ADDRSTRLEN)) != kOkRC ) return cwLogError(rc,"IP address to string conversion failed.", fbIndex); // create the TCP socket if((rc = sock::create( p->sockMgrH, fb->sockUserId, sock::kInvalidPortNumber, tcpFlags, p->sockTimeOutMs, _tcpCallback, p, fbIP, p->fdrTcpPort )) != kOkRC ) return cwLogError(rc,"The TCP socket for fader bank index %i failed. ", fbIndex); fb->remoteAddr = fromAddr->sin_addr.s_addr; time::futureMs(fb->nextRecvHbTs,fb->eucon->heartBeatPeriodMs*2); // Send the initial handshake to the fader bank _sendHandshake_0( fb ); fb->protoState = kWaitForHandshake_1_Id; } return rc; } void _udpCallback( void* arg, sock::cbOpId_t cbId, unsigned userId, unsigned connId, const void* data, unsigned dataByteCnt, const struct sockaddr_in* fromAddr ) { rc_t rc = kOkRC; eucon_t* p = (eucon_t*)arg; const uint16_t* u = (const uint16_t*)data; // if this is a DNS-SD reply if( cwIsFlag(ntohs(u[1]), kReplyHdrDnsFl ) ) { const char* name = (const char*)(u+6); const char* label = "MC Mix - "; unsigned sn = strlen(label); printf("%.*s|%i\n", name[0], name+1, sn ); // if this a 'MC Mix' DNS-SD SRV reply if( strncmp(label, name+1, strlen(label)) == 0 ) { unsigned n = strlen(label); if((rc = _on_McMix_DNS_SD_TXT( p, name+n+1, name[0]-n, fromAddr )) != kOkRC ) cwLogError(rc,"%.*s initialization failed.",name[0],name+1); } } } } } cw::rc_t cw::eucon::create( handle_t& hRef, const args_t& args ) { rc_t rc = kOkRC; unsigned udpFlags = sock::kBlockingFl | sock::kReuseAddrFl | sock::kReusePortFl | sock::kMultiCastTtlFl | sock::kMultiCastLoopFl; if((rc = destroy(hRef)) != kOkRC ) return rc; eucon_t* p = mem::allocZ(); // create the socket manager if((rc = sock::createMgr(p->sockMgrH, args.recvBufByteN, args.maxSockN)) != kOkRC ) { rc = cwLogError(rc,"Socket manager create failed during eucon mgr. allocation."); goto errLabel; } // create the MDNS/DNS SD UDP socket if((rc = sock::create( p->sockMgrH, kUdpSockUserId, args.mdnsPort, udpFlags, args.sockTimeOutMs, _udpCallback, p )) != kOkRC ) { rc = cwLogError(rc,"The Eucon controller UDP socket creation failed. "); goto errLabel; } // add the mDNS socket to the multicast group if((rc = join_multicast_group( p->sockMgrH, kUdpSockUserId, args.mdnsIP )) != kOkRC ) { rc = cwLogError(rc,"The Eucon controller UDP socket could not be added to the multicast group. "); goto errLabel; } // set the TTL for multicast if((rc = set_multicast_time_to_live( p->sockMgrH, kUdpSockUserId, 255 )) != kOkRC ) { rc = cwLogError(rc,"The multicast assignment to Eucon controller UDP socket failed. "); goto errLabel; } p->maxFaderBankN = args.maxFaderBankN; p->sockTimeOutMs = args.sockTimeOutMs; p->fdrTcpPort = args.fdrTcpPort; p->heartBeatPeriodMs = args.heartBeatPeriodMs; hRef.set(p); errLabel: if( rc != kOkRC ) _destroy(p); return rc; } cw::rc_t cw::eucon::destroy( handle_t& hRef ) { rc_t rc = kOkRC; if( !hRef.isValid() ) return rc; eucon_t* p = _handleToPtr(hRef); if((rc = _destroy(p)) != kOkRC ) return rc; hRef.clear(); return rc; } cw::rc_t cw::eucon::exec( handle_t h, unsigned sockTimeOutMs ) { rc_t rc = kOkRC; eucon_t* p = _handleToPtr(h); unsigned totalReadByteN = 0; time::spec_t t0; // poll sockets for incoming EuCon messages if((rc = sock::receive_all(p->sockMgrH, sockTimeOutMs, totalReadByteN )) != kOkRC ) return rc; switch( rc ) { case kOkRC: case kTimeOutRC: rc = kOkRC; break; default: rc = cwLogError(rc,"EuCon network receive failed."); }; // get the current time time::get(t0); // check the health of each fader bank for(fbank_t* fb = p->fbankL; fb!=nullptr; fb=fb->link) if( fb->protoState != kSendHandshake_0_Id ) { // has it been more than 'heartBeatPerioMs' millisecnods since we received a msg from this fader bank if( time::isGTE( t0, fb->nextRecvHbTs ) ) { cwLogInfo("Missed heart-beat disconnecting fader bank index %i.",fb->fbIndex ); _disconnect(fb); } // is it time to send a heart-beat to this fader bank if( time::isGTE( t0, fb->nextSendHbTs ) ) { _send_response( fb, HEART_BEAT, sizeof(HEART_BEAT)-1 ); time::futureMs(fb->nextSendHbTs,fb->eucon->heartBeatPeriodMs); } } return rc; } bool cw::eucon::areMsgsWaiting( handle_t h ) { //eucon_t* p = _handleToPtr(h); return false; } cw::rc_t cw::eucon::getMsgs( handle_t h, msgCallback_t cbFunc, void* cbArg ) { rc_t rc = kOkRC; //eucon_t* p = _handleToPtr(h); return rc; } cw::rc_t cw::eucon::sendMsg( handle_t h, unsigned fbIndex, unsigned fbChIndex, unsigned msgTypeId, unsigned value ) { rc_t rc = kOkRC; eucon_t* p = _handleToPtr(h); fbank_t* fb = p->fbankL; while( fb != nullptr ) if( fb->fbIndex == fbIndex ) { rc = _send_app_msg(fb, fbChIndex, msgTypeId, value ); break; } return rc; } namespace cw { namespace eucon { typedef struct app_str { bool quitFl; handle_t h; thread::handle_t thH; unsigned sockTimeOutMs; } app_t; bool appThreadFunc( void* arg ) { app_t* app = static_cast(arg); exec(app->h,app->sockTimeOutMs); return true; } rc_t appBegin( const args_t& args, app_t& app ) { rc_t rc = kOkRC; // Create the EuCon controller if((rc = create( app.h, args )) != kOkRC ) return cwLogError(rc,"Unable to create EuCon server."); // Create the application thread if((rc = thread::create( app.thH, appThreadFunc, &app, "eu_con" )) != kOkRC ) return cwLogError(rc,"App thread create failed."); // Start the application thread if((rc = thread::unpause( app.thH )) != kOkRC ) return cwLogError(rc,"App thread start failed."); app.sockTimeOutMs = args.sockTimeOutMs; return rc; } rc_t appEnd( app_t& app ) { rc_t rc = kOkRC; // Destroy the application thread if((rc = thread::destroy(app.thH)) != kOkRC ) cwLogError(rc,"EuCon app thread destroy failed."); // Destroy the EuCon controller if((rc = destroy(app.h)) != kOkRC ) cwLogError(rc,"Eucon app object destroy failed."); return rc; } } } cw::rc_t cw::eucon::test() { rc_t rc = kOkRC; app_t app; args_t args; const unsigned sbufN = 31; char sbuf[ sbufN+1 ]; memset(&args,0,sizeof(app)); args.recvBufByteN = 4096; args.mdnsIP = "224.0.0.251"; args.mdnsPort = 5353; args.sockTimeOutMs = 50; args.maxFaderBankN = 8; args.fdrTcpPort = 49168; args.maxSockN = 50; args.heartBeatPeriodMs = 4000; if((rc = appBegin(args,app)) != kOkRC ) return 1; printf("'quit' to exit\n"); // readline loop while( true ) { printf("? "); if( std::fgets(sbuf,sbufN,stdin) == sbuf ) { printf("Sending:%s",sbuf); if( strcmp(sbuf,"quit\n") == 0) break; } } appEnd(app); return rc; }