From 4ea54ae61aa3d019848d5958fb08503e34fa052d Mon Sep 17 00:00:00 2001 From: cyanide-burnout Date: Fri, 8 Jul 2016 15:25:19 +0400 Subject: [PATCH] Updated to support brand new External Server Interface --- CronosAgent.c | 183 +++++++++++++++++++++++++++------------------- Makefile | 15 ++-- Rewind.h | 21 ++++-- cronosagent.plist | 2 + cronosagent.sh | 2 +- 5 files changed, 129 insertions(+), 94 deletions(-) diff --git a/CronosAgent.c b/CronosAgent.c index 14576e6..c5bf5cf 100644 --- a/CronosAgent.c +++ b/CronosAgent.c @@ -45,11 +45,11 @@ #define ASN_CONSTRUCTOR 0x20 #endif -// #include "RA-RTP.h" -#ifndef RA_RTP_H -#define RTP_PROTOCOL_VERSION 2 -#define RTP_CONTROL_VERSION_SHIFT 6 -#define RTP_HEADER_MINIMAL_LENGTH 12 +// #include "KAIROS-HAM.h" +#ifndef KAIROS_HAM_H +#define KAIROS_HAM_DEFAULT_PORT 65472 +#define KAIROS_HAM_RECORD_ID 0xcbfaded8 +#define KAIROS_EXCHANGE_HEADER_LENGTH 12 #endif // #include "RemoteControl.h" @@ -99,8 +99,7 @@ #define MODE_SYSLOG (1 << 1) #define MODE_DAEMON (1 << 2) -#define MEDIA_PORT_COUNT (REWIND_TYPE_ANALOG_DATA - REWIND_TYPE_SLOT_1_VOICE + 1) -#define EVENT_LIST_LENGTH (4 + 1 + 3 + MEDIA_PORT_COUNT) +#define EVENT_LIST_LENGTH (4 + 1 + 4) #define BUFFER_SIZE 4096 #define EXPIRATION_TIME 20 @@ -136,7 +135,7 @@ int main(int argc, const char* argv[]) // Parameters of repeater int proxyTrapPort = 162; - int proxyBasePort = 40000; + int proxyMediaPort = KAIROS_HAM_DEFAULT_PORT; uint32_t repeaterNumber = 0; int repeaterControlPort = REMOTE_DEFAULT_PORT; @@ -155,7 +154,7 @@ int main(int argc, const char* argv[]) { "server-password", required_argument, NULL, 'w' }, { "server-address", required_argument, NULL, 's' }, { "server-port", required_argument, NULL, 'p' }, - { "base-port", required_argument, NULL, 'b' }, + { "media-port", required_argument, NULL, 'b' }, { "trap-port", required_argument, NULL, 't' }, { "service-mode", required_argument, NULL, 'm' }, { NULL, 0, NULL, 0 } @@ -190,7 +189,7 @@ int main(int argc, const char* argv[]) break; case 'b': - proxyBasePort = strtol(optarg, NULL, 10); + proxyMediaPort = strtol(optarg, NULL, 10); break; case 't': @@ -215,8 +214,8 @@ int main(int argc, const char* argv[]) " --repeater-port \n" " --server-password \n" " --server-address \n" - " --server-port \n" - " --base-port \n" + " --server-port \n" + " --media-port \n" " --trap-port \n" " --service-mode \n" " bit 0 - print to standard output\n" @@ -287,8 +286,8 @@ int main(int argc, const char* argv[]) // Initialize proxy sockets int trapHandle; + int mediaHandle; int remoteHandle; - int mediaHandles[MEDIA_PORT_COUNT]; struct sockaddr_in proxySocketAddress; proxySocketAddress.sin_family = AF_INET; @@ -312,17 +311,13 @@ int main(int argc, const char* argv[]) return EXIT_FAILURE; } - for (size_t index = 0; index < MEDIA_PORT_COUNT; index ++) + proxySocketAddress.sin_port = htons(proxyMediaPort); + mediaHandle = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); + if((mediaHandle < 0) || + (bind(mediaHandle, (struct sockaddr*)&proxySocketAddress, sizeof(proxySocketAddress)) < 0)) { - proxySocketAddress.sin_port = htons(proxyBasePort + index * 10); - int handle = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); - if((handle < 0) || - (bind(handle, (struct sockaddr*)&proxySocketAddress, sizeof(proxySocketAddress)) < 0)) - { - print("Error opening port for RTP Media\n"); - return EXIT_FAILURE; - } - mediaHandles[index] = handle; + print("Error opening port for KAIROS External Server\n"); + return EXIT_FAILURE; } // Initialize uplink socket @@ -343,6 +338,11 @@ int main(int argc, const char* argv[]) return EXIT_FAILURE; } + // Configure socket options + + int value = true; + setsockopt(remoteHandle, IPPROTO_IP, IP_PKTINFO, &value, sizeof(value)); + #ifdef __linux__ // Initialize timer handle @@ -378,12 +378,9 @@ int main(int argc, const char* argv[]) pollHandle = epoll_create(EVENT_LIST_LENGTH); - for (size_t index = 0; index < MEDIA_PORT_COUNT; index ++) - { - event.events = EPOLLIN; - event.data.fd = mediaHandles[index]; - epoll_ctl(pollHandle, EPOLL_CTL_ADD, event.data.fd, &event); - } + event.events = EPOLLIN; + event.data.fd = mediaHandle; + epoll_ctl(pollHandle, EPOLL_CTL_ADD, event.data.fd, &event); event.events = EPOLLIN; event.data.fd = trapHandle; @@ -429,11 +426,8 @@ int main(int argc, const char* argv[]) queueHandle = kqueue(); - for (size_t index = 0; index < MEDIA_PORT_COUNT; index ++) - { - EV_SET(change, mediaHandles[index], EVFILT_READ, EV_ADD | EV_ENABLE, 0, 0, 0); - change ++; - } + EV_SET(change, mediaHandle, EVFILT_READ, EV_ADD | EV_ENABLE, 0, 0, 0); + change ++; EV_SET(change, uplinkHandle, EVFILT_READ, EV_ADD | EV_ENABLE, 0, 0, 0); change ++; @@ -479,7 +473,14 @@ int main(int argc, const char* argv[]) size_t passwordLength = strlen(serverPassword); time_t watchDog = now.tv_sec + EXPIRATION_TIME; - uint32_t sequenceNumber = 0; + + uint32_t sequenceNumbers[] = + { + 0, + 0, + 0, + 0 + }; // Main loop @@ -530,13 +531,10 @@ int main(int argc, const char* argv[]) uint16_t type = le16toh(incomingBuffer->type); size_t length = le16toh(incomingBuffer->length); - if ((type >= REWIND_TYPE_SLOT_1_VOICE) && - (type <= REWIND_TYPE_ANALOG_DATA)) + if (type == REWIND_TYPE_EXTERNAL_SERVER) { - size_t index = type - REWIND_TYPE_SLOT_1_VOICE; - repeaterSocketAddress.sin_port = htons(proxyBasePort + index * 10); - sendto(mediaHandles[index], incomingBuffer->data, length, 0, (struct sockaddr*)&repeaterSocketAddress, sizeof(struct sockaddr_in)); - + repeaterSocketAddress.sin_port = htons(proxyMediaPort); + sendto(mediaHandle, incomingBuffer->data, length, 0, (struct sockaddr*)&repeaterSocketAddress, sizeof(struct sockaddr_in)); continue; } @@ -544,7 +542,6 @@ int main(int argc, const char* argv[]) { repeaterSocketAddress.sin_port = htons(repeaterControlPort); sendto(remoteHandle, incomingBuffer->data, length, 0, (struct sockaddr*)&repeaterSocketAddress, sizeof(struct sockaddr_in)); - continue; } @@ -563,7 +560,7 @@ int main(int argc, const char* argv[]) SHA256(incomingBuffer->data, length + passwordLength, outgoingBuffer->data); outgoingBuffer->type = htole16(REWIND_TYPE_AUTHENTICATION); - outgoingBuffer->number = htole32(++ sequenceNumber); + outgoingBuffer->number = htole32(++ sequenceNumbers[0]); outgoingBuffer->length = htole16(SHA256_DIGEST_LENGTH); sendto(uplinkHandle, outgoingBuffer, sizeof(struct RewindData) + SHA256_DIGEST_LENGTH, 0, serverAddress->ai_addr, serverAddress->ai_addrlen); @@ -591,30 +588,29 @@ int main(int argc, const char* argv[]) } } - // Handle packet of RTP + // Handle packet of External Server - for (size_t index = 0; index < MEDIA_PORT_COUNT; index ++) + if (CHECK(event, mediaHandle)) { - if (CHECK(event, mediaHandles[index])) - { - struct sockaddr_in address; - socklen_t size = sizeof(address); - uint8_t* buffer = (uint8_t*)outgoingBuffer->data; - size_t length = recvfrom(mediaHandles[index], buffer, BUFFER_SIZE, 0, (struct sockaddr*)&address, &size); + struct sockaddr_in address; + socklen_t size = sizeof(address); + uint8_t* buffer = (uint8_t*)outgoingBuffer->data; + size_t length = recvfrom(mediaHandle, buffer, BUFFER_SIZE, 0, (struct sockaddr*)&address, &size); - if ((size == sizeof(struct sockaddr_in)) && - (address.sin_addr.s_addr == repeaterSocketAddress.sin_addr.s_addr) && - ((buffer[0] >> RTP_CONTROL_VERSION_SHIFT) == RTP_PROTOCOL_VERSION) && - (length >= RTP_HEADER_MINIMAL_LENGTH)) - { - outgoingBuffer->type = htole16(index + REWIND_TYPE_SLOT_1_VOICE); - outgoingBuffer->number = htole32(++ sequenceNumber); - outgoingBuffer->length = htole16(length); - length += sizeof(struct RewindData); - sendto(uplinkHandle, outgoingBuffer, length, 0, serverAddress->ai_addr, serverAddress->ai_addrlen); - } - break; + if ((size == sizeof(struct sockaddr_in)) && + (address.sin_addr.s_addr == repeaterSocketAddress.sin_addr.s_addr) && + (length >= KAIROS_EXCHANGE_HEADER_LENGTH) && + (le32toh(*(uint32_t*)buffer) == KAIROS_HAM_RECORD_ID)) + { + uint16_t number = ++ sequenceNumbers[buffer[8] & 3]; + outgoingBuffer->type = htole16(REWIND_TYPE_EXTERNAL_SERVER); + outgoingBuffer->flags = htole16(buffer[8] < 4); + outgoingBuffer->number = htole32(number); + outgoingBuffer->length = htole16(length); + length += sizeof(struct RewindData); + sendto(uplinkHandle, outgoingBuffer, length, 0, serverAddress->ai_addr, serverAddress->ai_addrlen); } + continue; } // Handle packet of Remote Control @@ -622,22 +618,62 @@ int main(int argc, const char* argv[]) if (CHECK(event, remoteHandle)) { struct sockaddr_in address; - socklen_t size = sizeof(address); uint8_t* buffer = (uint8_t*)outgoingBuffer->data; - size_t length = recvfrom(remoteHandle, buffer, BUFFER_SIZE, 0, (struct sockaddr*)&address, &size); - if ((size == sizeof(struct sockaddr_in)) && + struct iovec vector; + vector.iov_base = buffer; + vector.iov_len = BUFFER_SIZE; + + struct msghdr message; + message.msg_name = &address; + message.msg_namelen = sizeof(address); + message.msg_iov = &vector; + message.msg_iovlen = 1; + message.msg_control = alloca(BUFFER_SIZE); + message.msg_controllen = BUFFER_SIZE; + message.msg_flags = 0; + + size_t length = recvmsg(remoteHandle, &message, 0); + + if ((message.msg_namelen == sizeof(struct sockaddr_in)) && (address.sin_addr.s_addr == repeaterSocketAddress.sin_addr.s_addr) && (buffer[0] == REMOTE_STX) && (buffer[length - 1] == REMOTE_ETX) && (length >= 8)) { outgoingBuffer->type = htole16(REWIND_TYPE_REMOTE_CONTROL); - outgoingBuffer->number = htole32(++ sequenceNumber); + outgoingBuffer->number = htole32(++ sequenceNumbers[0]); outgoingBuffer->length = htole16(length); length += sizeof(struct RewindData); sendto(uplinkHandle, outgoingBuffer, length, 0, serverAddress->ai_addr, serverAddress->ai_addrlen); + + // Transmit destination address of received packet + // to make correct messages for External Server interface + + struct cmsghdr* control = CMSG_FIRSTHDR(&message); + while (control != NULL) + { + if (control->cmsg_type == IP_PKTINFO) + { + struct in_pktinfo* information = (struct in_pktinfo*)CMSG_DATA(control); + + size_t length = sizeof(struct RewindAddressData); + struct RewindAddressData* data = (struct RewindAddressData*)outgoingBuffer->data; + data->address = information->ipi_addr; + data->port = htons(proxyMediaPort); + + outgoingBuffer->type = htole16(REWIND_TYPE_ADDRESS_NOTICE); + outgoingBuffer->number = htole32(++ sequenceNumbers[0]); + outgoingBuffer->length = htobe16(length); + length += sizeof(struct RewindData); + sendto(uplinkHandle, outgoingBuffer, length, 0, serverAddress->ai_addr, serverAddress->ai_addrlen); + + break; + } + control = CMSG_NXTHDR(&message, control); + } } + continue; } @@ -656,7 +692,7 @@ int main(int argc, const char* argv[]) (length >= 20)) { outgoingBuffer->type = htole16(REWIND_TYPE_SNMP_TRAP); - outgoingBuffer->number = htole32(++ sequenceNumber); + outgoingBuffer->number = htole32(++ sequenceNumbers[0]); outgoingBuffer->length = htole16(length); length += sizeof(struct RewindData); sendto(uplinkHandle, outgoingBuffer, length, 0, serverAddress->ai_addr, serverAddress->ai_addrlen); @@ -692,7 +728,7 @@ int main(int argc, const char* argv[]) data->number = htole32(repeaterNumber); outgoingBuffer->type = htole16(REWIND_TYPE_KEEP_ALIVE); - outgoingBuffer->number = htole32(++ sequenceNumber); + outgoingBuffer->number = htole32(++ sequenceNumbers[0]); outgoingBuffer->length = htobe16(length); length += sizeof(struct RewindData); sendto(uplinkHandle, outgoingBuffer, length, 0, serverAddress->ai_addr, serverAddress->ai_addrlen); @@ -713,7 +749,7 @@ int main(int argc, const char* argv[]) { #endif outgoingBuffer->type = htole16(REWIND_TYPE_CLOSE); - outgoingBuffer->number = htole32(++ sequenceNumber); + outgoingBuffer->number = htole32(++ sequenceNumbers[0]); outgoingBuffer->length = 0; sendto(uplinkHandle, outgoingBuffer, sizeof(struct RewindData), 0, serverAddress->ai_addr, serverAddress->ai_addrlen); #ifdef __linux__ @@ -740,14 +776,9 @@ int main(int argc, const char* argv[]) close(uplinkHandle); close(remoteHandle); + close(mediaHandle); close(trapHandle); - for (size_t index = 0; index < MEDIA_PORT_COUNT; index ++) - { - int handle = mediaHandles[index]; - close(handle); - } - #ifdef __linux__ close(pollHandle); close(timerHandle); diff --git a/Makefile b/Makefile index f6e325c..d178737 100644 --- a/Makefile +++ b/Makefile @@ -2,11 +2,8 @@ BUILD := $(shell date -u +%Y%m%d-%H%M%S) OS := $(shell uname -s) PREFIX = $(DESTDIR)/opt/CronosAgent -TOOLKIT = ../.. -DIRECTORIES = \ - $(TOOLKIT)/Common \ - $(TOOLKIT)/KAIROS +DIRECTORIES = ifeq ($(OS), Linux) LIBRARIES += \ @@ -46,14 +43,14 @@ install: install -D -d $(PREFIX) install -o root -g root cronosagent $(PREFIX) install -o root -g root cronosagent.sh $(PREFIX) - install -o root -g root cronosagent-init $(PREFIX) - install -m 644 -o root -g root Main/brandmeister-monit $(PREFIX) - install -m 644 -o root -g root Main/brandmeister.plist $(PREFIX) - install -m 644 -o root -g root Main/brandmeister.service $(PREFIX) + # install -o root -g root cronosagent-init $(PREFIX) + # install -m 644 -o root -g root cronosagent-monit $(PREFIX) + # install -m 644 -o root -g root cronosagent.plist $(PREFIX) + install -m 644 -o root -g root cronosagent.service $(PREFIX) clean: rm -f $(PREREQUISITES) $(OBJECTS) cronosagent - rm -f *.d $(TOOLKIT)/*/*.d + rm -f *.d version: echo "#define VERSION $(shell svn info | grep -E "^Revision:" | grep -o -E "[0-9]+")" > Version.h diff --git a/Rewind.h b/Rewind.h index 90a1c82..8fa1ea9 100644 --- a/Rewind.h +++ b/Rewind.h @@ -2,6 +2,7 @@ #define REWIND_H #include +#include #ifdef __cplusplus extern "C" @@ -29,15 +30,13 @@ extern "C" #define REWIND_TYPE_REPORT (REWIND_CLASS_SYSTEM_CONSOLE + 0) #define REWIND_TYPE_BUSY_NOTICE (REWIND_CLASS_SERVER_NOTICE + 0) +#define REWIND_TYPE_ADDRESS_NOTICE (REWIND_CLASS_SERVER_NOTICE + 1) -#define REWIND_TYPE_REMOTE_CONTROL (REWIND_CLASS_KAIROS_DATA + 0) -#define REWIND_TYPE_SNMP_TRAP (REWIND_CLASS_KAIROS_DATA + 1) -#define REWIND_TYPE_SLOT_1_VOICE (REWIND_CLASS_KAIROS_DATA + 2) -#define REWIND_TYPE_SLOT_2_VOICE (REWIND_CLASS_KAIROS_DATA + 3) -#define REWIND_TYPE_ANALOG_VOICE (REWIND_CLASS_KAIROS_DATA + 4) -#define REWIND_TYPE_SLOT_1_DATA (REWIND_CLASS_KAIROS_DATA + 5) -#define REWIND_TYPE_SLOT_2_DATA (REWIND_CLASS_KAIROS_DATA + 6) -#define REWIND_TYPE_ANALOG_DATA (REWIND_CLASS_KAIROS_DATA + 7) +#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_FLAG_REAL_TIME (1 << 0) struct RewindVersionData { @@ -45,6 +44,12 @@ struct RewindVersionData char version[0]; // Software version }; +struct RewindAddressData +{ + struct in_addr address; + uint16_t port; +}; + struct RewindData { char sign[REWIND_SIGN_LENGTH]; diff --git a/cronosagent.plist b/cronosagent.plist index 0e86b67..1eb968a 100644 --- a/cronosagent.plist +++ b/cronosagent.plist @@ -10,6 +10,8 @@ 6 + RunAtLoad + KeepAlive diff --git a/cronosagent.sh b/cronosagent.sh index 129a968..1e0c3f0 100755 --- a/cronosagent.sh +++ b/cronosagent.sh @@ -1,4 +1,4 @@ -#/bin/bash +#!/bin/bash REPEATER_NUMBER=250304 REPEATER_ADDRESS=172.33.20.136