From b02587fd94c4e1b288aa59455ac502366fd68476 Mon Sep 17 00:00:00 2001 From: R3ABM Artem Date: Mon, 16 Jan 2023 08:07:57 +0000 Subject: [PATCH] Update Rewind.h, TellusAgent.c --- Rewind.h | 155 +++++++++++++++++++++++++++++++++++++++++++------- TellusAgent.c | 57 ++++++++++++------- 2 files changed, 170 insertions(+), 42 deletions(-) diff --git a/Rewind.h b/Rewind.h index 2b8951b..5fd875c 100644 --- a/Rewind.h +++ b/Rewind.h @@ -21,36 +21,57 @@ extern "C" #define REWIND_CLASS_SERVER_NOTICE 0x0200 #define REWIND_CLASS_DEVICE_DATA 0x0800 #define REWIND_CLASS_APPLICATION 0x0900 +#define REWIND_CLASS_TERMINAL 0x0a00 -#define REWIND_CLASS_KAIROS_DATA (REWIND_CLASS_DEVICE_DATA + 0x00) -#define REWIND_CLASS_HYTERA_DATA (REWIND_CLASS_DEVICE_DATA + 0x10) +#define REWIND_CLASS_KAIROS_DATA (REWIND_CLASS_DEVICE_DATA + 0x00) +#define REWIND_CLASS_HYTERA_DATA (REWIND_CLASS_DEVICE_DATA + 0x10) -#define REWIND_TYPE_KEEP_ALIVE (REWIND_CLASS_REWIND_CONTROL + 0) -#define REWIND_TYPE_CLOSE (REWIND_CLASS_REWIND_CONTROL + 1) -#define REWIND_TYPE_CHALLENGE (REWIND_CLASS_REWIND_CONTROL + 2) -#define REWIND_TYPE_AUTHENTICATION (REWIND_CLASS_REWIND_CONTROL + 3) +#define REWIND_TYPE_KEEP_ALIVE (REWIND_CLASS_REWIND_CONTROL + 0) +#define REWIND_TYPE_CLOSE (REWIND_CLASS_REWIND_CONTROL + 1) +#define REWIND_TYPE_CHALLENGE (REWIND_CLASS_REWIND_CONTROL + 2) +#define REWIND_TYPE_AUTHENTICATION (REWIND_CLASS_REWIND_CONTROL + 3) -#define REWIND_TYPE_REPORT (REWIND_CLASS_SYSTEM_CONSOLE + 0) +#define REWIND_TYPE_REDIRECTION (REWIND_CLASS_REWIND_CONTROL + 8) -#define REWIND_TYPE_BUSY_NOTICE (REWIND_CLASS_SERVER_NOTICE + 0) -#define REWIND_TYPE_ADDRESS_NOTICE (REWIND_CLASS_SERVER_NOTICE + 1) -#define REWIND_TYPE_BINDING_NOTICE (REWIND_CLASS_SERVER_NOTICE + 2) +#define REWIND_TYPE_REPORT (REWIND_CLASS_SYSTEM_CONSOLE + 0) -#define REWIND_TYPE_EXTERNAL_SERVER (REWIND_CLASS_KAIROS_DATA + 0) -#define REWIND_TYPE_REMOTE_CONTROL (REWIND_CLASS_KAIROS_DATA + 1) -#define REWIND_TYPE_SNMP_TRAP (REWIND_CLASS_KAIROS_DATA + 2) +#define REWIND_TYPE_BUSY_NOTICE (REWIND_CLASS_SERVER_NOTICE + 0) +#define REWIND_TYPE_ADDRESS_NOTICE (REWIND_CLASS_SERVER_NOTICE + 1) +#define REWIND_TYPE_BINDING_NOTICE (REWIND_CLASS_SERVER_NOTICE + 2) -#define REWIND_TYPE_PEER_DATA (REWIND_CLASS_HYTERA_DATA + 0) -#define REWIND_TYPE_RDAC_DATA (REWIND_CLASS_HYTERA_DATA + 1) -#define REWIND_TYPE_MEDIA_DATA (REWIND_CLASS_HYTERA_DATA + 2) +#define REWIND_TYPE_EXTERNAL_SERVER (REWIND_CLASS_KAIROS_DATA + 0) +#define REWIND_TYPE_REMOTE_CONTROL (REWIND_CLASS_KAIROS_DATA + 1) +#define REWIND_TYPE_SNMP_TRAP (REWIND_CLASS_KAIROS_DATA + 2) -#define REWIND_TYPE_SUBSCRIPTION (REWIND_CLASS_APPLICATION + 0x00) -#define REWIND_TYPE_DMR_DATA_BASE (REWIND_CLASS_APPLICATION + 0x10) -#define REWIND_TYPE_DMR_AUDIO_FRAME (REWIND_CLASS_APPLICATION + 0x20) +#define REWIND_TYPE_PEER_DATA (REWIND_CLASS_HYTERA_DATA + 0) +#define REWIND_TYPE_RDAC_DATA (REWIND_CLASS_HYTERA_DATA + 1) +#define REWIND_TYPE_MEDIA_DATA (REWIND_CLASS_HYTERA_DATA + 2) +#define REWIND_TYPE_XNMS_DATA (REWIND_CLASS_HYTERA_DATA + 3) + +#define REWIND_TYPE_CONFIGURATION (REWIND_CLASS_APPLICATION + 0x00) +#define REWIND_TYPE_SUBSCRIPTION (REWIND_CLASS_APPLICATION + 0x01) +#define REWIND_TYPE_CANCELLING (REWIND_CLASS_APPLICATION + 0x02) +#define REWIND_TYPE_SESSION_POLL (REWIND_CLASS_APPLICATION + 0x03) +#define REWIND_TYPE_DMR_DATA_BASE (REWIND_CLASS_APPLICATION + 0x10) +#define REWIND_TYPE_DMR_AUDIO_FRAME (REWIND_CLASS_APPLICATION + 0x20) +#define REWIND_TYPE_DMR_EMBEDDED_DATA (REWIND_CLASS_APPLICATION + 0x27) +#define REWIND_TYPE_SUPER_HEADER (REWIND_CLASS_APPLICATION + 0x28) +#define REWIND_TYPE_FAILURE_CODE (REWIND_CLASS_APPLICATION + 0x29) + +#define REWIND_TYPE_TERMINAL_IDLE (REWIND_CLASS_TERMINAL + 0x00) +#define REWIND_TYPE_TERMINAL_ATTACH (REWIND_CLASS_TERMINAL + 0x02) +#define REWIND_TYPE_TERMINAL_DETACH (REWIND_CLASS_TERMINAL + 0x03) +#define REWIND_TYPE_TERMINAL_WAKEUP (REWIND_CLASS_TERMINAL + 0x04) + +#define REWIND_TYPE_MESSAGE_TEXT (REWIND_CLASS_TERMINAL + 0x10) +#define REWIND_TYPE_MESSAGE_STATUS (REWIND_CLASS_TERMINAL + 0x11) +#define REWIND_TYPE_LOCATION_REPORT (REWIND_CLASS_TERMINAL + 0x20) +#define REWIND_TYPE_LOCATION_REQUEST (REWIND_CLASS_TERMINAL + 0x21) #define REWIND_FLAG_NONE 0 #define REWIND_FLAG_REAL_TIME_1 (1 << 0) #define REWIND_FLAG_REAL_TIME_2 (1 << 1) +#define REWIND_FLAG_BUFFERING (1 << 2) #define REWIND_FLAG_DEFAULT_SET REWIND_FLAG_NONE #define REWIND_ROLE_REPEATER_AGENT 0x10 @@ -59,6 +80,14 @@ extern "C" #define REWIND_SERVICE_CRONOS_AGENT (REWIND_ROLE_REPEATER_AGENT + 0) #define REWIND_SERVICE_TELLUS_AGENT (REWIND_ROLE_REPEATER_AGENT + 1) #define REWIND_SERVICE_SIMPLE_APPLICATION (REWIND_ROLE_APPLICATION + 0) +#define REWIND_SERVICE_OPEN_TERMINAL (REWIND_ROLE_APPLICATION + 1) + +#define REWIND_OPTION_SUPER_HEADER (1 << 0) +#define REWIND_OPTION_LINEAR_FRAME (1 << 1) + +#define REWIND_CALL_LENGTH 10 + +// Keep-Alive struct RewindVersionData { @@ -67,6 +96,23 @@ struct RewindVersionData char description[0]; // Software name and version }; +// Redirection + +union RewindAddress +{ + struct in_addr v4; + struct in6_addr v6; +}; + +struct RewindRedirectionData +{ + uint16_t family; // Address family: AF_INET, AF_INET6 or AF_UNSPEC + uint16_t port; // UDP port + union RewindAddress address; // +}; + +// Generic Data Structures + struct RewindAddressData { struct in_addr address; @@ -78,12 +124,79 @@ struct RewindBindingData uint16_t ports[0]; }; +struct RewindForwardData +{ + uint16_t port; + uint8_t data[0]; +}; + +// Simple Application Protocol + +struct RewindConfigurationData +{ + uint32_t options; // REWIND_OPTION_* +}; + struct RewindSubscriptionData { - uint32_t type; - uint32_t number; + uint32_t type; // SESSION_TYPE_* + uint32_t number; // Destination ID }; +struct RewindSessionPollData +{ + uint32_t type; // TREE_SESSION_* + uint32_t flag; // SESSION_FLAG_* + uint32_t number; // ID + uint32_t state; // +}; + +struct RewindSuperHeader +{ + uint32_t type; // SESSION_TYPE_* + uint32_t sourceID; // Source ID or 0 + uint32_t destinationID; // Destination ID or 0 + char sourceCall[REWIND_CALL_LENGTH]; // Source Call or zeros + char destinationCall[REWIND_CALL_LENGTH]; // Destination Call or zeros +}; + +// Open DMR Terminal + +struct RewindTextMessageData +{ + uint32_t reserved; // Reserved for future use, should be 0 + uint32_t sourceID; // Source ID + uint32_t destinationID; // Destination ID + uint16_t option; // CHEAD_GROUP_DESTINATION = 128, private message = 0 + uint16_t length; // Length of message in bytes + uint16_t data[0]; // Message text, UTF-16LE +}; + +struct RewindTextMessageStatus +{ + uint32_t reserved; // Reserved for future use, should be 0 + uint32_t sourceID; // Source ID + uint32_t destinationID; // Destination ID + uint8_t status; // STATUS_TYPE_*, corresponds to status field of DMR response header of data call +}; + +struct RewindLocationRequest +{ + uint32_t reserved; // Reserved for future use, should be 0 + uint32_t type; // LOCATION_REQUEST_SHOT = 0, LOCATION_REQUEST_TIMED_START = 1, LOCATION_REQUEST_TIMED_STOP = 2 + uint32_t interval; // Interval of timed report in seconds +}; + +struct RewindLocationReport +{ + uint32_t reserved; // Reserved for future use, should be 0 + uint32_t format; // LOCATION_FORMAT_NMEA = 0 + uint16_t length; // Length of message in bytes + char data[0]; // NMEA position data +}; + +// Rewind Transport Layer + struct RewindData { char sign[REWIND_SIGN_LENGTH]; diff --git a/TellusAgent.c b/TellusAgent.c index 86ccddb..547ce74 100644 --- a/TellusAgent.c +++ b/TellusAgent.c @@ -101,8 +101,8 @@ void print(const char* format, ...) int main(int argc, const char* argv[]) { print("\n"); - print("TellusAgent for BrandMeister DMR Master Server\n"); - print("Copyright 2016 Artem Prilutskiy (R3ABM, cyanide.burnout@gmail.com)\n"); + print("TellusAgent for BrandMeister Core\n"); + print("Copyright 2016-2023 Artem Prilutskiy (R3ABM, cyanide.burnout@gmail.com)\n"); print("Software revision " STRING(VERSION) " build " BUILD "\n"); print("\n"); @@ -185,7 +185,7 @@ int main(int argc, const char* argv[]) if (serviceMode & MODE_SYSLOG) { // Set proper origin for syslog (required by OpenWRT) - openlog("TellusAgent", LOG_NOWAIT | LOG_PID, LOG_USER); + openlog("TellusAgent", LOG_NOWAIT | LOG_PID, LOG_USER); } #ifdef __linux__ @@ -199,7 +199,7 @@ int main(int argc, const char* argv[]) #ifdef __MACH__ if (serviceMode & MODE_DAEMON) { - launch_data_t request = launch_data_new_string(LAUNCH_KEY_CHECKIN); + launch_data_t request = launch_data_new_string(LAUNCH_KEY_CHECKIN); launch_data_t response = launch_msg(request); launch_data_free(request); if (response == NULL) @@ -231,11 +231,11 @@ int main(int argc, const char* argv[]) hints.ai_socktype = SOCK_DGRAM; #ifdef __linux__ - hints.ai_flags = AI_ADDRCONFIG; + hints.ai_flags = AI_ADDRCONFIG; hints.ai_family = AF_UNSPEC; #endif #ifdef __MACH__ - hints.ai_flags = AI_V4MAPPED; + hints.ai_flags = AI_V4MAPPED; hints.ai_family = AF_INET6; #endif @@ -260,7 +260,7 @@ int main(int argc, const char* argv[]) int handle; proxySocketAddress.sin_port = proxyPorts[selection]; - handle = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); + handle = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP); if ((handle < 0) || (bind(handle, (struct sockaddr*)&proxySocketAddress, proxySocketLength) < 0)) @@ -277,12 +277,12 @@ int main(int argc, const char* argv[]) int uplinkHandle; struct sockaddr_in6 uplinkSocketAddress; - uplinkSocketAddress.sin6_family = AF_INET6; - uplinkSocketAddress.sin6_addr = in6addr_any; - uplinkSocketAddress.sin6_port = 0; + uplinkSocketAddress.sin6_family = AF_INET6; + uplinkSocketAddress.sin6_addr = in6addr_any; + uplinkSocketAddress.sin6_port = 0; uplinkSocketAddress.sin6_scope_id = 0; - uplinkHandle = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP); + uplinkHandle = socket(PF_INET6, SOCK_DGRAM, IPPROTO_UDP); if ((uplinkHandle < 0) || (bind(uplinkHandle, (struct sockaddr*)&uplinkSocketAddress, sizeof(uplinkSocketAddress)) < 0)) { @@ -310,7 +310,7 @@ int main(int argc, const char* argv[]) int pollHandle; struct epoll_event event; - + pollHandle = epoll_create(EVENT_LIST_LENGTH); event.events = EPOLLIN; @@ -419,7 +419,7 @@ int main(int argc, const char* argv[]) if (watchDog > WATCH_THRESHOLD) { print("Server connection timed out\n"); - break; + break; } for (size_t index = 0; index < count; index ++) @@ -437,7 +437,7 @@ int main(int argc, const char* argv[]) { struct sockaddr_in6 address; socklen_t size = sizeof(address); - size_t length = recvfrom(uplinkHandle, incomingBuffer, BUFFER_SIZE, 0, (struct sockaddr*)&address, &size); + size_t length = recvfrom(uplinkHandle, incomingBuffer, BUFFER_SIZE, 0, (struct sockaddr*)&address, &size); if ((length >= sizeof(struct RewindData)) && ((serverAddress->ai_addr->sa_family == AF_INET) || /* Work-around for Linux */ @@ -456,13 +456,28 @@ int main(int argc, const char* argv[]) struct sockaddr_in* address; selection = type - REWIND_TYPE_PEER_DATA; - address = repeaterSocketAddresses + selection; - handle = proxyHandles[selection]; + address = repeaterSocketAddresses + selection; + handle = proxyHandles[selection]; sendto(handle, incomingBuffer->data, length, 0, (struct sockaddr*)address, sizeof(struct sockaddr_in)); continue; } + if (type == REWIND_TYPE_XNMS_DATA) + { + struct sockaddr_in* address; + struct RewindForwardData* data; + + data = (struct RewindForwardData*)incomingBuffer->data; + length -= sizeof(struct RewindForwardData); + address = repeaterSocketAddresses + 1; + + address->sin_port = data->port; + + sendto(proxyHandles[1], data->data, length, 0, (struct sockaddr*)address, sizeof(struct sockaddr_in)); + continue; + } + if (type == REWIND_TYPE_REPORT) { incomingBuffer->data[length] = '\0'; @@ -488,7 +503,7 @@ int main(int argc, const char* argv[]) watchDog ++; - outgoingBuffer->type = htole16(REWIND_TYPE_BINDING_NOTICE); + outgoingBuffer->type = htole16(REWIND_TYPE_BINDING_NOTICE); outgoingBuffer->length = htole16(sizeof(proxyPorts)); vectors[0].iov_base = outgoingBuffer; @@ -511,12 +526,12 @@ int main(int argc, const char* argv[]) int handle = proxyHandles[selection]; if (CHECK(event, handle)) { - socklen_t size = sizeof(struct sockaddr_in); - uint8_t* buffer = (uint8_t*)outgoingBuffer->data; + socklen_t size = sizeof(struct sockaddr_in); + uint8_t* buffer = (uint8_t*)outgoingBuffer->data; struct sockaddr_in* address = repeaterSocketAddresses + selection; - size_t length = recvfrom(handle, buffer, BUFFER_SIZE, 0, (struct sockaddr*)address, &size); + size_t length = recvfrom(handle, buffer, BUFFER_SIZE, 0, (struct sockaddr*)address, &size); - outgoingBuffer->type = htole16(REWIND_CLASS_HYTERA_DATA + selection); + outgoingBuffer->type = htole16(REWIND_CLASS_HYTERA_DATA + selection); outgoingBuffer->length = htole16(length); length += sizeof(struct RewindData);