Commit a94e728e authored by captainwong's avatar captainwong

http relay

parent 7c2894e6
......@@ -13,6 +13,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ademco_static", "ademco_sta
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ademco_static_mt", "ademco_static_mt\ademco_static_mt.vcxproj", "{0AA93A45-37CE-40DE-A0E9-7163941DFB2A}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "httprelay", "httprelay\httprelay.vcxproj", "{3E0F1766-91F4-4218-A970-667F6345AF99}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
......@@ -97,6 +99,20 @@ Global
{0AA93A45-37CE-40DE-A0E9-7163941DFB2A}.Release|x64.Build.0 = Release|x64
{0AA93A45-37CE-40DE-A0E9-7163941DFB2A}.Release|x86.ActiveCfg = Release|Win32
{0AA93A45-37CE-40DE-A0E9-7163941DFB2A}.Release|x86.Build.0 = Release|Win32
{3E0F1766-91F4-4218-A970-667F6345AF99}.Debug|Any CPU.ActiveCfg = Debug|Win32
{3E0F1766-91F4-4218-A970-667F6345AF99}.Debug|ARM.ActiveCfg = Debug|Win32
{3E0F1766-91F4-4218-A970-667F6345AF99}.Debug|ARM64.ActiveCfg = Debug|Win32
{3E0F1766-91F4-4218-A970-667F6345AF99}.Debug|x64.ActiveCfg = Debug|x64
{3E0F1766-91F4-4218-A970-667F6345AF99}.Debug|x64.Build.0 = Debug|x64
{3E0F1766-91F4-4218-A970-667F6345AF99}.Debug|x86.ActiveCfg = Debug|Win32
{3E0F1766-91F4-4218-A970-667F6345AF99}.Debug|x86.Build.0 = Debug|Win32
{3E0F1766-91F4-4218-A970-667F6345AF99}.Release|Any CPU.ActiveCfg = Release|Win32
{3E0F1766-91F4-4218-A970-667F6345AF99}.Release|ARM.ActiveCfg = Release|Win32
{3E0F1766-91F4-4218-A970-667F6345AF99}.Release|ARM64.ActiveCfg = Release|Win32
{3E0F1766-91F4-4218-A970-667F6345AF99}.Release|x64.ActiveCfg = Release|x64
{3E0F1766-91F4-4218-A970-667F6345AF99}.Release|x64.Build.0 = Release|x64
{3E0F1766-91F4-4218-A970-667F6345AF99}.Release|x86.ActiveCfg = Release|Win32
{3E0F1766-91F4-4218-A970-667F6345AF99}.Release|x86.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
......
This diff is collapsed.
This diff is collapsed.
#include <stdio.h>
#include "../../hb_com.h"
#include "uvlib/uv_log.h"
#include "uvlib/uv_tcpserver.h"
#include "cJSON/cJSON.h"
#include <curl/curl.h>
typedef struct machine_info_s {
char acct[ADEMCO_PACKET_ACCT_MAX_LEN + 1];
AdemcoId ademcoId;
HbMachineType type;
HbMachineStatus status;
}machine_info_t;
struct {
uv_loop_t* loop;
uv_tcpserver_t* tcpd;
const char* uri;
}context;
size_t on_write(void* buffer, size_t size, size_t nmemb, void* user) {
mybuf_t* buf = user;
mybuf_append(buf, buffer, size * nmemb);
return size * nmemb;
}
int post(const char* json) {
CURLcode res;
CURL* curl = curl_easy_init();
struct curl_slist* headers = NULL;
mybuf_t resp;
long http_status, header_size;
mybuf_init(&resp);
do {
if (!curl) {
res = CURLE_FAILED_INIT;
uvlog_error("curl_easy_init failed");
break;
}
headers = curl_slist_append(headers, "Content-Type: application/json");
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1);
curl_easy_setopt(curl, CURLOPT_HEADER, 1);
curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0);
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0);
curl_easy_setopt(curl, CURLOPT_POST, 1);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &resp);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, on_write);
curl_easy_setopt(curl, CURLOPT_URL, context.uri);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, json);
curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, strlen(json));
curl_easy_setopt(curl, CURLOPT_TIMEOUT, 3);
res = curl_easy_perform(curl);
if (res == CURLE_OK || res == CURLE_GOT_NOTHING) {
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_status);
curl_easy_getinfo(curl, CURLINFO_HEADER_SIZE, &header_size);
}
mybuf_reserve(&resp, resp.size + 1);
resp.buf[resp.size] = '\0';
uvlog_debug("RESP: %d %s\n"
"%s\n",
res, curl_easy_strerror(res),
resp.buf);
} while (0);
if (curl)
curl_easy_cleanup(curl);
if (headers) {
curl_slist_free_all(headers);
headers = NULL;
}
return 0;
}
int relay(const char* acct, AdemcoEvent ademco_event, AdemcoZone zone, AdemcoGG gg) {
cJSON* json = NULL;
char* string = NULL;
int r = 0;
json = cJSON_CreateObject();
fatal_if_null(json);
if (cJSON_AddStringToObject(json, "acct", acct) == 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, "gg", gg) == NULL) goto end;
string = cJSON_Print(json);
if (string == NULL) goto end;
uvlog_debug("OUT:\n%s\n", string);
r = post(string);
end:
if (json)
cJSON_Delete(json);
if (string)
free(string);
return r;
}
void on_tcp_connection(uv_tcpserver_client_context_t* client, int connected) {
if (connected) {
machine_info_t* machine = malloc(sizeof(machine_info_t));
memset(machine->acct, '\0', sizeof(machine->acct));
machine->ademcoId = 0;
machine->type = HMT_INVALID;
machine->status = HMS_INVALID;
client->data = machine;
} else if(client->data) {
if (((machine_info_t*)(client->data))->acct[0] != '\0') {
relay(((machine_info_t*)(client->data))->acct, EVENT_OFFLINE, 0, 0);
}
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) {
AdemcoPacket pkt;
auto res = ademcoPacketParse(buf, len, &pkt, ate);
switch (res) {
case RESULT_OK:
switch (pkt.id) {
case AID_NULL:
case AID_HB:
case AID_ADM_CID:
printf("C:");
ademcoPrint(pkt.raw, pkt.raw_len);
if (((machine_info_t*)(client->data))->acct[0] == '\0') {
strcpy(((machine_info_t*)(client->data))->acct, pkt.acct);
relay(pkt.acct, EVENT_ONLINE, 0, 0);
}
if (pkt.data.ademcoId) {
((machine_info_t*)(client->data))->ademcoId = pkt.data.ademcoId;
}
if (ademcoIsMachineStatusEvent(pkt.data.ademcoEvent)) {
((machine_info_t*)(client->data))->status = hbMachineStatusFromAdemcoEvent(pkt.data.ademcoEvent);
}
if (ademcoIsMachineTypeEvent(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') {
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);
uv_tcpserver_send_to_cli(client, pkt.raw, pkt.raw_len);
printf("S:");
ademcoPrint(pkt.raw, pkt.raw_len);
break;
}
return uv_tcp_parse_ok;
break;
case RESULT_NOT_ENOUGH:
return uv_tcp_parse_not_enough;
break;
case RESULT_ERROR:
return uv_tcp_parse_error;
break;
default:
abort();
break;
}
}
int init_tcpd(const char* addr, int port) {
static uv_tcpserver_settings_t settings = { on_tcp_connection, on_tcp_parse, NULL };
int r = uv_tcpserver_create(&context.tcpd, context.loop, &settings);
fatal_on_uv_err(r, "uv_tcpserver_create");
r = uv_tcpserver_start_listen(context.tcpd, addr, port);
fatal_on_uv_err(r, "uv_tcpserver_start_listen");
printf("tcp server listening on %s:%d\n", addr, port);
return r;
}
int main(int argc, char** argv) {
if (argc != 4) {
fprintf(stderr, "Usage: %s tcp_bind_addr tcp_server_listening_port http_client_relay_to_uri\n"
" Example: %s 0.0.0.0 12345 http://your-http-server.com/ademco:8080\n",
argv[0], argv[0]);
exit(1);
}
uv_log_set_level(uv_log_level_debug);
memset(&context, 0, sizeof(context));
context.uri = argv[3];
context.loop = uv_default_loop();
fatal_if_null(context.loop);
curl_global_init(CURL_GLOBAL_ALL);
if (init_tcpd(argv[1], atoi(argv[2]))) {
abort();
}
uv_run(context.loop, UV_RUN_DEFAULT);
}
<?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>
<Keyword>Win32Proj</Keyword>
<ProjectGuid>{3e0f1766-91f4-4218-a970-667f6345af99}</ProjectGuid>
<RootNamespace>httprelay</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>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</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 Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions);_CRT_SECURE_NO_WARNINGS;strdup=_strdup;UV_LINK_STATIC</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<AdditionalIncludeDirectories>$(DEVLIBS);.\uvlib\llhttp\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);_CRT_SECURE_NO_WARNINGS;strdup=_strdup;UV_LINK_STATIC</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<AdditionalIncludeDirectories>$(DEVLIBS);.\uvlib\llhttp\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions);_CRT_SECURE_NO_WARNINGS;strdup=_strdup;UV_LINK_STATIC</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<AdditionalIncludeDirectories>$(DEVLIBS);.\uvlib\llhttp\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions);_CRT_SECURE_NO_WARNINGS;strdup=_strdup;UV_LINK_STATIC</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<AdditionalIncludeDirectories>$(DEVLIBS);.\uvlib\llhttp\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\..\ademco.c" />
<ClCompile Include="..\..\hb_com.c" />
<ClCompile Include="cJSON\cJSON.c" />
<ClCompile Include="httprelay.c" />
<ClCompile Include="uvlib\llhttp\src\api.c" />
<ClCompile Include="uvlib\llhttp\src\http.c" />
<ClCompile Include="uvlib\llhttp\src\llhttp.c" />
<ClCompile Include="uvlib\mybuf.c" />
<ClCompile Include="uvlib\uv_httpc.c" />
<ClCompile Include="uvlib\uv_httpd.c" />
<ClCompile Include="uvlib\uv_log.c" />
<ClCompile Include="uvlib\uv_tcpclient.c" />
<ClCompile Include="uvlib\uv_tcpserver.c" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\ademco.h" />
<ClInclude Include="..\..\hb_com.h" />
<ClInclude Include="cJSON\cJSON.h" />
<ClInclude Include="uvlib\list.h" />
<ClInclude Include="uvlib\mybuf.h" />
<ClInclude Include="uvlib\uv_http.h" />
<ClInclude Include="uvlib\uv_httpc.h" />
<ClInclude Include="uvlib\uv_httpd.h" />
<ClInclude Include="uvlib\uv_log.h" />
<ClInclude Include="uvlib\uv_tcp.h" />
<ClInclude Include="uvlib\uv_tcpclient.h" />
<ClInclude Include="uvlib\uv_tcpserver.h" />
</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;c++;cppm;ixx;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;h++;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>
<Filter Include="ademco">
<UniqueIdentifier>{e5563916-4ea7-4065-9be4-f34d41d6e97f}</UniqueIdentifier>
</Filter>
<Filter Include="uvlib">
<UniqueIdentifier>{ccce695b-7cff-4961-8c57-f722d12402cb}</UniqueIdentifier>
</Filter>
<Filter Include="uvlib\llhttp">
<UniqueIdentifier>{d87a50b2-ba54-4102-940a-ec65bb393464}</UniqueIdentifier>
</Filter>
<Filter Include="cJSON">
<UniqueIdentifier>{7d7954ed-fb8d-4e25-9f82-2c8780f8b7b8}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\..\ademco.c">
<Filter>ademco</Filter>
</ClCompile>
<ClCompile Include="..\..\hb_com.c">
<Filter>ademco</Filter>
</ClCompile>
<ClCompile Include="httprelay.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="uvlib\llhttp\src\api.c">
<Filter>uvlib\llhttp</Filter>
</ClCompile>
<ClCompile Include="uvlib\llhttp\src\http.c">
<Filter>uvlib\llhttp</Filter>
</ClCompile>
<ClCompile Include="uvlib\llhttp\src\llhttp.c">
<Filter>uvlib\llhttp</Filter>
</ClCompile>
<ClCompile Include="uvlib\mybuf.c">
<Filter>uvlib</Filter>
</ClCompile>
<ClCompile Include="uvlib\uv_httpd.c">
<Filter>uvlib</Filter>
</ClCompile>
<ClCompile Include="uvlib\uv_log.c">
<Filter>uvlib</Filter>
</ClCompile>
<ClCompile Include="uvlib\uv_tcpserver.c">
<Filter>uvlib</Filter>
</ClCompile>
<ClCompile Include="uvlib\uv_httpc.c">
<Filter>uvlib</Filter>
</ClCompile>
<ClCompile Include="uvlib\uv_tcpclient.c">
<Filter>uvlib</Filter>
</ClCompile>
<ClCompile Include="cJSON\cJSON.c">
<Filter>cJSON</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\ademco.h">
<Filter>ademco</Filter>
</ClInclude>
<ClInclude Include="..\..\hb_com.h">
<Filter>ademco</Filter>
</ClInclude>
<ClInclude Include="uvlib\list.h">
<Filter>uvlib</Filter>
</ClInclude>
<ClInclude Include="uvlib\mybuf.h">
<Filter>uvlib</Filter>
</ClInclude>
<ClInclude Include="uvlib\uv_http.h">
<Filter>uvlib</Filter>
</ClInclude>
<ClInclude Include="uvlib\uv_httpd.h">
<Filter>uvlib</Filter>
</ClInclude>
<ClInclude Include="uvlib\uv_log.h">
<Filter>uvlib</Filter>
</ClInclude>
<ClInclude Include="uvlib\uv_tcp.h">
<Filter>uvlib</Filter>
</ClInclude>
<ClInclude Include="uvlib\uv_tcpserver.h">
<Filter>uvlib</Filter>
</ClInclude>
<ClInclude Include="uvlib\uv_httpc.h">
<Filter>uvlib</Filter>
</ClInclude>
<ClInclude Include="uvlib\uv_tcpclient.h">
<Filter>uvlib</Filter>
</ClInclude>
<ClInclude Include="cJSON\cJSON.h">
<Filter>cJSON</Filter>
</ClInclude>
</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>0.0.0.0 12345 http://127.0.0.1:3000/ademco</LocalDebuggerCommandArguments>
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
</PropertyGroup>
</Project>
\ No newline at end of file
#ifndef __LIST_H__
#define __LIST_H__
#pragma once
#define list_append(type, l, node) \
do { \
type* tail_ = (l); \
while (tail_ && tail_->next) \
tail_ = tail_->next; \
if (tail_) \
tail_->next = (node); \
else \
(l) = node; \
} while (0);
#endif
cmake_minimum_required(VERSION 3.5.1)
cmake_policy(SET CMP0069 NEW)
project(llhttp VERSION 8.1.0)
include(GNUInstallDirs)
set(CMAKE_C_STANDARD 99)
# By default build in relwithdebinfo type, supports both lowercase and uppercase
if(NOT CMAKE_CONFIGURATION_TYPES)
set(allowableBuildTypes DEBUG RELEASE RELWITHDEBINFO MINSIZEREL)
set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "${allowableBuildTypes}")
if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE RELWITHDEBINFO CACHE STRING "" FORCE)
else()
string(TOUPPER ${CMAKE_BUILD_TYPE} CMAKE_BUILD_TYPE)
if(NOT CMAKE_BUILD_TYPE IN_LIST allowableBuildTypes)
message(FATAL_ERROR "Invalid build type: ${CMAKE_BUILD_TYPE}")
endif()
endif()
endif()
#
# Options
#
# Generic option
option(BUILD_SHARED_LIBS "Build shared libraries (.dll/.so)" ON)
option(BUILD_STATIC_LIBS "Build static libraries (.lib/.a)" OFF)
# Source code
set(LLHTTP_SOURCES
${CMAKE_CURRENT_SOURCE_DIR}/src/llhttp.c
${CMAKE_CURRENT_SOURCE_DIR}/src/http.c
${CMAKE_CURRENT_SOURCE_DIR}/src/api.c
)
set(LLHTTP_HEADERS
${CMAKE_CURRENT_SOURCE_DIR}/include/llhttp.h
)
configure_file(
${CMAKE_CURRENT_SOURCE_DIR}/libllhttp.pc.in
${CMAKE_CURRENT_SOURCE_DIR}/libllhttp.pc
@ONLY
)
function(config_library target)
target_sources(${target} PRIVATE ${LLHTTP_SOURCES} ${LLHTTP_HEADERS})
target_include_directories(${target} PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/include
)
set_target_properties(${target} PROPERTIES
OUTPUT_NAME llhttp
VERSION ${PROJECT_VERSION}
SOVERSION ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}
PUBLIC_HEADER ${LLHTTP_HEADERS}
)
install(TARGETS ${target}
EXPORT llhttp
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
)
install(FILES
${CMAKE_CURRENT_SOURCE_DIR}/libllhttp.pc
DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig
)
# This is required to work with FetchContent
install(EXPORT llhttp
FILE llhttp-config.cmake
NAMESPACE llhttp::
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/llhttp)
endfunction(config_library target)
if(BUILD_SHARED_LIBS)
add_library(llhttp_shared SHARED
${llhttp_src}
)
add_library(llhttp::llhttp ALIAS llhttp_shared)
config_library(llhttp_shared)
endif()
if(BUILD_STATIC_LIBS)
add_library(llhttp_static STATIC
${llhttp_src}
)
if(BUILD_SHARED_LIBS)
add_library(llhttp::llhttp ALIAS llhttp_shared)
else()
add_library(llhttp::llhttp ALIAS llhttp_static)
endif()
config_library(llhttp_static)
endif()
# On windows with Visual Studio, add a debug postfix so that release
# and debug libraries can coexist.
if(MSVC)
set(CMAKE_DEBUG_POSTFIX "d")
endif()
# Print project configure summary
message(STATUS "")
message(STATUS "")
message(STATUS "Project configure summary:")
message(STATUS "")
message(STATUS " CMake build type .................: ${CMAKE_BUILD_TYPE}")
message(STATUS " Install prefix ...................: ${CMAKE_INSTALL_PREFIX}")
message(STATUS " Build shared library .............: ${BUILD_SHARED_LIBS}")
message(STATUS " Build static library .............: ${BUILD_STATIC_LIBS}")
message(STATUS "")
This software is licensed under the MIT License.
Copyright Fedor Indutny, 2018.
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to permit
persons to whom the Software is furnished to do so, subject to the
following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
USE OR OTHER DEALINGS IN THE SOFTWARE.
This diff is collapsed.
{
'target_defaults': {
'default_configuration': 'Debug',
'configurations': {
# TODO: hoist these out and put them somewhere common, because
# RuntimeLibrary MUST MATCH across the entire project
'Debug': {
'defines': [ 'DEBUG', '_DEBUG' ],
'cflags': [ '-Wall', '-Wextra', '-O0', '-g', '-ftrapv' ],
'msvs_settings': {
'VCCLCompilerTool': {
'RuntimeLibrary': 1, # static debug
},
},
},
'Release': {
'defines': [ 'NDEBUG' ],
'cflags': [ '-Wall', '-Wextra', '-O3' ],
'msvs_settings': {
'VCCLCompilerTool': {
'RuntimeLibrary': 0, # static release
},
},
}
},
'msvs_settings': {
'VCCLCompilerTool': {
# Compile as C++. llhttp.c is actually C99, but C++ is
# close enough in this case.
'CompileAs': 2,
},
'VCLibrarianTool': {
},
'VCLinkerTool': {
'GenerateDebugInformation': 'true',
},
},
'conditions': [
['OS == "win"', {
'defines': [
'WIN32'
],
}]
],
},
}
This diff is collapsed.
prefix=@CMAKE_INSTALL_PREFIX@
exec_prefix=@CMAKE_INSTALL_PREFIX@
libdir=@CMAKE_INSTALL_PREFIX@/@CMAKE_INSTALL_LIBDIR@
includedir=@CMAKE_INSTALL_PREFIX@/@CMAKE_INSTALL_INCLUDEDIR@
Name: libllhttp
Description: Node.js llhttp Library
Version: @PROJECT_VERSION@
Libs: -L${libdir} -lllhttp
Cflags: -I${includedir}
\ No newline at end of file
{
'targets': [
{
'target_name': 'llhttp',
'type': 'static_library',
'include_dirs': [ '.', 'include' ],
'direct_dependent_settings': {
'include_dirs': [ 'include' ],
},
'sources': [ 'src/llhttp.c', 'src/api.c', 'src/http.c' ],
},
]
}
This diff is collapsed.
#include <stdio.h>
#ifndef LLHTTP__TEST
# include "llhttp.h"
#else
# define llhttp_t llparse_t
#endif /* */
int llhttp_message_needs_eof(const llhttp_t* parser);
int llhttp_should_keep_alive(const llhttp_t* parser);
int llhttp__before_headers_complete(llhttp_t* parser, const char* p,
const char* endp) {
/* Set this here so that on_headers_complete() callbacks can see it */
if ((parser->flags & F_UPGRADE) &&
(parser->flags & F_CONNECTION_UPGRADE)) {
/* For responses, "Upgrade: foo" and "Connection: upgrade" are
* mandatory only when it is a 101 Switching Protocols response,
* otherwise it is purely informational, to announce support.
*/
parser->upgrade =
(parser->type == HTTP_REQUEST || parser->status_code == 101);
} else {
parser->upgrade = (parser->method == HTTP_CONNECT);
}
return 0;
}
/* Return values:
* 0 - No body, `restart`, message_complete
* 1 - CONNECT request, `restart`, message_complete, and pause
* 2 - chunk_size_start
* 3 - body_identity
* 4 - body_identity_eof
* 5 - invalid transfer-encoding for request
*/
int llhttp__after_headers_complete(llhttp_t* parser, const char* p,
const char* endp) {
int hasBody;
hasBody = parser->flags & F_CHUNKED || parser->content_length > 0;
if (parser->upgrade && (parser->method == HTTP_CONNECT ||
(parser->flags & F_SKIPBODY) || !hasBody)) {
/* Exit, the rest of the message is in a different protocol. */
return 1;
}
if (parser->flags & F_SKIPBODY) {
return 0;
} else if (parser->flags & F_CHUNKED) {
/* chunked encoding - ignore Content-Length header, prepare for a chunk */
return 2;
} else if (parser->flags & F_TRANSFER_ENCODING) {
if (parser->type == HTTP_REQUEST &&
(parser->lenient_flags & LENIENT_CHUNKED_LENGTH) == 0 &&
(parser->lenient_flags & LENIENT_TRANSFER_ENCODING) == 0) {
/* RFC 7230 3.3.3 */
/* If a Transfer-Encoding header field
* is present in a request and the chunked transfer coding is not
* the final encoding, the message body length cannot be determined
* reliably; the server MUST respond with the 400 (Bad Request)
* status code and then close the connection.
*/
return 5;
} else {
/* RFC 7230 3.3.3 */
/* If a Transfer-Encoding header field is present in a response and
* the chunked transfer coding is not the final encoding, the
* message body length is determined by reading the connection until
* it is closed by the server.
*/
return 4;
}
} else {
if (!(parser->flags & F_CONTENT_LENGTH)) {
if (!llhttp_message_needs_eof(parser)) {
/* Assume content-length 0 - read the next */
return 0;
} else {
/* Read body until EOF */
return 4;
}
} else if (parser->content_length == 0) {
/* Content-Length header given but zero: Content-Length: 0\r\n */
return 0;
} else {
/* Content-Length header given and non-zero */
return 3;
}
}
}
int llhttp__after_message_complete(llhttp_t* parser, const char* p,
const char* endp) {
int should_keep_alive;
should_keep_alive = llhttp_should_keep_alive(parser);
parser->finish = HTTP_FINISH_SAFE;
parser->flags = 0;
/* NOTE: this is ignored in loose parsing mode */
return should_keep_alive;
}
int llhttp_message_needs_eof(const llhttp_t* parser) {
if (parser->type == HTTP_REQUEST) {
return 0;
}
/* See RFC 2616 section 4.4 */
if (parser->status_code / 100 == 1 || /* 1xx e.g. Continue */
parser->status_code == 204 || /* No Content */
parser->status_code == 304 || /* Not Modified */
(parser->flags & F_SKIPBODY)) { /* response to a HEAD request */
return 0;
}
/* RFC 7230 3.3.3, see `llhttp__after_headers_complete` */
if ((parser->flags & F_TRANSFER_ENCODING) &&
(parser->flags & F_CHUNKED) == 0) {
return 1;
}
if (parser->flags & (F_CHUNKED | F_CONTENT_LENGTH)) {
return 0;
}
return 1;
}
int llhttp_should_keep_alive(const llhttp_t* parser) {
if (parser->http_major > 0 && parser->http_minor > 0) {
/* HTTP/1.1 */
if (parser->flags & F_CONNECTION_CLOSE) {
return 0;
}
} else {
/* HTTP/1.0 or earlier */
if (!(parser->flags & F_CONNECTION_KEEP_ALIVE)) {
return 0;
}
}
return !llhttp_message_needs_eof(parser);
}
This diff is collapsed.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include "mybuf.h"
#include "uv_log.h"
void mybuf_init(mybuf_t* buf) {
buf->buf = buf->mybuf;
buf->size = 0;
buf->capacity = MYBUF_DEFAULT_SIZE;
}
size_t mybuf_space(mybuf_t* buf) {
return buf->capacity - buf->size;
}
void mybuf_reserve(mybuf_t* buf, size_t size) {
if (mybuf_space(buf) < size) {
//fprintf(stderr, "WARN: mybuf_t not enough, space=%zu, needed=%zu\n", mybuf_space(buf), size);
while (mybuf_space(buf) < size) {
buf->capacity *= 2;
}
if (buf->buf == buf->mybuf) {
buf->buf = (char*)malloc(buf->capacity);
fatal_if_null(buf->buf);
memcpy(buf->buf, buf->mybuf, buf->size);
} else {
char* tmp = (char*)realloc(buf->buf, buf->capacity);
fatal_if_null(tmp);
buf->buf = tmp;
}
}
}
void mybuf_append(mybuf_t* buf, const char* data, size_t len) {
if (mybuf_space(buf) >= len) {
memcpy(buf->buf + buf->size, data, len);
buf->size += len;
} else {
//fprintf(stderr, "WARN: mybuf_t not enough, space=%zu, needed=%zu\n", mybuf_space(buf), len);
while (mybuf_space(buf) < len) {
buf->capacity *= 2;
}
if (buf->buf == buf->mybuf) {
buf->buf = (char*)malloc(buf->capacity);
fatal_if_null(buf->buf);
memcpy(buf->buf, buf->mybuf, buf->size);
} else {
char* tmp = (char*)realloc(buf->buf, buf->capacity);
fatal_if_null(tmp);
buf->buf = tmp;
}
memcpy(buf->buf + buf->size, data, len);
buf->size += len;
}
}
static void mybuf_cat_vprintf(mybuf_t* buf, const char* fmt, va_list ap) {
va_list cpy;
int l;
while (1) {
va_copy(cpy, ap);
l = vsnprintf(buf->buf + buf->size, mybuf_space(buf), fmt, cpy);
va_end(cpy);
if (l < 0) {
uvlog_error("mybuf_cat_vprintf error:%d", l);
return;
} else if ((size_t)l >= mybuf_space(buf)) {
mybuf_reserve(buf, (size_t)l + 1);
continue;
} else {
break;
}
}
buf->size += (size_t)l;
}
void mybuf_cat_printf(mybuf_t* buf, const char* fmt, ...) {
va_list ap;
va_start(ap, fmt);
mybuf_cat_vprintf(buf, fmt, ap);
va_end(ap);
}
void mybuf_clear(mybuf_t* buf) {
if (buf->buf != buf->mybuf) {
free(buf->buf);
buf->buf = buf->mybuf;
}
buf->size = 0;
buf->capacity = MYBUF_DEFAULT_SIZE;
}
#ifndef __MYBUF_H__
#define __MYBUF_H__
#pragma once
#include <stddef.h> // size_t
#ifdef __cplusplus
extern "C" {
#endif
#ifndef MYBUF_DEFAULT_SIZE
#define MYBUF_DEFAULT_SIZE 4096
#endif
typedef struct {
char* buf;
char mybuf[MYBUF_DEFAULT_SIZE];
size_t size, capacity;
}mybuf_t;
void mybuf_init(mybuf_t* buf);
size_t mybuf_space(mybuf_t* buf);
void mybuf_reserve(mybuf_t* buf, size_t size);
void mybuf_append(mybuf_t* buf, const char* data, size_t len);
#ifdef __GNUC__
void mybuf_cat_printf(mybuf_t* buf, const char* fmt, ...)
__attribute__((format(printf, 2, 3)));
#else
void mybuf_cat_printf(mybuf_t* buf, const char* fmt, ...);
#endif
void mybuf_clear(mybuf_t* buf);
#ifdef __cplusplus
}
#endif
#endif
#ifndef __UV_HTTP_H__
#define __UV_HTTP_H__
#pragma once
#endif // !__UV_HTTP_H__
This diff is collapsed.
// uv http client
#ifndef __UV_HTTPC_H__
#define __UV_HTTPC_H__
#pragma once
#include <uv.h>
#include "mybuf.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef struct uv_httpc_s uv_httpc_t;
typedef struct uv_httpc_headers_s {
char* data;
struct uv_httpc_headers_s* next;
}uv_httpc_headers_t;
typedef enum {
uv_httpc_ok,
uv_httpc_resolve_failed,
uv_httpc_connection_failed,
uv_httpc_connection_reset,
uv_httpc_connection_timeout,
uv_httpc_parse_failed,
}uv_httpc_code;
typedef struct uv_httpc_response_s {
uv_httpc_code code;
int uvcode;
uv_httpc_headers_t* headers;
int http_status;
char* body;
size_t len;
}uv_httpc_response_t;
typedef void(*uv_httpc_on_response_t)(uv_httpc_t* httpc, uv_httpc_response_t* res);
int uv_httpc_create(uv_httpc_t** httpc, uv_loop_t* loop, const char* host, const char* port,
uv_httpc_on_response_t on_response);
int uv_httpc_post(uv_httpc_t* httpc, const char* url, uv_httpc_headers_t* headers,
const char* data, size_t len, int timeout);
int uv_httpc_stop(uv_httpc_t* httpc);
void uv_httpc_free(uv_httpc_t* httpc);
uv_httpc_headers_t* uv_httpc_headers_append(uv_httpc_headers_t* headers, char* data);
uv_httpc_headers_t* uv_httpc_headers_append_nodup(uv_httpc_headers_t* headers, char* data);
uv_httpc_headers_t* uv_httpc_headers_dup(uv_httpc_headers_t* headers);
void uv_httpc_headers_free_all(uv_httpc_headers_t* headers, int freedata);
#ifdef WEUV_TEST
int uv_httpc_test_main(int argc, char** argv);
#endif
#ifdef __cplusplus
}
#endif
#endif
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
#ifndef __UV_TCP_H__
#define __UV_TCP_H__
#pragma once
#include <uv.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef enum {
uv_tcp_parse_ok = 0,
uv_tcp_parse_not_enough,
uv_tcp_parse_error,
}uv_tcp_parse_result_t;
#ifdef __cplusplus
}
#endif
#endif
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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