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"