4
Fork 0

Updated to support brand new External Server Interface

This commit is contained in:
R3ABM Artem 2016-07-08 15:25:19 +04:00
parent ee57e48d53
commit 4ea54ae61a
5 changed files with 129 additions and 94 deletions

View file

@ -45,11 +45,11 @@
#define ASN_CONSTRUCTOR 0x20 #define ASN_CONSTRUCTOR 0x20
#endif #endif
// #include "RA-RTP.h" // #include "KAIROS-HAM.h"
#ifndef RA_RTP_H #ifndef KAIROS_HAM_H
#define RTP_PROTOCOL_VERSION 2 #define KAIROS_HAM_DEFAULT_PORT 65472
#define RTP_CONTROL_VERSION_SHIFT 6 #define KAIROS_HAM_RECORD_ID 0xcbfaded8
#define RTP_HEADER_MINIMAL_LENGTH 12 #define KAIROS_EXCHANGE_HEADER_LENGTH 12
#endif #endif
// #include "RemoteControl.h" // #include "RemoteControl.h"
@ -99,8 +99,7 @@
#define MODE_SYSLOG (1 << 1) #define MODE_SYSLOG (1 << 1)
#define MODE_DAEMON (1 << 2) #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 + 4)
#define EVENT_LIST_LENGTH (4 + 1 + 3 + MEDIA_PORT_COUNT)
#define BUFFER_SIZE 4096 #define BUFFER_SIZE 4096
#define EXPIRATION_TIME 20 #define EXPIRATION_TIME 20
@ -136,7 +135,7 @@ int main(int argc, const char* argv[])
// Parameters of repeater // Parameters of repeater
int proxyTrapPort = 162; int proxyTrapPort = 162;
int proxyBasePort = 40000; int proxyMediaPort = KAIROS_HAM_DEFAULT_PORT;
uint32_t repeaterNumber = 0; uint32_t repeaterNumber = 0;
int repeaterControlPort = REMOTE_DEFAULT_PORT; int repeaterControlPort = REMOTE_DEFAULT_PORT;
@ -155,7 +154,7 @@ int main(int argc, const char* argv[])
{ "server-password", required_argument, NULL, 'w' }, { "server-password", required_argument, NULL, 'w' },
{ "server-address", required_argument, NULL, 's' }, { "server-address", required_argument, NULL, 's' },
{ "server-port", required_argument, NULL, 'p' }, { "server-port", required_argument, NULL, 'p' },
{ "base-port", required_argument, NULL, 'b' }, { "media-port", required_argument, NULL, 'b' },
{ "trap-port", required_argument, NULL, 't' }, { "trap-port", required_argument, NULL, 't' },
{ "service-mode", required_argument, NULL, 'm' }, { "service-mode", required_argument, NULL, 'm' },
{ NULL, 0, NULL, 0 } { NULL, 0, NULL, 0 }
@ -190,7 +189,7 @@ int main(int argc, const char* argv[])
break; break;
case 'b': case 'b':
proxyBasePort = strtol(optarg, NULL, 10); proxyMediaPort = strtol(optarg, NULL, 10);
break; break;
case 't': case 't':
@ -215,8 +214,8 @@ int main(int argc, const char* argv[])
" --repeater-port <port number of interface Remote Control>\n" " --repeater-port <port number of interface Remote Control>\n"
" --server-password <access password of BrandMeister DMR Server>\n" " --server-password <access password of BrandMeister DMR Server>\n"
" --server-address <domain name of BrandMeister DMR Server>\n" " --server-address <domain name of BrandMeister DMR Server>\n"
" --server-port <port number of RadioActivity Console>\n" " --server-port <local port for BrandMeister DMR Server>\n"
" --base-port <base port for RTP Media>\n" " --media-port <media port for KAIROS External Servier>\n"
" --trap-port <port for SNMP Traps>\n" " --trap-port <port for SNMP Traps>\n"
" --service-mode <set of bits>\n" " --service-mode <set of bits>\n"
" bit 0 - print to standard output\n" " bit 0 - print to standard output\n"
@ -287,8 +286,8 @@ int main(int argc, const char* argv[])
// Initialize proxy sockets // Initialize proxy sockets
int trapHandle; int trapHandle;
int mediaHandle;
int remoteHandle; int remoteHandle;
int mediaHandles[MEDIA_PORT_COUNT];
struct sockaddr_in proxySocketAddress; struct sockaddr_in proxySocketAddress;
proxySocketAddress.sin_family = AF_INET; proxySocketAddress.sin_family = AF_INET;
@ -312,17 +311,13 @@ int main(int argc, const char* argv[])
return EXIT_FAILURE; 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); print("Error opening port for KAIROS External Server\n");
int handle = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); return EXIT_FAILURE;
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;
} }
// Initialize uplink socket // Initialize uplink socket
@ -343,6 +338,11 @@ int main(int argc, const char* argv[])
return EXIT_FAILURE; return EXIT_FAILURE;
} }
// Configure socket options
int value = true;
setsockopt(remoteHandle, IPPROTO_IP, IP_PKTINFO, &value, sizeof(value));
#ifdef __linux__ #ifdef __linux__
// Initialize timer handle // Initialize timer handle
@ -378,12 +378,9 @@ int main(int argc, const char* argv[])
pollHandle = epoll_create(EVENT_LIST_LENGTH); pollHandle = epoll_create(EVENT_LIST_LENGTH);
for (size_t index = 0; index < MEDIA_PORT_COUNT; index ++) event.events = EPOLLIN;
{ event.data.fd = mediaHandle;
event.events = EPOLLIN; epoll_ctl(pollHandle, EPOLL_CTL_ADD, event.data.fd, &event);
event.data.fd = mediaHandles[index];
epoll_ctl(pollHandle, EPOLL_CTL_ADD, event.data.fd, &event);
}
event.events = EPOLLIN; event.events = EPOLLIN;
event.data.fd = trapHandle; event.data.fd = trapHandle;
@ -429,11 +426,8 @@ int main(int argc, const char* argv[])
queueHandle = kqueue(); queueHandle = kqueue();
for (size_t index = 0; index < MEDIA_PORT_COUNT; index ++) EV_SET(change, mediaHandle, EVFILT_READ, EV_ADD | EV_ENABLE, 0, 0, 0);
{ change ++;
EV_SET(change, mediaHandles[index], EVFILT_READ, EV_ADD | EV_ENABLE, 0, 0, 0);
change ++;
}
EV_SET(change, uplinkHandle, EVFILT_READ, EV_ADD | EV_ENABLE, 0, 0, 0); EV_SET(change, uplinkHandle, EVFILT_READ, EV_ADD | EV_ENABLE, 0, 0, 0);
change ++; change ++;
@ -479,7 +473,14 @@ int main(int argc, const char* argv[])
size_t passwordLength = strlen(serverPassword); size_t passwordLength = strlen(serverPassword);
time_t watchDog = now.tv_sec + EXPIRATION_TIME; time_t watchDog = now.tv_sec + EXPIRATION_TIME;
uint32_t sequenceNumber = 0;
uint32_t sequenceNumbers[] =
{
0,
0,
0,
0
};
// Main loop // Main loop
@ -530,13 +531,10 @@ int main(int argc, const char* argv[])
uint16_t type = le16toh(incomingBuffer->type); uint16_t type = le16toh(incomingBuffer->type);
size_t length = le16toh(incomingBuffer->length); size_t length = le16toh(incomingBuffer->length);
if ((type >= REWIND_TYPE_SLOT_1_VOICE) && if (type == REWIND_TYPE_EXTERNAL_SERVER)
(type <= REWIND_TYPE_ANALOG_DATA))
{ {
size_t index = type - REWIND_TYPE_SLOT_1_VOICE; repeaterSocketAddress.sin_port = htons(proxyMediaPort);
repeaterSocketAddress.sin_port = htons(proxyBasePort + index * 10); sendto(mediaHandle, incomingBuffer->data, length, 0, (struct sockaddr*)&repeaterSocketAddress, sizeof(struct sockaddr_in));
sendto(mediaHandles[index], incomingBuffer->data, length, 0, (struct sockaddr*)&repeaterSocketAddress, sizeof(struct sockaddr_in));
continue; continue;
} }
@ -544,7 +542,6 @@ int main(int argc, const char* argv[])
{ {
repeaterSocketAddress.sin_port = htons(repeaterControlPort); repeaterSocketAddress.sin_port = htons(repeaterControlPort);
sendto(remoteHandle, incomingBuffer->data, length, 0, (struct sockaddr*)&repeaterSocketAddress, sizeof(struct sockaddr_in)); sendto(remoteHandle, incomingBuffer->data, length, 0, (struct sockaddr*)&repeaterSocketAddress, sizeof(struct sockaddr_in));
continue; continue;
} }
@ -563,7 +560,7 @@ int main(int argc, const char* argv[])
SHA256(incomingBuffer->data, length + passwordLength, outgoingBuffer->data); SHA256(incomingBuffer->data, length + passwordLength, outgoingBuffer->data);
outgoingBuffer->type = htole16(REWIND_TYPE_AUTHENTICATION); outgoingBuffer->type = htole16(REWIND_TYPE_AUTHENTICATION);
outgoingBuffer->number = htole32(++ sequenceNumber); outgoingBuffer->number = htole32(++ sequenceNumbers[0]);
outgoingBuffer->length = htole16(SHA256_DIGEST_LENGTH); outgoingBuffer->length = htole16(SHA256_DIGEST_LENGTH);
sendto(uplinkHandle, outgoingBuffer, sizeof(struct RewindData) + SHA256_DIGEST_LENGTH, 0, serverAddress->ai_addr, serverAddress->ai_addrlen); 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);
struct sockaddr_in address; uint8_t* buffer = (uint8_t*)outgoingBuffer->data;
socklen_t size = sizeof(address); size_t length = recvfrom(mediaHandle, buffer, BUFFER_SIZE, 0, (struct sockaddr*)&address, &size);
uint8_t* buffer = (uint8_t*)outgoingBuffer->data;
size_t length = recvfrom(mediaHandles[index], buffer, BUFFER_SIZE, 0, (struct sockaddr*)&address, &size);
if ((size == sizeof(struct sockaddr_in)) && if ((size == sizeof(struct sockaddr_in)) &&
(address.sin_addr.s_addr == repeaterSocketAddress.sin_addr.s_addr) && (address.sin_addr.s_addr == repeaterSocketAddress.sin_addr.s_addr) &&
((buffer[0] >> RTP_CONTROL_VERSION_SHIFT) == RTP_PROTOCOL_VERSION) && (length >= KAIROS_EXCHANGE_HEADER_LENGTH) &&
(length >= RTP_HEADER_MINIMAL_LENGTH)) (le32toh(*(uint32_t*)buffer) == KAIROS_HAM_RECORD_ID))
{ {
outgoingBuffer->type = htole16(index + REWIND_TYPE_SLOT_1_VOICE); uint16_t number = ++ sequenceNumbers[buffer[8] & 3];
outgoingBuffer->number = htole32(++ sequenceNumber); outgoingBuffer->type = htole16(REWIND_TYPE_EXTERNAL_SERVER);
outgoingBuffer->length = htole16(length); outgoingBuffer->flags = htole16(buffer[8] < 4);
length += sizeof(struct RewindData); outgoingBuffer->number = htole32(number);
sendto(uplinkHandle, outgoingBuffer, length, 0, serverAddress->ai_addr, serverAddress->ai_addrlen); outgoingBuffer->length = htole16(length);
} length += sizeof(struct RewindData);
break; sendto(uplinkHandle, outgoingBuffer, length, 0, serverAddress->ai_addr, serverAddress->ai_addrlen);
} }
continue;
} }
// Handle packet of Remote Control // Handle packet of Remote Control
@ -622,22 +618,62 @@ int main(int argc, const char* argv[])
if (CHECK(event, remoteHandle)) if (CHECK(event, remoteHandle))
{ {
struct sockaddr_in address; struct sockaddr_in address;
socklen_t size = sizeof(address);
uint8_t* buffer = (uint8_t*)outgoingBuffer->data; 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) && (address.sin_addr.s_addr == repeaterSocketAddress.sin_addr.s_addr) &&
(buffer[0] == REMOTE_STX) && (buffer[0] == REMOTE_STX) &&
(buffer[length - 1] == REMOTE_ETX) && (buffer[length - 1] == REMOTE_ETX) &&
(length >= 8)) (length >= 8))
{ {
outgoingBuffer->type = htole16(REWIND_TYPE_REMOTE_CONTROL); outgoingBuffer->type = htole16(REWIND_TYPE_REMOTE_CONTROL);
outgoingBuffer->number = htole32(++ sequenceNumber); outgoingBuffer->number = htole32(++ sequenceNumbers[0]);
outgoingBuffer->length = htole16(length); outgoingBuffer->length = htole16(length);
length += sizeof(struct RewindData); length += sizeof(struct RewindData);
sendto(uplinkHandle, outgoingBuffer, length, 0, serverAddress->ai_addr, serverAddress->ai_addrlen); 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; continue;
} }
@ -656,7 +692,7 @@ int main(int argc, const char* argv[])
(length >= 20)) (length >= 20))
{ {
outgoingBuffer->type = htole16(REWIND_TYPE_SNMP_TRAP); outgoingBuffer->type = htole16(REWIND_TYPE_SNMP_TRAP);
outgoingBuffer->number = htole32(++ sequenceNumber); outgoingBuffer->number = htole32(++ sequenceNumbers[0]);
outgoingBuffer->length = htole16(length); outgoingBuffer->length = htole16(length);
length += sizeof(struct RewindData); length += sizeof(struct RewindData);
sendto(uplinkHandle, outgoingBuffer, length, 0, serverAddress->ai_addr, serverAddress->ai_addrlen); 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); data->number = htole32(repeaterNumber);
outgoingBuffer->type = htole16(REWIND_TYPE_KEEP_ALIVE); outgoingBuffer->type = htole16(REWIND_TYPE_KEEP_ALIVE);
outgoingBuffer->number = htole32(++ sequenceNumber); outgoingBuffer->number = htole32(++ sequenceNumbers[0]);
outgoingBuffer->length = htobe16(length); outgoingBuffer->length = htobe16(length);
length += sizeof(struct RewindData); length += sizeof(struct RewindData);
sendto(uplinkHandle, outgoingBuffer, length, 0, serverAddress->ai_addr, serverAddress->ai_addrlen); sendto(uplinkHandle, outgoingBuffer, length, 0, serverAddress->ai_addr, serverAddress->ai_addrlen);
@ -713,7 +749,7 @@ int main(int argc, const char* argv[])
{ {
#endif #endif
outgoingBuffer->type = htole16(REWIND_TYPE_CLOSE); outgoingBuffer->type = htole16(REWIND_TYPE_CLOSE);
outgoingBuffer->number = htole32(++ sequenceNumber); outgoingBuffer->number = htole32(++ sequenceNumbers[0]);
outgoingBuffer->length = 0; outgoingBuffer->length = 0;
sendto(uplinkHandle, outgoingBuffer, sizeof(struct RewindData), 0, serverAddress->ai_addr, serverAddress->ai_addrlen); sendto(uplinkHandle, outgoingBuffer, sizeof(struct RewindData), 0, serverAddress->ai_addr, serverAddress->ai_addrlen);
#ifdef __linux__ #ifdef __linux__
@ -740,14 +776,9 @@ int main(int argc, const char* argv[])
close(uplinkHandle); close(uplinkHandle);
close(remoteHandle); close(remoteHandle);
close(mediaHandle);
close(trapHandle); close(trapHandle);
for (size_t index = 0; index < MEDIA_PORT_COUNT; index ++)
{
int handle = mediaHandles[index];
close(handle);
}
#ifdef __linux__ #ifdef __linux__
close(pollHandle); close(pollHandle);
close(timerHandle); close(timerHandle);

View file

@ -2,11 +2,8 @@ BUILD := $(shell date -u +%Y%m%d-%H%M%S)
OS := $(shell uname -s) OS := $(shell uname -s)
PREFIX = $(DESTDIR)/opt/CronosAgent PREFIX = $(DESTDIR)/opt/CronosAgent
TOOLKIT = ../..
DIRECTORIES = \ DIRECTORIES =
$(TOOLKIT)/Common \
$(TOOLKIT)/KAIROS
ifeq ($(OS), Linux) ifeq ($(OS), Linux)
LIBRARIES += \ LIBRARIES += \
@ -46,14 +43,14 @@ install:
install -D -d $(PREFIX) install -D -d $(PREFIX)
install -o root -g root cronosagent $(PREFIX) install -o root -g root cronosagent $(PREFIX)
install -o root -g root cronosagent.sh $(PREFIX) install -o root -g root cronosagent.sh $(PREFIX)
install -o root -g root cronosagent-init $(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 cronosagent-monit $(PREFIX)
install -m 644 -o root -g root Main/brandmeister.plist $(PREFIX) # install -m 644 -o root -g root cronosagent.plist $(PREFIX)
install -m 644 -o root -g root Main/brandmeister.service $(PREFIX) install -m 644 -o root -g root cronosagent.service $(PREFIX)
clean: clean:
rm -f $(PREREQUISITES) $(OBJECTS) cronosagent rm -f $(PREREQUISITES) $(OBJECTS) cronosagent
rm -f *.d $(TOOLKIT)/*/*.d rm -f *.d
version: version:
echo "#define VERSION $(shell svn info | grep -E "^Revision:" | grep -o -E "[0-9]+")" > Version.h echo "#define VERSION $(shell svn info | grep -E "^Revision:" | grep -o -E "[0-9]+")" > Version.h

View file

@ -2,6 +2,7 @@
#define REWIND_H #define REWIND_H
#include <stdint.h> #include <stdint.h>
#include <netinet/in.h>
#ifdef __cplusplus #ifdef __cplusplus
extern "C" extern "C"
@ -29,15 +30,13 @@ extern "C"
#define REWIND_TYPE_REPORT (REWIND_CLASS_SYSTEM_CONSOLE + 0) #define REWIND_TYPE_REPORT (REWIND_CLASS_SYSTEM_CONSOLE + 0)
#define REWIND_TYPE_BUSY_NOTICE (REWIND_CLASS_SERVER_NOTICE + 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_EXTERNAL_SERVER (REWIND_CLASS_KAIROS_DATA + 0)
#define REWIND_TYPE_SNMP_TRAP (REWIND_CLASS_KAIROS_DATA + 1) #define REWIND_TYPE_REMOTE_CONTROL (REWIND_CLASS_KAIROS_DATA + 1)
#define REWIND_TYPE_SLOT_1_VOICE (REWIND_CLASS_KAIROS_DATA + 2) #define REWIND_TYPE_SNMP_TRAP (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_FLAG_REAL_TIME (1 << 0)
#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)
struct RewindVersionData struct RewindVersionData
{ {
@ -45,6 +44,12 @@ struct RewindVersionData
char version[0]; // Software version char version[0]; // Software version
}; };
struct RewindAddressData
{
struct in_addr address;
uint16_t port;
};
struct RewindData struct RewindData
{ {
char sign[REWIND_SIGN_LENGTH]; char sign[REWIND_SIGN_LENGTH];

View file

@ -10,6 +10,8 @@
<array> <array>
<string>6</string> <string>6</string>
</array> </array>
<key>RunAtLoad</key>
<true/>
<key>KeepAlive</key> <key>KeepAlive</key>
<true/> <true/>
</dict> </dict>

View file

@ -1,4 +1,4 @@
#/bin/bash #!/bin/bash
REPEATER_NUMBER=250304 REPEATER_NUMBER=250304
REPEATER_ADDRESS=172.33.20.136 REPEATER_ADDRESS=172.33.20.136