From 12ffb10726d7200c1a6de752586fcd6b03f672df Mon Sep 17 00:00:00 2001 From: Artem Prilutskiy Date: Tue, 1 Nov 2016 12:17:27 +0300 Subject: [PATCH] Initial import --- Makefile | 74 ++++++ Rewind.h | 103 +++++++++ TellusAgent.c | 574 +++++++++++++++++++++++++++++++++++++++++++++++ Version.h | 1 + tellusagent.conf | 6 + tellusagent.sh | 33 +++ test.sh | 4 + 7 files changed, 795 insertions(+) create mode 100644 Makefile create mode 100644 Rewind.h create mode 100644 TellusAgent.c create mode 100644 Version.h create mode 100644 tellusagent.conf create mode 100755 tellusagent.sh create mode 100755 test.sh diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..95b1c0b --- /dev/null +++ b/Makefile @@ -0,0 +1,74 @@ +BUILD := $(shell date -u +%Y%m%d-%H%M%S) +OS := $(shell uname -s) + +PREFIX = $(DESTDIR)/opt/TellusAgent +TOOLKIT = ../.. + +DIRECTORIES = \ + $(TOOLKIT)/Common \ + $(TOOLKIT)/Rewind + +ifeq ($(OS), Linux) + FLAGS += -rdynamic + KIND := $(shell grep -E "^6.0" /etc/debian_version > /dev/null ; echo $?) +ifneq ($(KIND), 0) + LIBRARIES += rt +endif +endif + +ifeq ($(OS), Darwin) + FLAGS += -Wno-deprecated-declarations +endif + +OBJECTS = \ + TellusAgent.o + +FLAGS += -g -fno-omit-frame-pointer -O3 -MMD $(foreach directory, $(DIRECTORIES), -I$(directory)) -DBUILD=\"$(BUILD)\" +LIBS += $(foreach library, $(LIBRARIES), -l$(library)) + +CC = gcc +CFLAGS += $(FLAGS) -std=gnu99 + +ifneq ($(strip $(DEPENDENCIES)),) + FLAGS += $(shell pkg-config --cflags $(DEPENDENCIES)) + LIBS += $(shell pkg-config --libs $(DEPENDENCIES)) +endif + +all: build + +build: $(PREREQUISITES) $(OBJECTS) + $(CC) $(OBJECTS) $(FLAGS) $(LIBS) -o tellusagent + +install: + install -D -d $(PREFIX) + install -o root -g root tellusagent $(PREFIX) + install -o root -g root tellusagent.sh $(PREFIX) + install -o root -g root tellusagent.conf $(PREFIX) +ifeq ($(OS), Linux) + install -o root -g root tellusagent-init $(PREFIX) + install -m 644 -o root -g root tellusagent-monit $(PREFIX) + install -m 644 -o root -g root tellusagent.service $(PREFIX) +endif +ifeq ($(OS), Darwin) + install -m 644 -o root -g root tellusagent.plist $(DESTDIR)/Library/LaunchDaemons +endif + +clean: + rm -f $(PREREQUISITES) $(OBJECTS) tellusagent + rm -f *.d $(TOOLKIT)/*/*.d + +version: + echo "#define VERSION $(shell date -u +%Y%m%d)" > Version.h + +debian-package: + ./UpdateLog.sh +ifdef ARCH + dpkg-buildpackage -b -a$(ARCH) -tc +else + dpkg-buildpackage -b -tc +endif + +macos-archive: build + zip ../TellusAgent-macOS.zip tellusagent tellusagent.sh tellusagent.conf tellusagent.plist + +.PHONY: all build clean install diff --git a/Rewind.h b/Rewind.h new file mode 100644 index 0000000..41cc47d --- /dev/null +++ b/Rewind.h @@ -0,0 +1,103 @@ +#ifndef REWIND_H +#define REWIND_H + +#include +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + +#pragma pack(push, 1) + +#define REWIND_KEEP_ALIVE_INTERVAL 5 + +#define REWIND_SIGN_LENGTH 8 +#define REWIND_PROTOCOL_SIGN "REWIND01" + +#define REWIND_CLASS_REWIND_CONTROL 0x0000 +#define REWIND_CLASS_SYSTEM_CONSOLE 0x0100 +#define REWIND_CLASS_SERVER_NOTICE 0x0200 +#define REWIND_CLASS_DEVICE_DATA 0x0800 +#define REWIND_CLASS_APPLICATION 0x0900 + +#define REWIND_CLASS_KAIROS_DATA (REWIND_CLASS_DEVICE_DATA + 0x00) +#define REWIND_CLASS_TELLUS_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_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_BINDING_NOTICE (REWIND_CLASS_SERVER_NOTICE + 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_PEER_DATA (REWIND_CLASS_TELLUS_DATA + 0) +#define REWIND_TYPE_RDAC_DATA (REWIND_CLASS_TELLUS_DATA + 1) +#define REWIND_TYPE_MEDIA_DATA (REWIND_CLASS_TELLUS_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_FLAG_NONE 0 +#define REWIND_FLAG_REAL_TIME_1 (1 << 0) +#define REWIND_FLAG_REAL_TIME_2 (1 << 1) +#define REWIND_FLAG_DEFAULT_SET REWIND_FLAG_NONE + +#define REWIND_ROLE_REPEATER_AGENT 0x10 +#define REWIND_ROLE_APPLICATION 0x20 + +#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) + +struct RewindVersionData +{ + uint32_t number; // Remote ID + uint8_t service; // REWIND_SERVICE_* + char description[0]; // Software name and version +}; + +struct RewindAddressData +{ + struct in_addr address; + uint16_t port; +}; + +struct RewindBindingData +{ + uint16_t ports[0]; +}; + +struct RewindSubscriptionData +{ + uint32_t type; + uint32_t number; +}; + +struct RewindData +{ + char sign[REWIND_SIGN_LENGTH]; + uint16_t type; // REWIND_TYPE_* + uint16_t flags; // REWIND_FLAG_* + uint32_t number; // Packet sequence number + uint16_t length; // Length of following data + uint8_t data[0]; // +}; + +#pragma pack(pop) + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/TellusAgent.c b/TellusAgent.c new file mode 100644 index 0000000..8cce661 --- /dev/null +++ b/TellusAgent.c @@ -0,0 +1,574 @@ +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#ifdef __linux__ +#include +#include +#include +#include +#endif + +#ifdef __MACH__ +#include +#include +#include +#include +#include +#endif + +#include "Rewind.h" +#include "Version.h" + +#define HELPER(value) #value +#define STRING(value) HELPER(value) + +#define COUNT(array) sizeof(array) / sizeof(array[0]) + +#ifdef __cplusplus +#define CAST(type, value) const_cast(value) +#else +#define CAST(type, value) (type)value + +#ifndef bool +#define bool int +#define true 1 +#define false 0 +#endif +#endif + +#ifdef __linux__ +#define CHECK(event, handle) (event->data.fd == handle) +#endif + +#ifdef __MACH__ +#define CHECK(event, handle) (event->ident == handle) && (event->filter == EVFILT_READ) + +#define htobe16(value) OSSwapHostToBigInt16(value) +#define be16toh(value) OSSwapBigToHostInt16(value) +#define htobe32(value) OSSwapHostToBigInt32(value) +#define be32toh(value) OSSwapBigToHostInt32(value) + +#define htole16(value) OSSwapHostToLittleInt16(value) +#define le16toh(value) OSSwapLittleToHostInt16(value) +#define htole32(value) OSSwapHostToLittleInt32(value) +#define le32toh(value) OSSwapLittleToHostInt32(value) + +#define __bswap_16(value) OSSwapConstInt16(value) +#define __bswap_32(value) OSSwapConstInt32(value) +#endif + + +#define MODE_CONSOLE (1 << 0) +#define MODE_SYSLOG (1 << 1) +#define MODE_DAEMON (1 << 2) + +#define EVENT_LIST_LENGTH (4 + 4) + +#define BUFFER_SIZE 2048 +#define PROXY_PORT_COUNT 3 + + +int serviceMode = MODE_CONSOLE; + +void print(const char* format, ...) +{ + va_list arguments; + va_start(arguments, format); + if (serviceMode & MODE_CONSOLE) + vprintf(format, arguments); + if (serviceMode & MODE_SYSLOG) + vsyslog(LOG_INFO, format, arguments); + va_end(arguments); +} + +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("Software revision " STRING(VERSION) " build " BUILD "\n"); + print("\n"); + + // Parameters for server + + const char* serverPort = "54003"; + const char* serverLocation = NULL; + struct addrinfo* serverAddress = NULL; + + // Parameters for repeater + + uint16_t proxyPorts[PROXY_PORT_COUNT] = + { + htobe16(50000), + htobe16(50001), + htobe16(50002) + }; + + // Start up + + struct option options[] = + { + { "connect-port", required_argument, NULL, 'c' }, + { "control-port", required_argument, NULL, 'r' }, + { "media-port", required_argument, NULL, 'd' }, + { "server-address", required_argument, NULL, 's' }, + { "server-port", required_argument, NULL, 'p' }, + { "service-mode", required_argument, NULL, 'm' }, + { NULL, 0, NULL, 0 } + }; + + int selection = 0; + while ((selection = getopt_long(argc, CAST(char* const*, argv), "c:r:d:s:p:m:", options, NULL)) != EOF) + switch (selection) + { + case 'c': + proxyPorts[0] = htons(strtol(optarg, NULL, 10)); + break; + + case 'r': + proxyPorts[1] = htons(strtol(optarg, NULL, 10)); + break; + + case 'd': + proxyPorts[2] = htons(strtol(optarg, NULL, 10)); + break; + + case 's': + serverLocation = optarg; + break; + + case 'p': + serverPort = optarg; + break; + + case 'm': + serviceMode = strtol(optarg, NULL, 10); + break; + } + + if (serverLocation == NULL) + { + print( + "Usage:\n" + " %s\n" + " --connect-port \n" + " --control-port \n" + " --media-port \n" + " --server-address \n" + " --server-port \n" + " --service-mode \n" + " bit 0 - print to standard output\n" + " bit 1 - print to system log\n" + " bit 2 - run as daemon\n" + "\n", + argv[0]); + return EXIT_FAILURE; + } + + if (serviceMode & MODE_SYSLOG) + { + // Set proper origin for syslog (required by OpenWRT) + openlog("TellusAgent", LOG_NOWAIT | LOG_PID, LOG_USER); + } + +#ifdef __linux__ + if ((serviceMode & MODE_DAEMON) && + (daemon(-1, -1) < 0)) + { + print("Error launching daemon"); + return EXIT_FAILURE; + } +#endif +#ifdef __MACH__ + if (serviceMode & MODE_DAEMON) + { + 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) + { + print("Error calling launchd"); + return EXIT_FAILURE; + } + launch_data_type_t type = launch_data_get_type(response); + launch_data_free(response); + if (type == LAUNCH_DATA_ERRNO) + { + print("launchd returned error %d\n", launch_data_get_errno(response)); + return EXIT_FAILURE; + } + // launchd will return dictionary of job for successful check-in + if (type != LAUNCH_DATA_DICTIONARY) + { + print("Error launching daemon"); + return EXIT_FAILURE; + } + } +#endif + + // Resolve server address + + struct addrinfo hints; + + memset(&hints, 0, sizeof(hints)); + hints.ai_socktype = SOCK_DGRAM; + +#ifdef __linux__ + hints.ai_flags = AI_ADDRCONFIG; + hints.ai_family = AF_UNSPEC; +#endif +#ifdef __MACH__ + hints.ai_flags = AI_V4MAPPED; + hints.ai_family = AF_INET6; +#endif + + if (getaddrinfo(serverLocation, serverPort, &hints, &serverAddress) != 0) + { + print("Error resolving server address %s\n", serverLocation); + return EXIT_FAILURE; + } + + // Initialize proxy sockets + + int proxyHandles[PROXY_PORT_COUNT]; + + struct sockaddr_in proxySocketAddress; + socklen_t proxySocketLength = sizeof(proxySocketAddress); + + proxySocketAddress.sin_family = AF_INET; + proxySocketAddress.sin_addr.s_addr = htonl(INADDR_ANY); + + for (selection = 0; selection < PROXY_PORT_COUNT; selection ++) + { + int handle; + + proxySocketAddress.sin_port = proxyPorts[selection]; + handle = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); + + if((handle < 0) || + (bind(handle, (struct sockaddr*)&proxySocketAddress, proxySocketLength) < 0)) + { + print("Error opening port for Multi-Site Connect\n"); + return EXIT_FAILURE; + } + + proxyHandles[selection] = handle; + } + + // Initialize uplink socket + + int uplinkHandle; + struct sockaddr_in6 uplinkSocketAddress; + + 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); + if((uplinkHandle < 0) || + (bind(uplinkHandle, (struct sockaddr*)&uplinkSocketAddress, sizeof(uplinkSocketAddress)) < 0)) + { + print("Error opening port for Rewind Uplink\n"); + return EXIT_FAILURE; + } + +#ifdef __linux__ + + // Initialize signal handle + + int signalHandle; + sigset_t signalMask; + + sigemptyset(&signalMask); + sigaddset(&signalMask, SIGINT); + sigaddset(&signalMask, SIGHUP); + sigaddset(&signalMask, SIGTERM); + sigaddset(&signalMask, SIGQUIT); + + sigprocmask(SIG_BLOCK, &signalMask, NULL); + signalHandle = signalfd(-1, &signalMask, 0); + + // Initialize ePoll + + int pollHandle; + struct epoll_event event; + + pollHandle = epoll_create(EVENT_LIST_LENGTH); + + event.events = EPOLLIN; + event.data.fd = proxyHandles[0]; + epoll_ctl(pollHandle, EPOLL_CTL_ADD, event.data.fd, &event); + + event.events = EPOLLIN; + event.data.fd = proxyHandles[1]; + epoll_ctl(pollHandle, EPOLL_CTL_ADD, event.data.fd, &event); + + event.events = EPOLLIN; + event.data.fd = proxyHandles[2]; + epoll_ctl(pollHandle, EPOLL_CTL_ADD, event.data.fd, &event); + + event.events = EPOLLIN; + event.data.fd = uplinkHandle; + epoll_ctl(pollHandle, EPOLL_CTL_ADD, event.data.fd, &event); + + event.events = EPOLLIN; + event.data.fd = signalHandle; + epoll_ctl(pollHandle, EPOLL_CTL_ADD, event.data.fd, &event); + +#endif +#ifdef __MACH__ + + // Prepare signal handlers + + signal(SIGINT, SIG_IGN); + signal(SIGHUP, SIG_IGN); + signal(SIGTERM, SIG_IGN); + signal(SIGQUIT, SIG_IGN); + + // Initialize KQueue + + int queueHandle; + + struct kevent changes[EVENT_LIST_LENGTH]; + struct kevent* change = changes; + + queueHandle = kqueue(); + + EV_SET(change, proxyHandles[0], EVFILT_READ, EV_ADD | EV_ENABLE, 0, 0, 0); + change ++; + + EV_SET(change, proxyHandles[1], EVFILT_READ, EV_ADD | EV_ENABLE, 0, 0, 0); + change ++; + + EV_SET(change, proxyHandles[2], EVFILT_READ, EV_ADD | EV_ENABLE, 0, 0, 0); + change ++; + + EV_SET(change, uplinkHandle, EVFILT_READ, EV_ADD | EV_ENABLE, 0, 0, 0); + change ++; + + EV_SET(change, SIGINT, EVFILT_SIGNAL, EV_ADD | EV_ENABLE, 0, 0, 0); + change ++; + + EV_SET(change, SIGHUP, EVFILT_SIGNAL, EV_ADD | EV_ENABLE, 0, 0, 0); + change ++; + + EV_SET(change, SIGTERM, EVFILT_SIGNAL, EV_ADD | EV_ENABLE, 0, 0, 0); + change ++; + + EV_SET(change, SIGQUIT, EVFILT_SIGNAL, EV_ADD | EV_ENABLE, 0, 0, 0); + change ++; + +#endif + + // Prepare buffers + + void* controlBuffer = alloca(BUFFER_SIZE); + + struct RewindData* incomingBuffer = (struct RewindData*)alloca(sizeof(struct RewindData) + BUFFER_SIZE); + struct RewindData* outgoingBuffer = (struct RewindData*)alloca(sizeof(struct RewindData) + BUFFER_SIZE); + + memset(outgoingBuffer, 0, sizeof(struct RewindData)); + memcpy(outgoingBuffer, REWIND_PROTOCOL_SIGN, REWIND_SIGN_LENGTH); + + struct utsname systemName; + uname(&systemName); + + struct sockaddr_in repeaterSocketAddresses[3]; + memset(repeaterSocketAddresses, 0, sizeof(repeaterSocketAddresses)); + + // Main loop + + bool running = true; + + print("Server started\n"); + + while (running) + { +#ifdef __linux__ + struct epoll_event events[EVENT_LIST_LENGTH]; + int count = epoll_wait(pollHandle, events, EVENT_LIST_LENGTH, -1); +#endif +#ifdef __MACH__ + struct kevent events[EVENT_LIST_LENGTH]; + int count = kevent(queueHandle, changes, EVENT_LIST_LENGTH, events, EVENT_LIST_LENGTH, NULL); +#endif + + if (count < 0) + { + int error = errno; + print("Error processing handles: %s (%d)\n", strerror(error), error); + break; + } + + for (size_t index = 0; index < count; index ++) + { +#ifdef __linux__ + struct epoll_event* event = events + index; +#endif +#ifdef __MACH__ + struct kevent* event = events + index; +#endif + + // Handle packet from the uplink + + if (CHECK(event, uplinkHandle)) + { + struct sockaddr_in6 address; + socklen_t size = sizeof(address); + 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 */ + (memcmp(&address, serverAddress->ai_addr, serverAddress->ai_addrlen) == 0)) && + (memcmp(incomingBuffer->sign, REWIND_PROTOCOL_SIGN, REWIND_SIGN_LENGTH) == 0)) + { + uint16_t type = le16toh(incomingBuffer->type); + size_t length = le16toh(incomingBuffer->length); + + if ((type <= REWIND_TYPE_PEER_DATA) && + (type >= REWIND_TYPE_MEDIA_DATA)) + { + int handle; + struct sockaddr_in* address; + + selection = type - REWIND_TYPE_PEER_DATA; + address = repeaterSocketAddresses + selection; + handle = proxyHandles[selection]; + + sendto(handle, incomingBuffer->data, length, 0, (struct sockaddr*)address, sizeof(struct sockaddr_in)); + continue; + } + + if (type == REWIND_TYPE_REPORT) + { + incomingBuffer->data[length] = '\0'; + print("Server message: %s\n", incomingBuffer->data); + continue; + } + + if (type == REWIND_TYPE_CLOSE) + { + print("Disconnect request received\n"); + running = false; + break; + } + } + } + + // Handle packet from the repeater + + if (CHECK(event, proxyHandles[0])) + { + struct msghdr message; + struct iovec vectors[2]; + + outgoingBuffer->type = htole16(REWIND_TYPE_BINDING_NOTICE); + outgoingBuffer->length = htole16(sizeof(proxyPorts)); + + vectors[0].iov_base = outgoingBuffer; + vectors[0].iov_len = sizeof(struct RewindData); + vectors[1].iov_base = proxyPorts; + vectors[1].iov_len = sizeof(proxyPorts); + message.msg_name = serverAddress->ai_addr; + message.msg_namelen = serverAddress->ai_addrlen; + message.msg_iov = vectors; + message.msg_iovlen = 2; + message.msg_control = NULL; + message.msg_controllen = 0; + message.msg_flags = 0; + + sendmsg(uplinkHandle, &message, 0); + } + + for (selection = 0; selection < PROXY_PORT_COUNT; selection ++) + { + int handle = proxyHandles[selection]; + if (CHECK(event, handle)) + { + 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); + + outgoingBuffer->type = htole16(REWIND_CLASS_TELLUS_DATA + selection); + outgoingBuffer->length = htole16(length); + + length += sizeof(struct RewindData); + sendto(uplinkHandle, outgoingBuffer, length, 0, serverAddress->ai_addr, serverAddress->ai_addrlen); + } + } + + // Handle signal from the kernel + +#ifdef __linux__ + if (event->data.fd == signalHandle) + { + struct signalfd_siginfo information; + read(signalHandle, &information, sizeof(information)); +#endif +#ifdef __MACH__ + if (event->filter == EVFILT_SIGNAL) + { +#endif + outgoingBuffer->type = htole16(REWIND_TYPE_CLOSE); + outgoingBuffer->length = 0; + sendto(uplinkHandle, outgoingBuffer, sizeof(struct RewindData), 0, serverAddress->ai_addr, serverAddress->ai_addrlen); +#ifdef __linux__ + if ((information.ssi_signo == SIGINT) || + (information.ssi_signo == SIGTERM) || + (information.ssi_signo == SIGQUIT)) +#endif +#ifdef __MACH__ + if ((event->ident == SIGINT) || + (event->ident == SIGTERM) || + (event->ident == SIGQUIT)) +#endif + { + running = false; + break; + } + + } + } + } + + print("Server stopped\n"); + + // Clean up + + close(uplinkHandle); + close(proxyHandles[0]); + close(proxyHandles[1]); + close(proxyHandles[2]); + +#ifdef __linux__ + close(pollHandle); + close(signalHandle); +#endif +#ifdef __MACH__ + close(queueHandle); +#endif + + freeaddrinfo(serverAddress); + + return EXIT_SUCCESS; +}; diff --git a/Version.h b/Version.h new file mode 100644 index 0000000..49a1ce8 --- /dev/null +++ b/Version.h @@ -0,0 +1 @@ +#define VERSION 20161101 diff --git a/tellusagent.conf b/tellusagent.conf new file mode 100644 index 0000000..97ecd6c --- /dev/null +++ b/tellusagent.conf @@ -0,0 +1,6 @@ + +CONNECT_PORT=50000 +CONTROL_PORT=50001 +MEDIA_PORT=50002 +SERVER_ADDRESS=aesyle.dstar.su +SERVICE_MODE=1 diff --git a/tellusagent.sh b/tellusagent.sh new file mode 100755 index 0000000..06e2cdd --- /dev/null +++ b/tellusagent.sh @@ -0,0 +1,33 @@ +#!/bin/sh + +DIRECTORY=$(dirname $0) + +if [ -f $DIRECTORY/tellusagent.conf ] +then + # Read configuration from text file + # Dot is equivalent of bash's source + . $DIRECTORY/tellusagent.conf +fi + +if [ -f /etc/config/tellusagent ] +then + # Read configuration from UCI/LuCI on OpenWRT + CONNECT_PORT=$(uci get tellusagent.@tellusagent[0].connectPort) + CONTROL_PORT=$(uci get tellusagent.@tellusagent[0].controlPort) + MEDIA_PORT=$(uci get tellusagent.@tellusagent[0].mediaPort) +fi + +if [ -n "$1" ] +then + # 1 - print to standard output + # 2 - print to system log + # 6 - run as daemon and print to system log + SERVICE_MODE=$1 +fi + +$DIRECTORY/tellusagent \ + --connect-port ${CONNECT_PORT} \ + --control-port ${CONTROL_PORT} \ + --media-port ${MEDIA_PORT} \ + --server-address ${SERVER_ADDRESS} \ + --service-mode ${SERVICE_MODE} diff --git a/test.sh b/test.sh new file mode 100755 index 0000000..97db0fb --- /dev/null +++ b/test.sh @@ -0,0 +1,4 @@ +#/bin/bash +make +./tellusagent.sh +make clean