Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Contribute to GitLab
Sign in / Register
Toggle navigation
A
ademco_hb
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
captainwong
ademco_hb
Commits
685b679d
Commit
685b679d
authored
Nov 20, 2023
by
captainwong
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
update httprelay & server_demo with new api
parent
2e893557
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
528 additions
and
527 deletions
+528
-527
httprelay.c
examples/httprelay/httprelay.c
+211
-211
server_demo.cpp
examples/server_demo/server_demo.cpp
+317
-316
No files found.
examples/httprelay/httprelay.c
View file @
685b679d
#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
);
}
}
examples/server_demo/server_demo.cpp
View file @
685b679d
#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!"
);
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment