Commit 0901a155 authored by captainwong's avatar captainwong

add server_demo

parent c860bb2d
......@@ -5,6 +5,8 @@ VisualStudioVersion = 16.0.29306.81
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "demo", "demo\demo.vcxproj", "{36640D95-55AB-4DCF-9062-91A53203E6A9}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "server_demo", "server_demo\server_demo.vcxproj", "{EA5A04AA-EE49-4059-81A0-765402A210E7}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
......@@ -21,6 +23,14 @@ Global
{36640D95-55AB-4DCF-9062-91A53203E6A9}.Release|x64.Build.0 = Release|x64
{36640D95-55AB-4DCF-9062-91A53203E6A9}.Release|x86.ActiveCfg = Release|Win32
{36640D95-55AB-4DCF-9062-91A53203E6A9}.Release|x86.Build.0 = Release|Win32
{EA5A04AA-EE49-4059-81A0-765402A210E7}.Debug|x64.ActiveCfg = Debug|x64
{EA5A04AA-EE49-4059-81A0-765402A210E7}.Debug|x64.Build.0 = Debug|x64
{EA5A04AA-EE49-4059-81A0-765402A210E7}.Debug|x86.ActiveCfg = Debug|Win32
{EA5A04AA-EE49-4059-81A0-765402A210E7}.Debug|x86.Build.0 = Debug|Win32
{EA5A04AA-EE49-4059-81A0-765402A210E7}.Release|x64.ActiveCfg = Release|x64
{EA5A04AA-EE49-4059-81A0-765402A210E7}.Release|x64.Build.0 = Release|x64
{EA5A04AA-EE49-4059-81A0-765402A210E7}.Release|x86.ActiveCfg = Release|Win32
{EA5A04AA-EE49-4059-81A0-765402A210E7}.Release|x86.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
......
#ifndef _CRT_SECURE_NO_WARNINGS
#define _CRT_SECURE_NO_WARNINGS
#endif
#define DISABLE_JLIB_LOG2
#include <ademco_packet.h>
#include <ademco_detail.h>
#include <WinSock2.h>
#pragma comment(lib, "ws2_32.lib")
#include <thread>
#include <vector>
#include <mutex>
using namespace ademco;
void usage(const char* name)
{
printf("Usage: %s listening_port\nWhile connection established, press A for Arm, D for Disarm, Q for Quit\n", name);
}
constexpr size_t BUFF_SIZE = 4096;
struct Buffer
{
unsigned int rpos;
unsigned int wpos;
char buff[BUFF_SIZE];
Buffer() { clear(); }
void clear() { memset(this, 0, sizeof(Buffer)); }
};
SOCKET clientSock = INVALID_SOCKET;
Buffer clientBuffer = {};
std::string clientAcct = {};
size_t clientAdemcoId = 0;
std::mutex mutex = {};
std::vector<ADEMCO_EVENT> evntsWaiting4Send = {};
int main(int argc, char** argv)
{
usage(argv[0]);
if (argc < 2) {
return 0;
}
WSADATA wsaData;
int err = WSAStartup(MAKEWORD(1, 1), &wsaData);
if (err != 0) {
printf("init wsa failed %d\n", err);
abort();
}
int port = atoi(argv[1]);
struct sockaddr_in sAddrIn;
memset(&sAddrIn, 0, sizeof(sAddrIn));
sAddrIn.sin_family = AF_INET;
sAddrIn.sin_port = htons(static_cast<u_short>(port));
sAddrIn.sin_addr.S_un.S_addr = ADDR_ANY;
auto serverSock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
u_long lngMode = 1;
ioctlsocket(serverSock, FIONBIO, (u_long FAR*) & lngMode);
bind(serverSock, (struct sockaddr*) & sAddrIn, sizeof(sAddrIn));
listen(serverSock, SOMAXCONN);
auto do_accept = [&serverSock]() {
if (clientSock != INVALID_SOCKET) { return; }
struct sockaddr_in sForeignAddIn;
int nLength = sizeof(struct sockaddr_in);
fd_set rfd;
FD_ZERO(&rfd);
FD_SET(serverSock, &rfd);
timeval timeout = { 1, 0 };
int nfds = select(1, &rfd, (fd_set*)0, (fd_set*)0, &timeout);
if (nfds > 0) {
FD_CLR(serverSock, &rfd);
clientSock = accept(serverSock, (struct sockaddr*) & sForeignAddIn, &nLength);
}
};
auto do_handle = []() -> ademco::ParseResult {
AdemcoPacket ap; size_t dwBytesCommited = 0;
ParseResult result = ap.parse(clientBuffer.buff + clientBuffer.rpos,
clientBuffer.wpos - clientBuffer.rpos,
dwBytesCommited);
switch (result) {
case ademco::ParseResult::RESULT_OK:
{
clientBuffer.rpos += dwBytesCommited;
//printf("id=%s\n", ap.id_.data());
printf("C:%s\n", ap.toString().data());
switch (ap.id_.eid_) {
case AdemcoId::id_ack:
// success
break;
case AdemcoId::id_null: // reply ack
{
char ack[1024];
auto len = ap.make_ack(ack, sizeof(ack), ap.seq_.value_, ap.acct_.acct(), ap.ademcoData_.ademco_id_);
printf("S:%s\n", ap.toString().data());
send(clientSock, ack, len, 0);
break;
}
case AdemcoId::id_hb: // event report
{
clientAcct = ap.acct_.acct();
clientAdemcoId = ap.ademcoData_.ademco_id_;
// handle event
//printf("%s\n", ap.ademcoData_.toString().data());
// reply ack
{
char ack[1024];
auto len = ap.make_ack(ack, sizeof(ack), ap.seq_.value_, ap.acct_.acct(), ap.ademcoData_.ademco_id_);
printf("S:%s\n", ap.toString().data());
// send to machine via network
send(clientSock, ack, len, 0);
}
break;
}
default:
break;
}
break;
}
case ademco::ParseResult::RESULT_NOT_ENOUGH:
// do nothing
break;
case ademco::ParseResult::RESULT_DATA_ERROR:
default:
// error handle, e.g. clear buff
clientBuffer.clear();
break;
}
return result;
};
auto do_read = [&do_handle]() {
if (clientSock == INVALID_SOCKET) return;
timeval tv = { 0, 0 };
fd_set fd_read;
FD_ZERO(&fd_read);
FD_SET(clientSock, &fd_read);
BOOL bRead = FD_ISSET(clientSock, &fd_read);
if (!bRead) { return; }
char* temp = clientBuffer.buff + clientBuffer.wpos;
DWORD dwLenToRead = BUFF_SIZE - clientBuffer.wpos;
int bytes_transfered = recv(clientSock, temp, dwLenToRead, 0);
if (SOCKET_ERROR == bytes_transfered) {
if (WSAEWOULDBLOCK == WSAGetLastError()) {
return;
}
}
if (bytes_transfered <= 0) {
printf("client offline\n");
closesocket(clientSock);
clientBuffer.clear();
} else {
clientBuffer.wpos += bytes_transfered;
auto result = do_handle();
while (1) {
unsigned int bytes_not_commited = clientBuffer.wpos - clientBuffer.rpos;
if (bytes_not_commited == 0) {
if (clientBuffer.wpos == BUFF_SIZE) {
clientBuffer.clear();
}
break;
}
if (clientBuffer.wpos == BUFF_SIZE) {
memmove_s(clientBuffer.buff, BUFF_SIZE, clientBuffer.buff + clientBuffer.rpos, bytes_not_commited);
memset(clientBuffer.buff + bytes_not_commited, 0, BUFF_SIZE - bytes_not_commited);
clientBuffer.wpos -= clientBuffer.rpos; clientBuffer.rpos = 0;
result = do_handle();
} else {
result = do_handle();
}
if (result == ademco::ParseResult::RESULT_NOT_ENOUGH) { break; }
}
}
};
bool running = true;
std::thread worker([&running, &serverSock, &do_accept, &do_read]() {
while (running) {
std::this_thread::sleep_for(std::chrono::milliseconds(100));
do_accept();
do_read();
if (clientSock != INVALID_SOCKET && !evntsWaiting4Send.empty()) {
std::lock_guard<std::mutex> lg(mutex);
char buf[1024];
AdemcoPacket ap;
for (auto e : evntsWaiting4Send) {
auto len = ap.make_hb(buf, sizeof(buf), 1, clientAcct, clientAdemcoId, 0, e, 0);
printf("S:%s\n", ap.toString().data());
send(clientSock, buf, len, 0);
}
evntsWaiting4Send.clear();
}
}
});
while (1) {
std::this_thread::sleep_for(std::chrono::milliseconds(200));
int cmd = getc(stdin);
if (cmd == 'a' || cmd == 'A') {
std::lock_guard<std::mutex> lg(mutex);
evntsWaiting4Send.push_back(EVENT_ARM);
} else if (cmd == 'd' || cmd == 'D') {
std::lock_guard<std::mutex> lg(mutex);
evntsWaiting4Send.push_back(EVENT_DISARM);
} else if (cmd == '\r' || cmd == '\n') {
} else if (cmd == 'q' || cmd == 'Q') {
running = false;
worker.join();
break;
} else {
printf("Press A for Arm, D for Disarm, Q for Quit\n");
}
}
printf("Bye!");
}
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>16.0</VCProjectVersion>
<ProjectGuid>{EA5A04AA-EE49-4059-81A0-765402A210E7}</ProjectGuid>
<RootNamespace>serverdemo</RootNamespace>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup />
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<ConformanceMode>true</ConformanceMode>
<AdditionalIncludeDirectories>$(SolutionDir)include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<SDLCheck>true</SDLCheck>
<ConformanceMode>true</ConformanceMode>
<AdditionalIncludeDirectories>$(SolutionDir)include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<SDLCheck>true</SDLCheck>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="server_demo.cpp" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;hm;inl;inc;ipp;xsd</Extensions>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="server_demo.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
</Project>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LocalDebuggerCommandArguments>12346</LocalDebuggerCommandArguments>
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
</PropertyGroup>
</Project>
\ No newline at end of file
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