Commit 685b679d authored by captainwong's avatar captainwong

update httprelay & server_demo with new api

parent 2e893557
#include <stdio.h> #include <stdio.h>
#include "../../hb_com.h" #include "../../hb_com.h"
#include "uvlib/uv_log.h" #include "uvlib/uv_log.h"
#include "uvlib/uv_tcpserver.h" #include "uvlib/uv_tcpserver.h"
#include "cJSON/cJSON.h" #include "cJSON/cJSON.h"
#include <curl/curl.h> #include <curl/curl.h>
#include <string.h> #include <string.h>
typedef struct machine_info_s { typedef struct machine_info_s {
char acct[ADEMCO_PACKET_ACCT_MAX_LEN + 1]; char acct[ADEMCO_PACKET_ACCT_MAX_LEN + 1];
AdemcoId ademcoId; AdemcoId ademcoId;
HbMachineType type; HbMachineType type;
HbMachineStatus status; HbMachineStatus status;
}machine_info_t; }machine_info_t;
struct { struct {
uv_loop_t* loop; uv_loop_t* loop;
uv_tcpserver_t* tcpd; uv_tcpserver_t* tcpd;
const char* uri; const char* uri;
}context; }context;
size_t on_write(void* buffer, size_t size, size_t nmemb, void* user) { size_t on_write(void* buffer, size_t size, size_t nmemb, void* user) {
mybuf_t* buf = user; mybuf_t* buf = user;
mybuf_append(buf, buffer, size * nmemb); mybuf_append(buf, buffer, size * nmemb);
return size * nmemb; return size * nmemb;
} }
int post(const char* json) { int post(const char* json) {
CURLcode res; CURLcode res;
CURL* curl = curl_easy_init(); CURL* curl = curl_easy_init();
struct curl_slist* headers = NULL; struct curl_slist* headers = NULL;
mybuf_t resp; mybuf_t resp;
long http_status, header_size; long http_status, header_size;
mybuf_init(&resp); mybuf_init(&resp);
do { do {
if (!curl) { if (!curl) {
res = CURLE_FAILED_INIT; res = CURLE_FAILED_INIT;
uvlog_error("curl_easy_init failed"); uvlog_error("curl_easy_init failed");
break; break;
} }
headers = curl_slist_append(headers, "Content-Type: application/json"); headers = curl_slist_append(headers, "Content-Type: application/json");
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1); curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1);
curl_easy_setopt(curl, CURLOPT_HEADER, 1); curl_easy_setopt(curl, CURLOPT_HEADER, 1);
curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1); curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0); curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0);
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0); curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0);
curl_easy_setopt(curl, CURLOPT_POST, 1); curl_easy_setopt(curl, CURLOPT_POST, 1);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &resp); curl_easy_setopt(curl, CURLOPT_WRITEDATA, &resp);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, on_write); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, on_write);
curl_easy_setopt(curl, CURLOPT_URL, context.uri); curl_easy_setopt(curl, CURLOPT_URL, context.uri);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, json); curl_easy_setopt(curl, CURLOPT_POSTFIELDS, json);
curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, strlen(json)); curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, strlen(json));
curl_easy_setopt(curl, CURLOPT_TIMEOUT, 3); curl_easy_setopt(curl, CURLOPT_TIMEOUT, 3);
res = curl_easy_perform(curl); res = curl_easy_perform(curl);
if (res == CURLE_OK || res == CURLE_GOT_NOTHING) { if (res == CURLE_OK || res == CURLE_GOT_NOTHING) {
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_status); curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_status);
curl_easy_getinfo(curl, CURLINFO_HEADER_SIZE, &header_size); curl_easy_getinfo(curl, CURLINFO_HEADER_SIZE, &header_size);
} }
mybuf_reserve(&resp, resp.size + 1); mybuf_reserve(&resp, resp.size + 1);
resp.buf[resp.size] = '\0'; resp.buf[resp.size] = '\0';
uvlog_debug("RESP: %d %s\n" uvlog_debug("RESP: %d %s\n"
"%s\n", "%s\n",
res, curl_easy_strerror(res), res, curl_easy_strerror(res),
resp.buf); resp.buf);
} while (0); } while (0);
if (curl) if (curl)
curl_easy_cleanup(curl); curl_easy_cleanup(curl);
if (headers) { if (headers) {
curl_slist_free_all(headers); curl_slist_free_all(headers);
headers = NULL; headers = NULL;
} }
return 0; return 0;
} }
int relay(const char* acct, AdemcoEvent ademco_event, AdemcoZone zone, AdemcoGG gg) { int relay(const char* acct, AdemcoEvent ademco_event, AdemcoZone zone, AdemcoGG gg) {
cJSON* json = NULL; cJSON* json = NULL;
char* string = NULL; char* string = NULL;
int r = 0; int r = 0;
json = cJSON_CreateObject(); json = cJSON_CreateObject();
fatal_if_null(json); fatal_if_null(json);
if (cJSON_AddStringToObject(json, "acct", acct) == NULL) goto end; if (cJSON_AddStringToObject(json, "acct", acct) == NULL) goto end;
if (cJSON_AddNumberToObject(json, "ademco_event", ademco_event) == NULL) goto end; if (cJSON_AddNumberToObject(json, "ademco_event", ademco_event) == NULL) goto end;
if (cJSON_AddNumberToObject(json, "zone", zone) == NULL) goto end; if (cJSON_AddNumberToObject(json, "zone", zone) == NULL) goto end;
if (cJSON_AddNumberToObject(json, "gg", gg) == NULL) goto end; if (cJSON_AddNumberToObject(json, "gg", gg) == NULL) goto end;
string = cJSON_Print(json); string = cJSON_Print(json);
if (string == NULL) goto end; if (string == NULL) goto end;
uvlog_debug("OUT:\n%s\n", string); uvlog_debug("OUT:\n%s\n", string);
r = post(string); r = post(string);
end: end:
if (json) if (json)
cJSON_Delete(json); cJSON_Delete(json);
if (string) if (string)
free(string); free(string);
return r; return r;
} }
void on_tcp_connection(uv_tcpserver_client_context_t* client, int connected) { void on_tcp_connection(uv_tcpserver_client_context_t* client, int connected) {
if (connected) { if (connected) {
machine_info_t* machine = malloc(sizeof(machine_info_t)); machine_info_t* machine = malloc(sizeof(machine_info_t));
memset(machine->acct, '\0', sizeof(machine->acct)); memset(machine->acct, '\0', sizeof(machine->acct));
machine->ademcoId = 0; machine->ademcoId = 0;
machine->type = HMT_INVALID; machine->type = HMT_INVALID;
machine->status = HMS_INVALID; machine->status = HMS_INVALID;
client->data = machine; client->data = machine;
} else if(client->data) { } else if(client->data) {
if (((machine_info_t*)(client->data))->acct[0] != '\0') { if (((machine_info_t*)(client->data))->acct[0] != '\0') {
relay(((machine_info_t*)(client->data))->acct, EVENT_OFFLINE, 0, 0); relay(((machine_info_t*)(client->data))->acct, EVENT_OFFLINE, 0, 0);
} }
free(client->data); free(client->data);
} }
} }
uv_tcp_parse_result_t on_tcp_parse(uv_tcpserver_client_context_t* client, const char* buf, size_t len, size_t* ate) { uv_tcp_parse_result_t on_tcp_parse(uv_tcpserver_client_context_t* client, const char* buf, size_t len, size_t* ate) {
AdemcoPacket pkt; AdemcoPacket pkt;
AdemcoParseResult res = ademcoPacketParse(buf, len, &pkt, ate); AdemcoParseResult res = ademcoPacketParse(buf, len, &pkt, ate, NULL);
switch (res) { switch (res) {
case RESULT_OK: case RESULT_OK:
switch (pkt.id) { switch (pkt.id) {
case AID_NULL: case AID_NULL:
case AID_HB: case AID_HB:
case AID_ADM_CID: case AID_ADM_CID:
printf("C:"); printf("C:");
ademcoPrint(pkt.raw, pkt.raw_len); ademcoPrint(pkt.raw, pkt.raw_len);
if (((machine_info_t*)(client->data))->acct[0] == '\0') { if (((machine_info_t*)(client->data))->acct[0] == '\0') {
strcpy(((machine_info_t*)(client->data))->acct, pkt.acct); strcpy(((machine_info_t*)(client->data))->acct, pkt.acct);
relay(pkt.acct, EVENT_ONLINE, 0, 0); relay(pkt.acct, EVENT_ONLINE, 0, 0);
} }
if (pkt.data.ademcoId) { if (pkt.data.ademcoId) {
((machine_info_t*)(client->data))->ademcoId = pkt.data.ademcoId; ((machine_info_t*)(client->data))->ademcoId = pkt.data.ademcoId;
} }
if (ademcoIsMachineStatusEvent(pkt.data.ademcoEvent)) { if (ademcoIsMachineStatusEvent(pkt.data.ademcoEvent)) {
((machine_info_t*)(client->data))->status = hbMachineStatusFromAdemcoEvent(pkt.data.ademcoEvent); ((machine_info_t*)(client->data))->status = hbMachineStatusFromAdemcoEvent(pkt.data.ademcoEvent);
} }
if (ademcoIsMachineTypeEvent(pkt.data.ademcoEvent)) { if (ademcoIsMachineTypeEvent(pkt.data.ademcoEvent)) {
((machine_info_t*)(client->data))->type = hbMachineTypeFromAdemcoEvent(pkt.data.ademcoEvent); ((machine_info_t*)(client->data))->type = hbMachineTypeFromAdemcoEvent(pkt.data.ademcoEvent);
} }
if (pkt.data.ademcoEvent != EVENT_INVALID_EVENT && ((machine_info_t*)(client->data))->acct[0] != '\0') { if (pkt.data.ademcoEvent != EVENT_INVALID_EVENT && ((machine_info_t*)(client->data))->acct[0] != '\0') {
relay(((machine_info_t*)(client->data))->acct, pkt.data.ademcoEvent, pkt.data.zone, pkt.data.gg); relay(((machine_info_t*)(client->data))->acct, pkt.data.ademcoEvent, pkt.data.zone, pkt.data.gg);
} }
ademcoMakeAckPacket2(&pkt, pkt.seq, pkt.acct, pkt.data.ademcoId); ademcoMakeAckPacket2(&pkt, pkt.seq, pkt.acct, pkt.data.ademcoId);
uv_tcpserver_send_to_cli(client, pkt.raw, pkt.raw_len); uv_tcpserver_send_to_cli(client, pkt.raw, pkt.raw_len);
printf("S:"); printf("S:");
ademcoPrint(pkt.raw, pkt.raw_len); ademcoPrint(pkt.raw, pkt.raw_len);
break; break;
} }
return uv_tcp_parse_ok; return uv_tcp_parse_ok;
break; break;
case RESULT_NOT_ENOUGH: case RESULT_NOT_ENOUGH:
return uv_tcp_parse_not_enough; return uv_tcp_parse_not_enough;
break; break;
case RESULT_ERROR: case RESULT_ERROR:
return uv_tcp_parse_error; return uv_tcp_parse_error;
break; break;
default: default:
abort(); abort();
break; break;
} }
} }
int init_tcpd(int port) { int init_tcpd(int port) {
static uv_tcpserver_settings_t settings = { on_tcp_connection, on_tcp_parse, NULL }; static uv_tcpserver_settings_t settings = { on_tcp_connection, on_tcp_parse, NULL };
int r = uv_tcpserver_create(&context.tcpd, context.loop, &settings); int r = uv_tcpserver_create(&context.tcpd, context.loop, &settings);
fatal_on_uv_err(r, "uv_tcpserver_create"); fatal_on_uv_err(r, "uv_tcpserver_create");
r = uv_tcpserver_start_listen(context.tcpd, "0.0.0.0", port); r = uv_tcpserver_start_listen(context.tcpd, "0.0.0.0", port);
fatal_on_uv_err(r, "uv_tcpserver_start_listen"); fatal_on_uv_err(r, "uv_tcpserver_start_listen");
printf("tcp server listening on %s:%d\n", "0.0.0.0", port); printf("tcp server listening on %s:%d\n", "0.0.0.0", port);
return r; return r;
} }
int main(int argc, char** argv) { int main(int argc, char** argv) {
if (argc != 3) { if (argc != 3) {
fprintf(stderr, "Usage: %s tcp_server_listening_port http_client_relay_to_uri\n" fprintf(stderr, "Usage: %s tcp_server_listening_port http_client_relay_to_uri\n"
" Example: %s 12345 http://your-http-server.com:8080/ademco\n", " Example: %s 12345 http://your-http-server.com:8080/ademco\n",
argv[0], argv[0]); argv[0], argv[0]);
exit(1); exit(1);
} }
uv_log_set_level(uv_log_level_debug); uv_log_set_level(uv_log_level_debug);
memset(&context, 0, sizeof(context)); memset(&context, 0, sizeof(context));
context.uri = argv[2]; context.uri = argv[2];
context.loop = uv_default_loop(); context.loop = uv_default_loop();
fatal_if_null(context.loop); fatal_if_null(context.loop);
curl_global_init(CURL_GLOBAL_ALL); curl_global_init(CURL_GLOBAL_ALL);
if (init_tcpd(atoi(argv[1]))) { if (init_tcpd(atoi(argv[1]))) {
abort(); abort();
} }
uv_run(context.loop, UV_RUN_DEFAULT); uv_run(context.loop, UV_RUN_DEFAULT);
} }
#ifdef _WIN32 #ifdef _WIN32
#define _WINSOCK_DEPRECATED_NO_WARNINGS #define _WINSOCK_DEPRECATED_NO_WARNINGS
#ifndef NOMINMAX #ifndef NOMINMAX
#define NOMINMAX #define NOMINMAX
#endif #endif
#include <WinSock2.h> #include <WinSock2.h>
#pragma comment(lib, "ws2_32.lib") #pragma comment(lib, "ws2_32.lib")
#define ioctl ioctlsocket #define ioctl ioctlsocket
#define socklen_t int #define socklen_t int
#define close closesocket #define close closesocket
#else // linux #else // linux
#include <unistd.h> #include <unistd.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <sys/types.h> #include <sys/types.h>
#include <sys/ioctl.h> #include <sys/ioctl.h>
#include <netinet/in.h> #include <netinet/in.h>
#include <arpa/inet.h> #include <arpa/inet.h>
#define SOCKET int #define SOCKET int
#define INVALID_SOCKET -1 #define INVALID_SOCKET -1
#endif #endif
#define DISABLE_JLIB_LOG2 #define DISABLE_JLIB_LOG2
#include <thread> #include <thread>
#include <vector> #include <vector>
#include <mutex> #include <mutex>
#include <string.h> #include <string.h>
#include "../../ademco.h" #include "../../ademco.h"
void op_usage() { void op_usage() {
printf("Press A for Arm, D for Disarm, E for Emergency, Q for Quit\n"); printf("Press A for Arm, D for Disarm, E for Emergency, Q for Quit\n");
} }
void usage(const char* name) { void usage(const char* name) {
printf("Usage: %s listening_port\n", name); printf("Usage: %s listening_port\n", name);
op_usage(); op_usage();
} }
constexpr size_t BUFF_SIZE = 4096; constexpr size_t BUFF_SIZE = 4096;
struct Buffer { struct Buffer {
size_t rpos; size_t rpos;
size_t wpos; size_t wpos;
char buff[BUFF_SIZE]; char buff[BUFF_SIZE];
Buffer() { clear(); } Buffer() { clear(); }
void clear() { memset(this, 0, sizeof(Buffer)); } void clear() { memset(this, 0, sizeof(Buffer)); }
}; };
SOCKET clientSock = INVALID_SOCKET; SOCKET clientSock = INVALID_SOCKET;
Buffer clientBuffer = {}; Buffer clientBuffer = {};
std::string clientAcct = {}; std::string clientAcct = {};
AdemcoId clientAdemcoId = 0; AdemcoId clientAdemcoId = 0;
std::mutex mutex = {}; std::mutex mutex = {};
std::vector<AdemcoEvent> evntsWaiting4Send = {}; std::vector<AdemcoEvent> evntsWaiting4Send = {};
char pwd[1024] = {}; char pwd[1024] = {};
int setNonBlocking(SOCKET socket) { int setNonBlocking(SOCKET socket) {
u_long lngMode = 1; u_long lngMode = 1;
int ret = ioctl(socket, FIONBIO, (u_long*)&lngMode); int ret = ioctl(socket, FIONBIO, (u_long*)&lngMode);
if (ret != 0) { if (ret != 0) {
fprintf(stderr, "ioctl failed %d\n", ret); fprintf(stderr, "ioctl failed %d\n", ret);
return ret; return ret;
} }
return ret; return ret;
} }
int main(int argc, char** argv) { int main(int argc, char** argv) {
usage(argv[0]); usage(argv[0]);
#ifdef _WIN32 #ifdef _WIN32
WSADATA wsaData; WSADATA wsaData;
int err = WSAStartup(MAKEWORD(1, 1), &wsaData); int err = WSAStartup(MAKEWORD(1, 1), &wsaData);
if (err != 0) { if (err != 0) {
printf("init wsa failed %d\n", err); printf("init wsa failed %d\n", err);
abort(); abort();
} }
#endif #endif
int port = 12345; int port = 12345;
if (argc > 1) { if (argc > 1) {
port = atoi(argv[1]); port = atoi(argv[1]);
} }
struct sockaddr_in sAddrIn; struct sockaddr_in sAddrIn;
memset(&sAddrIn, 0, sizeof(sAddrIn)); memset(&sAddrIn, 0, sizeof(sAddrIn));
sAddrIn.sin_family = AF_INET; sAddrIn.sin_family = AF_INET;
sAddrIn.sin_port = htons(static_cast<u_short>(port)); sAddrIn.sin_port = htons(static_cast<u_short>(port));
sAddrIn.sin_addr.s_addr = INADDR_ANY; sAddrIn.sin_addr.s_addr = INADDR_ANY;
auto serverSock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); auto serverSock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
int ret = setNonBlocking(serverSock); int ret = setNonBlocking(serverSock);
if (ret != 0) { if (ret != 0) {
return ret; return ret;
} }
ret = bind(serverSock, (struct sockaddr*)&sAddrIn, sizeof(sAddrIn)); ret = bind(serverSock, (struct sockaddr*)&sAddrIn, sizeof(sAddrIn));
if (ret != 0) { if (ret != 0) {
fprintf(stderr, "bind failed %d\n", ret); fprintf(stderr, "bind failed %d\n", ret);
return ret; return ret;
} }
ret = listen(serverSock, SOMAXCONN); ret = listen(serverSock, SOMAXCONN);
if (ret != 0) { if (ret != 0) {
fprintf(stderr, "listen failed %d\n", ret); fprintf(stderr, "listen failed %d\n", ret);
return ret; return ret;
} }
printf("Listening on %s:%d\n", inet_ntoa(sAddrIn.sin_addr), ntohs(sAddrIn.sin_port)); printf("Listening on %s:%d\n", inet_ntoa(sAddrIn.sin_addr), ntohs(sAddrIn.sin_port));
auto do_accept = [&serverSock]() { auto do_accept = [&serverSock]() {
if (clientSock != INVALID_SOCKET) { return; } if (clientSock != INVALID_SOCKET) { return; }
struct sockaddr_in sForeignAddrIn; struct sockaddr_in sForeignAddrIn;
socklen_t nLength = sizeof(struct sockaddr_in); socklen_t nLength = sizeof(struct sockaddr_in);
fd_set rfd; fd_set rfd;
FD_ZERO(&rfd); FD_ZERO(&rfd);
FD_SET(serverSock, &rfd); FD_SET(serverSock, &rfd);
timeval timeout = { 1, 0 }; timeval timeout = { 1, 0 };
int nfds = select((int)(serverSock + 1), &rfd, (fd_set*)0, (fd_set*)0, &timeout); int nfds = select((int)(serverSock + 1), &rfd, (fd_set*)0, (fd_set*)0, &timeout);
printf("do_accept, select ret=%d\n", nfds); printf("do_accept, select ret=%d\n", nfds);
if (nfds > 0) { if (nfds > 0) {
FD_CLR(serverSock, &rfd); FD_CLR(serverSock, &rfd);
clientSock = accept(serverSock, (struct sockaddr*)&sForeignAddrIn, &nLength); clientSock = accept(serverSock, (struct sockaddr*)&sForeignAddrIn, &nLength);
int ret = setNonBlocking(clientSock); int ret = setNonBlocking(clientSock);
if (ret != 0) { if (ret != 0) {
exit(0); exit(0);
} }
printf("Got connection from %s:%d, fd=%d\n", inet_ntoa(sForeignAddrIn.sin_addr), sForeignAddrIn.sin_port, (int)clientSock); printf("Got connection from %s:%d, fd=%d\n", inet_ntoa(sForeignAddrIn.sin_addr), sForeignAddrIn.sin_port, (int)clientSock);
} }
}; };
auto do_handle = []() -> AdemcoParseResult { auto do_handle = []() -> AdemcoParseResult {
AdemcoPacket pkt; size_t cb = 0; AdemcoPacket pkt; size_t cb = 0;
AdemcoParseResult result = ademcoPacketParse(clientBuffer.buff + clientBuffer.rpos, AdemcoParseResult result = ademcoPacketParse(clientBuffer.buff + clientBuffer.rpos,
clientBuffer.wpos - clientBuffer.rpos, clientBuffer.wpos - clientBuffer.rpos,
&pkt, &pkt,
&cb); &cb,
nullptr);
switch (result) {
case AdemcoParseResult::RESULT_OK: switch (result) {
{ case AdemcoParseResult::RESULT_OK:
clientBuffer.rpos += cb; {
//printf("id=%s\n", ap.id_.data()); clientBuffer.rpos += cb;
printf("C:"); ademcoPrint(pkt.raw, pkt.raw_len); //printf("id=%s\n", ap.id_.data());
switch (pkt.id) { printf("C:"); ademcoPrint(pkt.raw, pkt.raw_len);
case AID_ACK: switch (pkt.id) {
// success case AID_ACK:
break; // success
break;
case AID_NULL: // reply ack
{ case AID_NULL: // reply ack
char ack[1024]; {
size_t len = ademcoMakeAckPacket(ack, sizeof(ack), pkt.seq, pkt.acct, 0); char ack[1024];
printf("S:"); ademcoPrint(ack, len); size_t len = ademcoMakeAckPacket(ack, sizeof(ack), pkt.seq, pkt.acct, 0);
send(clientSock, (const char*)ack, len, 0); printf("S:"); ademcoPrint(ack, len);
break; send(clientSock, (const char*)ack, len, 0);
} break;
}
case AID_HB: // event report
case AID_ADM_CID: case AID_HB: // event report
{ case AID_ADM_CID:
clientAcct = pkt.acct; {
clientAdemcoId = pkt.data.ademcoId; clientAcct = pkt.acct;
// handle event clientAdemcoId = pkt.data.ademcoId;
// handle event
// reply ack
{ // reply ack
char ack[1024]; {
int len = ademcoMakeAckPacket(ack, sizeof(ack), pkt.seq, pkt.acct, 0); char ack[1024];
printf("S:"); ademcoPrint(ack, len); int len = ademcoMakeAckPacket(ack, sizeof(ack), pkt.seq, pkt.acct, 0);
send(clientSock, (const char*)ack, len, 0); printf("S:"); ademcoPrint(ack, len);
} send(clientSock, (const char*)ack, len, 0);
}
break;
} break;
}
default:
break; default:
} break;
break; }
} break;
}
case AdemcoParseResult::RESULT_NOT_ENOUGH:
// do nothing case AdemcoParseResult::RESULT_NOT_ENOUGH:
break; // do nothing
break;
case AdemcoParseResult::RESULT_ERROR:
default: case AdemcoParseResult::RESULT_ERROR:
// error handle, e.g. clear buff default:
clientBuffer.clear(); // error handle, e.g. clear buff
break; clientBuffer.clear();
} break;
}
return result;
}; return result;
};
auto do_read = [&do_handle]() {
if (clientSock == INVALID_SOCKET) return; auto do_read = [&do_handle]() {
if (clientSock == INVALID_SOCKET) return;
timeval tv = { 0, 1000000 };
fd_set fd_read; timeval tv = { 0, 1000000 };
FD_ZERO(&fd_read); fd_set fd_read;
FD_SET(clientSock, &fd_read); FD_ZERO(&fd_read);
int nfds = select(int(clientSock + 1), &fd_read, (fd_set*)0, (fd_set*)0, &tv); FD_SET(clientSock, &fd_read);
if (nfds <= 0) { int nfds = select(int(clientSock + 1), &fd_read, (fd_set*)0, (fd_set*)0, &tv);
return; if (nfds <= 0) {
} return;
}
int bRead = FD_ISSET(clientSock, &fd_read);
if (!bRead) { return; } int bRead = FD_ISSET(clientSock, &fd_read);
if (!bRead) { return; }
char* temp = clientBuffer.buff + clientBuffer.wpos;
size_t dwLenToRead = BUFF_SIZE - clientBuffer.wpos; char* temp = clientBuffer.buff + clientBuffer.wpos;
int bytes_transfered = recv(clientSock, (char*)temp, (int)dwLenToRead, 0); size_t dwLenToRead = BUFF_SIZE - clientBuffer.wpos;
int bytes_transfered = recv(clientSock, (char*)temp, (int)dwLenToRead, 0);
if (-1 == bytes_transfered) {
if (EAGAIN == errno) { if (-1 == bytes_transfered) {
return; if (EAGAIN == errno) {
} return;
} }
}
if (bytes_transfered <= 0) {
printf("Client %d offline\n", (int)clientSock); if (bytes_transfered <= 0) {
close(clientSock); clientSock = INVALID_SOCKET; printf("Client %d offline\n", (int)clientSock);
clientBuffer.clear(); close(clientSock); clientSock = INVALID_SOCKET;
} else { clientBuffer.clear();
clientBuffer.wpos += bytes_transfered; } else {
auto result = do_handle(); clientBuffer.wpos += bytes_transfered;
while (1) { auto result = do_handle();
size_t bytes_not_commited = clientBuffer.wpos - clientBuffer.rpos; while (1) {
if (bytes_not_commited == 0) { size_t bytes_not_commited = clientBuffer.wpos - clientBuffer.rpos;
if (clientBuffer.wpos == BUFF_SIZE) { if (bytes_not_commited == 0) {
clientBuffer.clear(); if (clientBuffer.wpos == BUFF_SIZE) {
} clientBuffer.clear();
break; }
} break;
}
if (clientBuffer.wpos == BUFF_SIZE) {
memmove(clientBuffer.buff, clientBuffer.buff + clientBuffer.rpos, bytes_not_commited); if (clientBuffer.wpos == BUFF_SIZE) {
memset(clientBuffer.buff + bytes_not_commited, 0, BUFF_SIZE - bytes_not_commited); memmove(clientBuffer.buff, clientBuffer.buff + clientBuffer.rpos, bytes_not_commited);
clientBuffer.wpos -= clientBuffer.rpos; clientBuffer.rpos = 0; memset(clientBuffer.buff + bytes_not_commited, 0, BUFF_SIZE - bytes_not_commited);
result = do_handle(); clientBuffer.wpos -= clientBuffer.rpos; clientBuffer.rpos = 0;
} else { result = do_handle();
result = do_handle(); } else {
} result = do_handle();
}
if (result == AdemcoParseResult::RESULT_NOT_ENOUGH) { break; }
} if (result == AdemcoParseResult::RESULT_NOT_ENOUGH) { break; }
} }
}; }
};
bool running = true;
bool running = true;
std::thread worker([&running, &serverSock, &do_accept, &do_read]() {
while (running) { std::thread worker([&running, &serverSock, &do_accept, &do_read]() {
std::this_thread::sleep_for(std::chrono::milliseconds(100)); while (running) {
do_accept(); std::this_thread::sleep_for(std::chrono::milliseconds(100));
do_read(); do_accept();
do_read();
if (clientSock != INVALID_SOCKET && !evntsWaiting4Send.empty()) {
std::lock_guard<std::mutex> lg(mutex); if (clientSock != INVALID_SOCKET && !evntsWaiting4Send.empty()) {
char buf[1024]; std::lock_guard<std::mutex> lg(mutex);
for (auto e : evntsWaiting4Send) { char buf[1024];
if (e == EVENT_DISARM) { for (auto e : evntsWaiting4Send) {
AdemcoXDataSegment xdata; if (e == EVENT_DISARM) {
ademcoMakeXData(&xdata, TWO_HEX, AdemcoXDataTransform::AdemcoXDataTransform_as_is, pwd, 6); AdemcoXDataSegment xdata;
int len = ademcoMakeHbPacket(buf, sizeof(buf), 1, clientAcct.c_str(), clientAdemcoId, e, 0, 0, &xdata); ademcoMakeXData(&xdata, TWO_HEX, AdemcoXDataTransform::AdemcoXDataTransform_as_is, pwd, 6);
printf("S:"); ademcoPrint(buf, len); int len = ademcoMakeHbPacket(buf, sizeof(buf), 1, clientAcct.c_str(), clientAdemcoId, e, 0, 0, &xdata);
send(clientSock, (const char*)buf, len, 0); printf("S:"); ademcoPrint(buf, len);
} else { send(clientSock, (const char*)buf, len, 0);
int len = ademcoMakeHbPacket(buf, sizeof(buf), 1, clientAcct.c_str(), clientAdemcoId, e, 0, 0, nullptr); } else {
printf("S:"); ademcoPrint(buf, len); int len = ademcoMakeHbPacket(buf, sizeof(buf), 1, clientAcct.c_str(), clientAdemcoId, e, 0, 0, nullptr);
send(clientSock, (const char*)buf, len, 0); printf("S:"); ademcoPrint(buf, len);
} send(clientSock, (const char*)buf, len, 0);
}
}
evntsWaiting4Send.clear(); }
} evntsWaiting4Send.clear();
} }
}); }
});
while (1) {
std::this_thread::sleep_for(std::chrono::milliseconds(200)); while (1) {
std::this_thread::sleep_for(std::chrono::milliseconds(200));
int cmd = getc(stdin);
int cmd = getc(stdin);
if (cmd == 'a' || cmd == 'A') {
std::lock_guard<std::mutex> lg(mutex); if (cmd == 'a' || cmd == 'A') {
evntsWaiting4Send.push_back(EVENT_ARM); std::lock_guard<std::mutex> lg(mutex);
} else if (cmd == 'd' || cmd == 'D') { evntsWaiting4Send.push_back(EVENT_ARM);
int ret = 0; } else if (cmd == 'd' || cmd == 'D') {
do { int ret = 0;
printf("Input 6 digit password:"); do {
ret = scanf("%s", pwd); printf("Input 6 digit password:");
} while (ret != 1 || strlen(pwd) != 6); ret = scanf("%s", pwd);
std::lock_guard<std::mutex> lg(mutex); } while (ret != 1 || strlen(pwd) != 6);
evntsWaiting4Send.push_back(EVENT_DISARM); std::lock_guard<std::mutex> lg(mutex);
} else if (cmd == 'e' || cmd == 'E') { evntsWaiting4Send.push_back(EVENT_DISARM);
std::lock_guard<std::mutex> lg(mutex); } else if (cmd == 'e' || cmd == 'E') {
evntsWaiting4Send.push_back(EVENT_EMERGENCY); std::lock_guard<std::mutex> lg(mutex);
} else if (cmd == '\r' || cmd == '\n') { evntsWaiting4Send.push_back(EVENT_EMERGENCY);
} else if (cmd == 'q' || cmd == 'Q') { } else if (cmd == '\r' || cmd == '\n') {
running = false; } else if (cmd == 'q' || cmd == 'Q') {
worker.join(); running = false;
break; worker.join();
} else { break;
op_usage(); } else {
} op_usage();
} }
}
close(serverSock);
printf("Bye!"); close(serverSock);
} printf("Bye!");
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment