MINIFICPP-1092 - Make CoAP compile and work on Windows
Signed-off-by: Arpad Boda <aboda@apache.org>
This closes #687
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 87fe4f3..284a876 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -318,7 +318,7 @@
option(ENABLE_COAP "Enables the CoAP extension." OFF)
if (ENABLE_ALL OR ENABLE_COAP STREQUAL "ON")
- include(BundledLibCOAP)
+ include(BundledLibCoAP)
use_bundled_libcoap(${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR})
createExtension(COAP-EXTENSION "COAP EXTENSIONS" "Enables LibCOAP Functionality." "extensions/coap" "extensions/coap/tests/")
if( NOT DISABLE_CURL)
diff --git a/cmake/BundledLibCOAP.cmake b/cmake/BundledLibCOAP.cmake
deleted file mode 100644
index 7d52d5a..0000000
--- a/cmake/BundledLibCOAP.cmake
+++ /dev/null
@@ -1,62 +0,0 @@
-#
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-#
-
-function(use_bundled_libcoap SOURCE_DIR BINARY_DIR)
- message("Using bundled libcoap")
-
- # Define byproducts
- if (WIN32)
- set(BYPRODUCT "lib/libcoap-2.lib")
- else()
- set(BYPRODUCT "lib/libcoap-2.a")
- endif()
-
- # Build project
- ExternalProject_Add(
- coap-external
- GIT_REPOSITORY "https://github.com/obgm/libcoap.git"
- GIT_TAG "v4.2.0-rc2"
- BUILD_IN_SOURCE true
- SOURCE_DIR "${BINARY_DIR}/thirdparty/libcoap-src"
- BUILD_COMMAND make
- CMAKE_COMMAND ""
- UPDATE_COMMAND ""
- INSTALL_COMMAND make install
- BUILD_BYPRODUCTS "${BINARY_DIR}/thirdparty/libcoap-install/${BYPRODUCT}"
- CONFIGURE_COMMAND ""
- PATCH_COMMAND ./autogen.sh && ./configure --disable-examples --disable-dtls --disable-tests --disable-documentation --prefix=${BINARY_DIR}/thirdparty/libcoap-install
- STEP_TARGETS build
- EXCLUDE_FROM_ALL TRUE
- )
-
- # Set variables
- set(COAP_FOUND "YES" CACHE STRING "" FORCE)
- set(COAP_INCLUDE_DIRS "${BINARY_DIR}/thirdparty/libcoap-install/include" CACHE STRING "" FORCE)
- set(COAP_LIBRARY "${BINARY_DIR}/thirdparty/libcoap-install/${BYPRODUCT}" CACHE STRING "" FORCE)
- set(COAP_LIBRARIES "${COAP_LIBRARY}" CACHE STRING "" FORCE)
-
- # Create imported targets
- file(MAKE_DIRECTORY ${COAP_INCLUDE_DIRS})
-
- add_library(COAP::libcoap STATIC IMPORTED)
- set_target_properties(COAP::libcoap PROPERTIES IMPORTED_LOCATION "${COAP_LIBRARY}")
- add_dependencies(COAP::libcoap coap-external)
- set_property(TARGET COAP::libcoap APPEND PROPERTY INTERFACE_INCLUDE_DIRECTORIES "${COAP_INCLUDE_DIRS}")
- set_property(TARGET COAP::libcoap APPEND PROPERTY INTERFACE_COMPILE_DEFINITIONS "WITH_POSIX=1")
-endfunction(use_bundled_libcoap)
diff --git a/cmake/BundledLibCoAP.cmake b/cmake/BundledLibCoAP.cmake
new file mode 100644
index 0000000..1f09362
--- /dev/null
+++ b/cmake/BundledLibCoAP.cmake
@@ -0,0 +1,84 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+function(use_bundled_libcoap SOURCE_DIR BINARY_DIR)
+ message("Using bundled libcoap")
+
+ # Define patch step
+ if (WIN32)
+ set(PC "${Patch_EXECUTABLE}" -p1 -i "${SOURCE_DIR}/thirdparty/libcoap/libcoap-windows-cmake.patch")
+ endif()
+
+ # Define byproducts
+ if (WIN32)
+ set(BYPRODUCT "lib/coap.lib")
+ else()
+ set(BYPRODUCT "lib/libcoap-2.a")
+ endif()
+
+ # Build project
+ set(LIBCOAP_URL https://github.com/obgm/libcoap/archive/v4.2.1.tar.gz)
+ set(LIBCOAP_URL_HASH "SHA256=29a0394a265d3febee41e5e2dc03d34292a0aede37f5f80334e529ac0dab2321")
+
+ if (WIN32)
+ set(LIBCOAP_CMAKE_ARGS ${PASSTHROUGH_CMAKE_ARGS}
+ "-DCMAKE_INSTALL_PREFIX=${BINARY_DIR}/thirdparty/libcoap-install")
+
+ ExternalProject_Add(
+ coap-external
+ URL ${LIBCOAP_URL}
+ URL_HASH ${LIBCOAP_URL_HASH}
+ CMAKE_ARGS ${LIBCOAP_CMAKE_ARGS}
+ PATCH_COMMAND ${PC}
+ BUILD_BYPRODUCTS "${BINARY_DIR}/thirdparty/libcoap-install/${BYPRODUCT}"
+ EXCLUDE_FROM_ALL TRUE
+ )
+ else()
+ ExternalProject_Add(
+ coap-external
+ URL ${LIBCOAP_URL}
+ URL_HASH ${LIBCOAP_URL_HASH}
+ BUILD_IN_SOURCE true
+ SOURCE_DIR "${BINARY_DIR}/thirdparty/libcoap-src"
+ BUILD_COMMAND make
+ CMAKE_COMMAND ""
+ UPDATE_COMMAND ""
+ INSTALL_COMMAND make install
+ BUILD_BYPRODUCTS "${BINARY_DIR}/thirdparty/libcoap-install/${BYPRODUCT}"
+ CONFIGURE_COMMAND ""
+ PATCH_COMMAND ./autogen.sh && ./configure --disable-examples --disable-dtls --disable-tests --disable-documentation --prefix=${BINARY_DIR}/thirdparty/libcoap-install
+ STEP_TARGETS build
+ EXCLUDE_FROM_ALL TRUE
+ )
+ endif()
+
+ # Set variables
+ set(COAP_FOUND "YES" CACHE STRING "" FORCE)
+ set(COAP_INCLUDE_DIRS "${BINARY_DIR}/thirdparty/libcoap-install/include" CACHE STRING "" FORCE)
+ set(COAP_LIBRARY "${BINARY_DIR}/thirdparty/libcoap-install/${BYPRODUCT}" CACHE STRING "" FORCE)
+ set(COAP_LIBRARIES "${COAP_LIBRARY}" CACHE STRING "" FORCE)
+
+ # Create imported targets
+ file(MAKE_DIRECTORY ${COAP_INCLUDE_DIRS})
+
+ add_library(COAP::libcoap STATIC IMPORTED)
+ set_target_properties(COAP::libcoap PROPERTIES IMPORTED_LOCATION "${COAP_LIBRARY}")
+ add_dependencies(COAP::libcoap coap-external)
+ set_property(TARGET COAP::libcoap APPEND PROPERTY INTERFACE_INCLUDE_DIRECTORIES "${COAP_INCLUDE_DIRS}")
+endfunction(use_bundled_libcoap)
diff --git a/extensions/coap/COAPLoader.cpp b/extensions/coap/COAPLoader.cpp
index ea49cd6..6ed03c8 100644
--- a/extensions/coap/COAPLoader.cpp
+++ b/extensions/coap/COAPLoader.cpp
@@ -16,9 +16,36 @@
* limitations under the License.
*/
#include "core/FlowConfiguration.h"
+#include "core/logging/LoggerConfiguration.h"
#include "COAPLoader.h"
+#ifdef WIN32
+#include <winsock2.h>
+#endif
+
bool COAPObjectFactory::added = core::FlowConfiguration::add_static_func("createCOAPFactory");
+
+bool COAPObjectFactoryInitializer::initialize() {
+#ifdef WIN32
+ static WSADATA s_wsaData;
+ int iWinSockInitResult = WSAStartup(MAKEWORD(2, 2), &s_wsaData);
+ if (iWinSockInitResult != 0) {
+ logging::LoggerFactory<COAPObjectFactoryInitializer>::getLogger()->log_error("WSAStartup failed with error %d", iWinSockInitResult);
+ return false;
+ } else {
+ return true;
+ }
+#else
+ return true;
+#endif
+}
+
+void COAPObjectFactoryInitializer::deinitialize() {
+#ifdef WIN32
+ WSACleanup();
+#endif
+}
+
extern "C" {
diff --git a/extensions/coap/COAPLoader.h b/extensions/coap/COAPLoader.h
index ce6383f..e948782 100644
--- a/extensions/coap/COAPLoader.h
+++ b/extensions/coap/COAPLoader.h
@@ -28,6 +28,13 @@
#include "utils/StringUtils.h"
#include "protocols/CoapC2Protocol.h"
+class COAPObjectFactoryInitializer : public core::ObjectFactoryInitializer {
+ public:
+ bool initialize() override;
+
+ void deinitialize() override;
+};
+
/**
* Object factory class loader for this extension.
* Can add extensions to the default class loader through REGISTER_RESOURCE,
@@ -43,25 +50,25 @@
* Gets the name of the object.
* @return class name of processor
*/
- virtual std::string getName() override{
+ std::string getName() override {
return "COAPObjectFactory";
}
- virtual std::string getClassName() override{
+ std::string getClassName() override {
return "COAPObjectFactory";
}
/**
* Gets the class name for the object
* @return class name for the processor.
*/
- virtual std::vector<std::string> getClassNames() override{
+ std::vector<std::string> getClassNames() override {
std::vector<std::string> class_names;
class_names.push_back("CoapProtocol");
class_names.push_back("CoapConnectorService");
return class_names;
}
- virtual std::unique_ptr<ObjectFactory> assign(const std::string &class_name) override{
+ std::unique_ptr<ObjectFactory> assign(const std::string &class_name) override {
if (utils::StringUtils::equalsIgnoreCase(class_name, "CoapProtocol")) {
return std::unique_ptr<ObjectFactory>(new core::DefautObjectFactory<minifi::coap::c2::CoapProtocol>());
} else if (utils::StringUtils::equalsIgnoreCase(class_name, "CoapConnectorService")) {
@@ -71,6 +78,10 @@
}
}
+ std::unique_ptr<core::ObjectFactoryInitializer> getInitializer() override {
+ return std::unique_ptr<core::ObjectFactoryInitializer>(new COAPObjectFactoryInitializer());
+ }
+
static bool added;
};
diff --git a/extensions/coap/nanofi/coap_connection.c b/extensions/coap/nanofi/coap_connection.c
index eaa6c36..20137e0 100644
--- a/extensions/coap/nanofi/coap_connection.c
+++ b/extensions/coap/nanofi/coap_connection.c
@@ -17,6 +17,12 @@
*/
#include "coap_connection.h"
+#ifdef WIN32
+#include <winsock2.h>
+#else
+#include <netdb.h>
+#endif
+
CoapPDU *create_connection(uint8_t type, const char * const server, const char * const endpoint, int port, const CoapMessage * const message) {
CoapPDU *pdu = (CoapPDU*) malloc(sizeof(CoapPDU));
diff --git a/extensions/coap/nanofi/coap_connection.h b/extensions/coap/nanofi/coap_connection.h
index 6a762d2..514366e 100644
--- a/extensions/coap/nanofi/coap_connection.h
+++ b/extensions/coap/nanofi/coap_connection.h
@@ -22,7 +22,6 @@
#endif
#include <coap2/coap.h>
-#include <netdb.h>
#include "coap_message.h"
#include "coap_functions.h"
diff --git a/extensions/coap/nanofi/coap_functions.h b/extensions/coap/nanofi/coap_functions.h
index 5061ac5..faa63d2 100644
--- a/extensions/coap/nanofi/coap_functions.h
+++ b/extensions/coap/nanofi/coap_functions.h
@@ -28,12 +28,18 @@
#include "coap2/coap.h"
#include "coap2/uri.h"
#include "coap2/address.h"
+
#include <stdio.h>
+#include <string.h>
+#ifdef WIN32
+#include <winsock2.h>
+#else
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
-#include <string.h>
#include <netdb.h>
+#endif
+
#include "coap_message.h"
diff --git a/extensions/coap/protocols/CoapC2Protocol.h b/extensions/coap/protocols/CoapC2Protocol.h
index ff63f86..a2a702c 100644
--- a/extensions/coap/protocols/CoapC2Protocol.h
+++ b/extensions/coap/protocols/CoapC2Protocol.h
@@ -35,9 +35,6 @@
#include "coap2/uri.h"
#include "coap2/address.h"
#include <stdio.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
#include <string.h>
#include "protocols/RESTSender.h"
diff --git a/extensions/coap/server/CoapServer.h b/extensions/coap/server/CoapServer.h
index 3717eff..e949a2f 100644
--- a/extensions/coap/server/CoapServer.h
+++ b/extensions/coap/server/CoapServer.h
@@ -18,6 +18,7 @@
#ifndef EXTENSIONS_COAP_SERVER_COAPSERVER_H_
#define EXTENSIONS_COAP_SERVER_COAPSERVER_H_
+
#include "core/Connectable.h"
#include "coap_server.h"
#include "coap_message.h"
@@ -25,17 +26,18 @@
#include <functional>
#include <thread>
#include <future>
+
namespace org {
namespace apache {
namespace nifi {
namespace minifi {
namespace coap {
-enum METHOD {
- GET,
- POST,
- PUT,
- DELETE
+enum class Method {
+ Get,
+ Post,
+ Put,
+ Delete
};
/**
@@ -133,19 +135,19 @@
});
}
- void add_endpoint(const std::string &path, METHOD method, std::function<CoapResponse(CoapQuery)> functor) {
+ void add_endpoint(const std::string &path, Method method, std::function<CoapResponse(CoapQuery)> functor) {
unsigned char mthd = COAP_REQUEST_POST;
switch (method) {
- case GET:
+ case Method::Get:
mthd = COAP_REQUEST_GET;
break;
- case POST:
+ case Method::Post:
mthd = COAP_REQUEST_POST;
break;
- case PUT:
+ case Method::Put:
mthd = COAP_REQUEST_PUT;
break;
- case DELETE:
+ case Method::Delete:
mthd = COAP_REQUEST_DELETE;
break;
}
@@ -159,19 +161,19 @@
}
}
- void add_endpoint(METHOD method, std::function<CoapResponse(CoapQuery)> functor) {
+ void add_endpoint(Method method, std::function<CoapResponse(CoapQuery)> functor) {
unsigned char mthd = COAP_REQUEST_POST;
switch (method) {
- case GET:
+ case Method::Get:
mthd = COAP_REQUEST_GET;
break;
- case POST:
+ case Method::Post:
mthd = COAP_REQUEST_POST;
break;
- case PUT:
+ case Method::Put:
mthd = COAP_REQUEST_PUT;
break;
- case DELETE:
+ case Method::Delete:
mthd = COAP_REQUEST_DELETE;
break;
}
diff --git a/extensions/coap/tests/CMakeLists.txt b/extensions/coap/tests/CMakeLists.txt
index 89ba7af..9e7e13b 100644
--- a/extensions/coap/tests/CMakeLists.txt
+++ b/extensions/coap/tests/CMakeLists.txt
@@ -40,7 +40,7 @@
target_include_directories(${testfilename} BEFORE PRIVATE "../../http-curl/sitetosite/")
target_include_directories(${testfilename} BEFORE PRIVATE "${CMAKE_SOURCE_DIR}/extensions/civetweb/")
target_include_directories(${testfilename} BEFORE PRIVATE ./include)
- createTests("${testfilename}")
+ createTests("${testfilename}")
target_wholearchive_library(${testfilename} minifi-coap)
target_wholearchive_library(${testfilename} minifi-civet-extensions)
target_wholearchive_library(${testfilename} minifi-http-curl)
diff --git a/extensions/coap/tests/CoapC2VerifyHeartbeat.cpp b/extensions/coap/tests/CoapC2VerifyHeartbeat.cpp
index 81a2587..a0e9cd3 100644
--- a/extensions/coap/tests/CoapC2VerifyHeartbeat.cpp
+++ b/extensions/coap/tests/CoapC2VerifyHeartbeat.cpp
@@ -128,7 +128,7 @@
server = std::unique_ptr<minifi::coap::CoapServer>(new minifi::coap::CoapServer("127.0.0.1", newport));
- server->add_endpoint(minifi::coap::METHOD::POST, [](minifi::coap::CoapQuery)->minifi::coap::CoapResponse {
+ server->add_endpoint(minifi::coap::Method::Post, [](minifi::coap::CoapQuery)->minifi::coap::CoapResponse {
minifi::coap::CoapResponse response(205,0x00,0);
return response;
@@ -165,7 +165,7 @@
responses.enqueue(std::move(response));
}
- server->add_endpoint("heartbeat", minifi::coap::METHOD::POST, [&](minifi::coap::CoapQuery)-> minifi::coap::CoapResponse {
+ server->add_endpoint("heartbeat", minifi::coap::Method::Post, [&](minifi::coap::CoapQuery)-> minifi::coap::CoapResponse {
if (responses.size_approx() > 0) {
minifi::coap::CoapResponse resp(500,0,0);;
responses.try_dequeue(resp);
diff --git a/thirdparty/libcoap/libcoap-windows-cmake.patch b/thirdparty/libcoap/libcoap-windows-cmake.patch
new file mode 100644
index 0000000..9150cd0
--- /dev/null
+++ b/thirdparty/libcoap/libcoap-windows-cmake.patch
@@ -0,0 +1,93 @@
+diff -rupN orig/CMakeLists.txt patched/CMakeLists.txt
+--- orig/CMakeLists.txt 1970-01-01 01:00:00.000000000 +0100
++++ patched/CMakeLists.txt 2019-11-21 17:42:30.000000000 +0100
+@@ -0,0 +1,77 @@
++cmake_minimum_required(VERSION 3.10)
++
++project(libcoap)
++
++set(SOURCES src/address.c
++ src/async.c
++ src/block.c
++ src/coap_debug.c
++ src/coap_event.c
++ src/coap_hashkey.c
++ src/coap_gnutls.c
++ src/coap_io.c
++ src/coap_notls.c
++ src/coap_openssl.c
++ src/coap_session.c
++ src/coap_time.c
++ src/coap_tinydtls.c
++ src/encode.c
++ src/mem.c
++ src/net.c
++ src/option.c
++ src/pdu.c
++ src/resource.c
++ src/str.c
++ src/subscribe.c
++ src/uri.c)
++if(WIN32)
++ configure_file(include/coap2/coap.h.windows include/coap2/coap.h COPYONLY)
++ configure_file(coap_config.h.windows coap_config.h COPYONLY)
++elseif(APPLE)
++ configure_file(include/coap2/coap.h.macos include/coap2/coap.h COPYONLY)
++ configure_file(coap_config.h.macos coap_config.h COPYONLY)
++endif()
++
++set(PUBLIC_HEADERS include/coap2/address.h
++ include/coap2/async.h
++ include/coap2/bits.h
++ include/coap2/block.h
++ ${CMAKE_BINARY_DIR}/include/coap2/coap.h
++ include/coap2/coap_debug.h
++ include/coap2/coap_dtls.h
++ include/coap2/coap_event.h
++ include/coap2/coap_forward_decls.h
++ include/coap2/coap_hashkey.h
++ include/coap2/coap_io.h
++ include/coap2/coap_mutex.h
++ include/coap2/coap_session.h
++ include/coap2/coap_time.h
++ include/coap2/encode.h
++ include/coap2/libcoap.h
++ include/coap2/mem.h
++ include/coap2/net.h
++ include/coap2/option.h
++ include/coap2/pdu.h
++ include/coap2/prng.h
++ include/coap2/resource.h
++ include/coap2/str.h
++ include/coap2/subscribe.h
++ include/coap2/uri.h
++ include/coap2/uthash.h)
++
++add_library(coap STATIC ${SOURCES})
++
++set_property(TARGET coap PROPERTY POSITION_INDEPENDENT_CODE ON)
++
++target_include_directories(coap
++ PRIVATE
++ ${CMAKE_BINARY_DIR}
++ PUBLIC
++ include/coap2
++ ${CMAKE_BINARY_DIR}/include/coap2/)
++
++install(TARGETS coap
++ ARCHIVE DESTINATION lib
++)
++
++install(FILES ${PUBLIC_HEADERS} DESTINATION include/coap2)
+diff -rupN orig/coap_config.h.windows patched/coap_config.h.windows
+--- orig/coap_config.h.windows 2019-11-21 17:42:00.000000000 +0100
++++ patched/coap_config.h.windows 2019-11-22 09:11:43.000000000 +0100
+@@ -67,7 +67,7 @@
+ #define snprintf _snprintf
+ #endif
+
+-#define HAVE_OPENSSL 1
++/* #define HAVE_OPENSSL 1 */
+
+ /* Define to the address where bug reports for this package should be sent. */
+ #define PACKAGE_BUGREPORT "libcoap-developers@lists.sourceforge.net"
diff --git a/win_build_vs.bat b/win_build_vs.bat
index 095cb35..f63b6da 100644
--- a/win_build_vs.bat
+++ b/win_build_vs.bat
@@ -57,9 +57,9 @@
if [%%~x] EQU [/M] (
set installer_merge_modules=ON
)
- rem if [%%~x] EQU [/C] (
- rem set build_coap=ON
- rem )
+ if [%%~x] EQU [/C] (
+ set build_coap=ON
+ )
if [%%~x] EQU [/64] (
set build_platform=x64
set generator="Visual Studio 15 2017 Win64"