..
This commit is contained in:
parent
37792d9beb
commit
37951d1d3c
1 changed files with 123 additions and 39 deletions
162
CronosAgent.c
162
CronosAgent.c
|
@ -10,14 +10,19 @@
|
||||||
|
|
||||||
#include <netdb.h>
|
#include <netdb.h>
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
|
#include <netinet/ip.h>
|
||||||
|
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <syslog.h>
|
#include <syslog.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
|
#include <sys/utsname.h>
|
||||||
|
|
||||||
|
#ifdef USE_OPENSSL
|
||||||
|
#include <openssl/sha.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
// #include <openssl/sha.h>
|
|
||||||
#ifndef HEADER_SHA_H
|
#ifndef HEADER_SHA_H
|
||||||
#include "sha256.h"
|
#include "sha256.h"
|
||||||
#define SHA256_DIGEST_LENGTH SHA256_BLOCK_SIZE
|
#define SHA256_DIGEST_LENGTH SHA256_BLOCK_SIZE
|
||||||
|
@ -50,6 +55,13 @@
|
||||||
#include "Rewind.h"
|
#include "Rewind.h"
|
||||||
#include "Version.h"
|
#include "Version.h"
|
||||||
|
|
||||||
|
#include "RingBuffer.h"
|
||||||
|
|
||||||
|
// #include "DMR.h"
|
||||||
|
#ifndef DMR_H
|
||||||
|
#define TDMA_FRAME_DURATION 60
|
||||||
|
#endif
|
||||||
|
|
||||||
// #include "ASNTools.h"
|
// #include "ASNTools.h"
|
||||||
#ifndef ASNTOOLS_H
|
#ifndef ASNTOOLS_H
|
||||||
#define ASN_SEQUENCE 0x10
|
#define ASN_SEQUENCE 0x10
|
||||||
|
@ -110,14 +122,15 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#define MODE_CONSOLE (1 << 0)
|
#define MODE_CONSOLE (1 << 0)
|
||||||
#define MODE_SYSLOG (1 << 1)
|
#define MODE_SYSLOG (1 << 1)
|
||||||
#define MODE_DAEMON (1 << 2)
|
#define MODE_DAEMON (1 << 2)
|
||||||
|
|
||||||
#define EVENT_LIST_LENGTH (4 + 1 + 4)
|
#define EVENT_LIST_LENGTH (4 + 2 + 4)
|
||||||
|
|
||||||
#define BUFFER_SIZE 4096
|
#define BUFFER_SIZE 2048 // 2 KB
|
||||||
#define EXPIRATION_TIME 20
|
#define EXPIRATION_TIME 60 // 1 minute
|
||||||
|
#define INITIAL_INTERVAL 100 * 1000000 // 100 milliseconds
|
||||||
|
|
||||||
|
|
||||||
int serviceMode = MODE_CONSOLE;
|
int serviceMode = MODE_CONSOLE;
|
||||||
|
@ -224,7 +237,7 @@ 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 <local port for BrandMeister DMR Server>\n"
|
" --server-port <service port for BrandMeister DMR Server>\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"
|
||||||
|
@ -235,6 +248,12 @@ int main(int argc, const char* argv[])
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (serviceMode & MODE_SYSLOG)
|
||||||
|
{
|
||||||
|
// Set proper origin for syslog (required by OpenWRT)
|
||||||
|
openlog("CronosAgent", LOG_NOWAIT | LOG_PID, LOG_USER);
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
if ((serviceMode & MODE_DAEMON) &&
|
if ((serviceMode & MODE_DAEMON) &&
|
||||||
(daemon(-1, -1) < 0))
|
(daemon(-1, -1) < 0))
|
||||||
|
@ -297,38 +316,41 @@ int main(int argc, const char* argv[])
|
||||||
int trapHandle;
|
int trapHandle;
|
||||||
int mediaHandle;
|
int mediaHandle;
|
||||||
int remoteHandle;
|
int remoteHandle;
|
||||||
|
int socketOptionValue;
|
||||||
struct sockaddr_in proxySocketAddress;
|
struct sockaddr_in proxySocketAddress;
|
||||||
|
|
||||||
socklen_t proxySocketLength = sizeof(proxySocketAddress);
|
socklen_t proxySocketLength = sizeof(proxySocketAddress);
|
||||||
int socketOptionValue = true;
|
|
||||||
|
|
||||||
proxySocketAddress.sin_family = AF_INET;
|
proxySocketAddress.sin_family = AF_INET;
|
||||||
proxySocketAddress.sin_addr.s_addr = htonl(INADDR_ANY);
|
proxySocketAddress.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||||
|
|
||||||
proxySocketAddress.sin_port = htons(proxyTrapPort);
|
proxySocketAddress.sin_port = htons(proxyTrapPort);
|
||||||
trapHandle = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
trapHandle = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
||||||
if((trapHandle < 0) ||
|
if ((trapHandle < 0) ||
|
||||||
(bind(trapHandle, (struct sockaddr*)&proxySocketAddress, proxySocketLength) < 0))
|
(bind(trapHandle, (struct sockaddr*)&proxySocketAddress, proxySocketLength) < 0))
|
||||||
{
|
{
|
||||||
print("Error opening port for SNMP Traps\n");
|
print("Error opening port for SNMP Traps\n");
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
socketOptionValue = true;
|
||||||
proxySocketAddress.sin_port = 0;
|
proxySocketAddress.sin_port = 0;
|
||||||
remoteHandle = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
remoteHandle = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
||||||
if((remoteHandle < 0) ||
|
if ((remoteHandle < 0) ||
|
||||||
(bind(remoteHandle, (struct sockaddr*)&proxySocketAddress, proxySocketLength) < 0) ||
|
(bind(remoteHandle, (struct sockaddr*)&proxySocketAddress, proxySocketLength) < 0) ||
|
||||||
(setsockopt(remoteHandle, IPPROTO_IP, IP_PKTINFO, &socketOptionValue, sizeof(socketOptionValue)) < 0))
|
(setsockopt(remoteHandle, IPPROTO_IP, IP_PKTINFO, &socketOptionValue, sizeof(socketOptionValue)) < 0))
|
||||||
{
|
{
|
||||||
print("Error opening port for Remote Control\n");
|
print("Error opening port for Remote Control\n");
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
socketOptionValue = IPTOS_LOWDELAY;
|
||||||
proxySocketAddress.sin_port = 0;
|
proxySocketAddress.sin_port = 0;
|
||||||
mediaHandle = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
mediaHandle = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
||||||
if((mediaHandle < 0) ||
|
if ((mediaHandle < 0) ||
|
||||||
(bind(mediaHandle, (struct sockaddr*)&proxySocketAddress, proxySocketLength) < 0) ||
|
(bind(mediaHandle, (struct sockaddr*)&proxySocketAddress, proxySocketLength) < 0) ||
|
||||||
(getsockname(mediaHandle, (struct sockaddr*)&proxySocketAddress, &proxySocketLength) < 0))
|
(getsockname(mediaHandle, (struct sockaddr*)&proxySocketAddress, &proxySocketLength) < 0) ||
|
||||||
|
(setsockopt(mediaHandle, IPPROTO_IP, IP_TOS, &socketOptionValue, sizeof(socketOptionValue)) < 0))
|
||||||
{
|
{
|
||||||
print("Error opening port for External Server\n");
|
print("Error opening port for External Server\n");
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
|
@ -345,8 +367,8 @@ int main(int argc, const char* argv[])
|
||||||
uplinkSocketAddress.sin6_scope_id = 0;
|
uplinkSocketAddress.sin6_scope_id = 0;
|
||||||
|
|
||||||
uplinkHandle = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
|
uplinkHandle = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
|
||||||
if((uplinkHandle < 0) ||
|
if ((uplinkHandle < 0) ||
|
||||||
(bind(uplinkHandle, (struct sockaddr*)&uplinkSocketAddress, sizeof(uplinkSocketAddress)) < 0))
|
(bind(uplinkHandle, (struct sockaddr*)&uplinkSocketAddress, sizeof(uplinkSocketAddress)) < 0))
|
||||||
{
|
{
|
||||||
print("Error opening port for Rewind Uplink\n");
|
print("Error opening port for Rewind Uplink\n");
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
|
@ -356,15 +378,22 @@ int main(int argc, const char* argv[])
|
||||||
|
|
||||||
// Initialize timer handle
|
// Initialize timer handle
|
||||||
|
|
||||||
int timerHandle;
|
int timerHandle1;
|
||||||
|
int timerHandle2;
|
||||||
struct itimerspec timerInterval;
|
struct itimerspec timerInterval;
|
||||||
|
|
||||||
memset(&timerInterval, 0, sizeof(timerInterval));
|
memset(&timerInterval, 0, sizeof(timerInterval));
|
||||||
timerInterval.it_interval.tv_sec = REWIND_KEEP_ALIVE_INTERVAL;
|
|
||||||
timerInterval.it_value.tv_sec = REWIND_KEEP_ALIVE_INTERVAL;
|
|
||||||
|
|
||||||
timerHandle = timerfd_create(CLOCK_MONOTONIC, 0);
|
timerInterval.it_value.tv_nsec = INITIAL_INTERVAL;
|
||||||
timerfd_settime(timerHandle, 0, &timerInterval, NULL);
|
timerInterval.it_interval.tv_sec = REWIND_KEEP_ALIVE_INTERVAL;
|
||||||
|
|
||||||
|
timerHandle1 = timerfd_create(CLOCK_MONOTONIC, 0);
|
||||||
|
timerfd_settime(timerHandle1, 0, &timerInterval, NULL);
|
||||||
|
|
||||||
|
timerInterval.it_interval.tv_sec = 0;
|
||||||
|
timerInterval.it_interval.tv_nsec = TDMA_FRAME_DURATION * 1000000;
|
||||||
|
|
||||||
|
timerHandle2 = timerfd_create(CLOCK_MONOTONIC, 0);
|
||||||
|
timerfd_settime(timerHandle2, 0, &timerInterval, NULL);
|
||||||
|
|
||||||
// Initialize signal handle
|
// Initialize signal handle
|
||||||
|
|
||||||
|
@ -404,7 +433,11 @@ int main(int argc, const char* argv[])
|
||||||
epoll_ctl(pollHandle, EPOLL_CTL_ADD, event.data.fd, &event);
|
epoll_ctl(pollHandle, EPOLL_CTL_ADD, event.data.fd, &event);
|
||||||
|
|
||||||
event.events = EPOLLIN;
|
event.events = EPOLLIN;
|
||||||
event.data.fd = timerHandle;
|
event.data.fd = timerHandle1;
|
||||||
|
epoll_ctl(pollHandle, EPOLL_CTL_ADD, event.data.fd, &event);
|
||||||
|
|
||||||
|
event.events = EPOLLIN;
|
||||||
|
event.data.fd = timerHandle2;
|
||||||
epoll_ctl(pollHandle, EPOLL_CTL_ADD, event.data.fd, &event);
|
epoll_ctl(pollHandle, EPOLL_CTL_ADD, event.data.fd, &event);
|
||||||
|
|
||||||
event.events = EPOLLIN;
|
event.events = EPOLLIN;
|
||||||
|
@ -450,6 +483,9 @@ int main(int argc, const char* argv[])
|
||||||
EV_SET(change, 1, EVFILT_TIMER, EV_ADD | EV_ENABLE, NOTE_SECONDS, REWIND_KEEP_ALIVE_INTERVAL, 0);
|
EV_SET(change, 1, EVFILT_TIMER, EV_ADD | EV_ENABLE, NOTE_SECONDS, REWIND_KEEP_ALIVE_INTERVAL, 0);
|
||||||
change ++;
|
change ++;
|
||||||
|
|
||||||
|
EV_SET(change, 2, EVFILT_TIMER, EV_ADD | EV_ENABLE, NOTE_USECONDS, TDMA_FRAME_DURATION, 0);
|
||||||
|
change ++;
|
||||||
|
|
||||||
EV_SET(change, SIGINT, EVFILT_SIGNAL, EV_ADD | EV_ENABLE, 0, 0, 0);
|
EV_SET(change, SIGINT, EVFILT_SIGNAL, EV_ADD | EV_ENABLE, 0, 0, 0);
|
||||||
change ++;
|
change ++;
|
||||||
|
|
||||||
|
@ -472,7 +508,9 @@ int main(int argc, const char* argv[])
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Prepare uplink buffers
|
// Prepare buffers
|
||||||
|
|
||||||
|
void* controlBuffer = alloca(BUFFER_SIZE);
|
||||||
|
|
||||||
struct RewindData* incomingBuffer = (struct RewindData*)alloca(sizeof(struct RewindData) + BUFFER_SIZE);
|
struct RewindData* incomingBuffer = (struct RewindData*)alloca(sizeof(struct RewindData) + BUFFER_SIZE);
|
||||||
struct RewindData* outgoingBuffer = (struct RewindData*)alloca(sizeof(struct RewindData) + BUFFER_SIZE);
|
struct RewindData* outgoingBuffer = (struct RewindData*)alloca(sizeof(struct RewindData) + BUFFER_SIZE);
|
||||||
|
@ -483,7 +521,10 @@ 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 sequenceNumbers[] =
|
struct RingBuffer ringBuffers[2];
|
||||||
|
memset(ringBuffers, 0, sizeof(ringBuffers));
|
||||||
|
|
||||||
|
uint32_t sequenceNumbers[] =
|
||||||
{
|
{
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
|
@ -491,6 +532,9 @@ int main(int argc, const char* argv[])
|
||||||
0
|
0
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct utsname systemName;
|
||||||
|
uname(&systemName);
|
||||||
|
|
||||||
// Main loop
|
// Main loop
|
||||||
|
|
||||||
bool running = true;
|
bool running = true;
|
||||||
|
@ -542,6 +586,21 @@ int main(int argc, const char* argv[])
|
||||||
|
|
||||||
if (type == REWIND_TYPE_EXTERNAL_SERVER)
|
if (type == REWIND_TYPE_EXTERNAL_SERVER)
|
||||||
{
|
{
|
||||||
|
uint16_t flags = le16toh(incomingBuffer->flags);
|
||||||
|
uint32_t number = le32toh(incomingBuffer->number);
|
||||||
|
|
||||||
|
if (flags & REWIND_FLAG_REAL_TIME_1)
|
||||||
|
{
|
||||||
|
PokeData(ringBuffers + 0, number, incomingBuffer->data, length);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flags & REWIND_FLAG_REAL_TIME_2)
|
||||||
|
{
|
||||||
|
PokeData(ringBuffers + 1, number, incomingBuffer->data, length);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
repeaterSocketAddress.sin_port = htons(KAIROS_HAM_DEFAULT_PORT);
|
repeaterSocketAddress.sin_port = htons(KAIROS_HAM_DEFAULT_PORT);
|
||||||
sendto(mediaHandle, incomingBuffer->data, length, 0, (struct sockaddr*)&repeaterSocketAddress, sizeof(struct sockaddr_in));
|
sendto(mediaHandle, incomingBuffer->data, length, 0, (struct sockaddr*)&repeaterSocketAddress, sizeof(struct sockaddr_in));
|
||||||
continue;
|
continue;
|
||||||
|
@ -580,6 +639,10 @@ int main(int argc, const char* argv[])
|
||||||
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);
|
||||||
|
|
||||||
|
socketOptionValue = true;
|
||||||
|
setsockopt(remoteHandle, IPPROTO_IP, IP_PKTINFO, &socketOptionValue, sizeof(socketOptionValue));
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -646,7 +709,7 @@ int main(int argc, const char* argv[])
|
||||||
message.msg_namelen = sizeof(address);
|
message.msg_namelen = sizeof(address);
|
||||||
message.msg_iov = &vector;
|
message.msg_iov = &vector;
|
||||||
message.msg_iovlen = 1;
|
message.msg_iovlen = 1;
|
||||||
message.msg_control = alloca(BUFFER_SIZE);
|
message.msg_control = controlBuffer;
|
||||||
message.msg_controllen = BUFFER_SIZE;
|
message.msg_controllen = BUFFER_SIZE;
|
||||||
message.msg_flags = 0;
|
message.msg_flags = 0;
|
||||||
|
|
||||||
|
@ -724,15 +787,16 @@ int main(int argc, const char* argv[])
|
||||||
// Handle timer to transmit keep-alive
|
// Handle timer to transmit keep-alive
|
||||||
|
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
if (event->data.fd == timerHandle)
|
if (event->data.fd == timerHandle1)
|
||||||
{
|
{
|
||||||
uint64_t information;
|
uint64_t information;
|
||||||
read(timerHandle, &information, sizeof(information));
|
read(timerHandle1, &information, sizeof(information));
|
||||||
|
|
||||||
clock_gettime(CLOCK_MONOTONIC, &now);
|
clock_gettime(CLOCK_MONOTONIC, &now);
|
||||||
#endif
|
#endif
|
||||||
#ifdef __MACH__
|
#ifdef __MACH__
|
||||||
if (event->filter == EVFILT_TIMER)
|
if ((event->ident == 1) &&
|
||||||
|
(event->filter == EVFILT_TIMER))
|
||||||
{
|
{
|
||||||
clock_get_time(clockService, &now);
|
clock_get_time(clockService, &now);
|
||||||
#endif
|
#endif
|
||||||
|
@ -748,18 +812,41 @@ int main(int argc, const char* argv[])
|
||||||
|
|
||||||
data->number = htole32(repeaterNumber);
|
data->number = htole32(repeaterNumber);
|
||||||
data->service = REWIND_SERVICE_CRONOS_AGENT;
|
data->service = REWIND_SERVICE_CRONOS_AGENT;
|
||||||
length += sprintf(data->description, "CronosAgent " STRING(VERSION) " " BUILD);
|
|
||||||
|
length += sprintf(data->description,
|
||||||
|
"CronosAgent " STRING(VERSION) " %s %s " BUILD,
|
||||||
|
systemName.sysname,
|
||||||
|
systemName.machine);
|
||||||
|
|
||||||
outgoingBuffer->type = htole16(REWIND_TYPE_KEEP_ALIVE);
|
outgoingBuffer->type = htole16(REWIND_TYPE_KEEP_ALIVE);
|
||||||
outgoingBuffer->flags = htole16(REWIND_FLAG_DEFAULT_SET);
|
outgoingBuffer->flags = htole16(REWIND_FLAG_DEFAULT_SET);
|
||||||
outgoingBuffer->number = htole32(++ sequenceNumbers[0]);
|
outgoingBuffer->number = htole32(++ sequenceNumbers[0]);
|
||||||
outgoingBuffer->length = htobe16(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);
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Handle timer to process RingBuffer
|
||||||
|
|
||||||
|
#ifdef __linux__
|
||||||
|
if (event->data.fd == timerHandle2)
|
||||||
|
{
|
||||||
|
uint64_t information;
|
||||||
|
read(timerHandle2, &information, sizeof(information));
|
||||||
|
#endif
|
||||||
|
#ifdef __MACH__
|
||||||
|
if ((event->ident == 2) &&
|
||||||
|
(event->filter == EVFILT_TIMER))
|
||||||
|
{
|
||||||
|
#endif
|
||||||
|
repeaterSocketAddress.sin_port = htons(KAIROS_HAM_DEFAULT_PORT);
|
||||||
|
ProcessBuffer(ringBuffers + 0, mediaHandle, &repeaterSocketAddress);
|
||||||
|
ProcessBuffer(ringBuffers + 1, mediaHandle, &repeaterSocketAddress);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// Handle signal from the kernel
|
// Handle signal from the kernel
|
||||||
|
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
|
@ -792,10 +879,6 @@ int main(int argc, const char* argv[])
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// SIGHUP
|
|
||||||
|
|
||||||
socketOptionValue = true;
|
|
||||||
setsockopt(remoteHandle, IPPROTO_IP, IP_PKTINFO, &socketOptionValue, sizeof(socketOptionValue));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -811,7 +894,8 @@ int main(int argc, const char* argv[])
|
||||||
|
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
close(pollHandle);
|
close(pollHandle);
|
||||||
close(timerHandle);
|
close(timerHandle1);
|
||||||
|
close(timerHandle2);
|
||||||
close(signalHandle);
|
close(signalHandle);
|
||||||
#endif
|
#endif
|
||||||
#ifdef __MACH__
|
#ifdef __MACH__
|
||||||
|
|
Loading…
Add table
Reference in a new issue