libcoap_env.AppendUnique(CPPDEFINES = ['_DEFAULT_SOURCE'])
libcoap_env.AppendUnique(CFLAGS = ['-std=c99'])
-if target_os in ['linux', 'tizen', 'android', 'ios', 'arduino']:
+if target_os in ['linux', 'tizen', 'android', 'ios', 'arduino', 'windows']:
if with_tcp == True:
libcoap_env.AppendUnique(CPPDEFINES = ['WITH_TCP'])
mbedtls_env = env.Clone()
mbedtls_env.PrependUnique(CPPPATH = [mbedtls_dir])
mbedtls_env.AppendUnique(CPPPATH = [mbedtls_dir+'include/'])
-mbedtls_env.AppendUnique(CFLAGS = ['-Wall'])
+if 'g++' in mbedtls_env.get('CXX'):
+ mbedtls_env.AppendUnique(CFLAGS = ['-Wall'])
-if mbedtls_env['CC'] != 'cl':
- mbedtls_env.AppendUnique(CFLAGS = ['-fPIC'])
+ if mbedtls_env['CC'] != 'cl':
+ mbedtls_env.AppendUnique(CFLAGS = ['-fPIC'])
######################################################################
# Source files and Target(s)
'stdlib.h',
'string.h',
'strings.h',
+ 'sys/ioctl.h',
+ 'sys/poll.h',
+ 'sys/select.h',
'sys/socket.h',
'sys/stat.h',
'sys/time.h',
# endif
# define ssize_t SSIZE_T
# define F_OK 0
+# define SHUT_RDWR SD_BOTH
# define sleep(SECS) Sleep(1000*(SECS))
# ifdef __cplusplus
# define SUPPORTS_DEFAULT_CTOR
# endif
+# include "windows/include/memmem.h"
# include "windows/include/win_sleep.h"
# include "windows/include/pthread_create.h"
#endif
#ifdef HAVE_WINSOCK2_H
# define OPTVAL_T(t) (const char*)(t)
+# define OC_CLOSE_SOCKET(s) closesocket(s)
#else
# define OPTVAL_T(t) (t)
+# define OC_CLOSE_SOCKET(s) close(s)
#endif
#endif
src_dir = Dir('src').abspath
helper_src = [
os.path.join(src_dir, 'getopt.c'),
+ os.path.join(src_dir, 'memmem.c'),
os.path.join(src_dir, 'win_sleep.c'),
os.path.join(src_dir, 'snprintf.c'),
os.path.join(src_dir, 'pthread_create.c')
win_helper_env.InstallTarget(static_libwinhelper, 'win_helper')
win_helper_env.UserInstallTargetLib(static_libwinhelper, 'win_helper')
+win_helper_env.UserInstallTargetHeader('include/memmem.h', 'c_common/windows/include', 'memmem.h')
win_helper_env.UserInstallTargetHeader('include/win_sleep.h', 'c_common/windows/include', 'win_sleep.h')
win_helper_env.UserInstallTargetHeader('include/pthread_create.h', 'c_common/windows/include', 'pthread_create.h')
win_helper_env.UserInstallTargetHeader('include/vs12_snprintf.h', 'c_common/windows/include', 'vs12_snprintf.h')
--- /dev/null
+/* *****************************************************************
+*
+* Copyright 2017 Microsoft
+*
+*
+* Licensed 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.
+*
+******************************************************************/
+
+#ifndef MEMMEM_H__
+#define MEMMEM_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void *memmem(const void *haystack, size_t haystackLen, const void *needle, size_t needleLen);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
--- /dev/null
+/* *****************************************************************
+*
+* Copyright 2016 Microsoft
+*
+*
+* Licensed 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.
+*
+******************************************************************/
+
+#include <stddef.h>
+#include <memory.h>
+
+void *memmem(const void *haystack, size_t haystackLen, const void *needle, size_t needleLen)
+{
+ if (needleLen == 0)
+ {
+ return (void *) haystack;
+ }
+
+ if (haystackLen >= needleLen)
+ {
+ for (size_t i = 0; i <= haystackLen - needleLen; i++)
+ {
+ if (memcmp(needle, ((char *) haystack) + i, needleLen) == 0)
+ {
+ return ((char *) haystack) + i;
+ }
+ }
+ }
+ return NULL;
+}
env.AppendUnique(CPPDEFINES = ['NO_IP_ADAPTER'])
if with_tcp == True:
- if target_os in ['linux', 'tizen', 'android', 'arduino']:
+ if target_os in ['linux', 'tizen', 'android', 'arduino', 'windows']:
env.AppendUnique(CPPDEFINES = ['TCP_ADAPTER', 'WITH_TCP'])
print "CA Transport is TCP"
else:
#include "iotivity_config.h"
-#ifndef WITH_ARDUINO
-#ifdef TCP_ADAPTER
-#define HAVE_SYS_POLL_H
-#endif
-#endif
-
#include <stdint.h>
#include <stdlib.h>
#include <stdbool.h>
#else
int netlinkFd; /**< netlink */
int shutdownFds[2]; /**< fds used to signal threads to stop */
+ int maxfd; /**< highest fd (for select) */
#endif
int selectTimeout; /**< in seconds */
- int maxfd; /**< highest fd (for select) */
bool started; /**< the IP adapter has started */
bool terminate; /**< the IP adapter needs to stop */
bool ipv6enabled; /**< IPv6 enabled by OCInit flags */
void *svrlist; /**< unicast IPv4 TCP server information*/
int selectTimeout; /**< in seconds */
int listenBacklog; /**< backlog counts*/
+#if defined(_WIN32)
+ WSAEVENT shutdownEvent; /**< Event used to signal threads to stop */
+#else
int shutdownFds[2]; /**< shutdown pipe */
int connectionFds[2]; /**< connection pipe */
int maxfd; /**< highest fd (for select) */
+#endif
bool started; /**< the TCP adapter has started */
bool terminate; /**< the TCP adapter needs to stop */
bool ipv4tcpenabled; /**< IPv4 TCP enabled by OCInit flags */
* @param[in] sockAddrLen size of sockAddr.
* @param[out] host address string (must be CA_IPADDR_SIZE).
* @param[out] port host order port number.
+ * @return CA_STATUS_OK on success, or an appropriate error code on failure.
*/
-void CAConvertAddrToName(const struct sockaddr_storage *sockAddr, socklen_t sockAddrLen,
- char *host, uint16_t *port);
+CAResult_t CAConvertAddrToName(const struct sockaddr_storage *sockAddr, socklen_t sockAddrLen,
+ char *host, uint16_t *port);
/**
* Convert address from string to binary.
* @param[in] host address string.
* @param[in] port host order port number.
* @param[out] ipaddr IP address info.
+ * @return CA_STATUS_OK on success, or an appropriate error code on failure.
*/
-void CAConvertNameToAddr(const char *host, uint16_t port, struct sockaddr_storage *sockaddr);
+CAResult_t CAConvertNameToAddr(const char *host, uint16_t port, struct sockaddr_storage *sockaddr);
#endif /* WITH_ARDUINO */
#ifdef __JAVA__
size_t CAGetTotalLengthFromHeader(const unsigned char *recvBuffer);
/**
- * Get session information from file descriptor index.
+ * Get session information from socket file descriptor.
*
- * @param[in] fd file descriptor.
+ * @param[in] fd socket file descriptor.
* @param[out] index index of array list
* @return TCP Server Information structure.
*/
-CATCPSessionInfo_t *CAGetSessionInfoFromFD(int fd, size_t *index);
+CATCPSessionInfo_t *CAGetSessionInfoFromFD(CASocketFd_t fd, size_t *index);
/**
* Get socket file descriptor from remote device information.
if 'NFC' in ca_transport:
env.SConscript(os.path.join(ca_path, 'nfc_adapter/SConscript'))
-if ca_os in ['linux', 'tizen', 'android']:
+if ca_os in ['linux', 'tizen', 'android', 'windows']:
if with_tcp == True:
env.SConscript(os.path.join(ca_path, 'tcp_adapter/SConscript'))
env.AppendUnique(CPPDEFINES = ['WITH_TCP'])
*
******************************************************************/
+#include "iotivity_config.h"
#define _GNU_SOURCE
#include <stddef.h>
#include "mbedtls/version.h"
#endif
-#ifdef __unix__
+#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
#include <sys/stat.h>
+#endif
+#ifdef HAVE_FCNTL_H
#include <fcntl.h>
+#endif
+#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
}
#endif
-#if defined(_WIN32)
-/*
- * Finds the first occurrence of the byte string s in byte string l.
- */
-
-static void * memmem(const void *l, size_t lLen, const void *s, size_t sLen)
-{
- char *cur;
- char *last;
- const char *cl = (const char *)l;
- const char *cs = (const char *)s;
-
- if (lLen == 0 || sLen == 0)
- {
- return NULL;
- }
- if (lLen < sLen)
- {
- return NULL;
- }
- if (sLen == 1)
- {
- return (void *)memchr(l, (int)*cs, lLen);
- }
-
- last = (char *)cl + lLen - sLen;
-
- for (cur = (char *)cl; cur <= last; cur++)
- {
- if (cur[0] == cs[0] && memcmp(cur, cs, sLen) == 0)
- {
- return cur;
- }
- }
- return NULL;
-}
-#endif
/**
* structure to holds the information of cache message and address info.
*/
}
#else // not with_arduino
-/*
- * These two conversion functions return void because errors can't happen
- * (because of NI_NUMERIC), and there's nothing to do if they do happen.
- */
-void CAConvertAddrToName(const struct sockaddr_storage *sockAddr, socklen_t sockAddrLen,
- char *host, uint16_t *port)
+CAResult_t CAConvertAddrToName(const struct sockaddr_storage *sockAddr, socklen_t sockAddrLen,
+ char *host, uint16_t *port)
{
- VERIFY_NON_NULL_VOID(sockAddr, CA_ADAPTER_UTILS_TAG, "sockAddr is null");
- VERIFY_NON_NULL_VOID(host, CA_ADAPTER_UTILS_TAG, "host is null");
- VERIFY_NON_NULL_VOID(port, CA_ADAPTER_UTILS_TAG, "port is null");
+ VERIFY_NON_NULL_RET(sockAddr, CA_ADAPTER_UTILS_TAG, "sockAddr is null",
+ CA_STATUS_INVALID_PARAM);
+ VERIFY_NON_NULL_RET(host, CA_ADAPTER_UTILS_TAG, "host is null", CA_STATUS_INVALID_PARAM);
+ VERIFY_NON_NULL_RET(port, CA_ADAPTER_UTILS_TAG, "port is null", CA_STATUS_INVALID_PARAM);
int r = getnameinfo((struct sockaddr *)sockAddr,
sockAddrLen,
OIC_LOG_V(ERROR, CA_ADAPTER_UTILS_TAG,
"getnameinfo failed: %s", gai_strerror(r));
#endif
- return;
+ return CA_STATUS_FAILED;
}
*port = ntohs(((struct sockaddr_in *)sockAddr)->sin_port); // IPv4 and IPv6
+ return CA_STATUS_OK;
}
-void CAConvertNameToAddr(const char *host, uint16_t port, struct sockaddr_storage *sockaddr)
+CAResult_t CAConvertNameToAddr(const char *host, uint16_t port, struct sockaddr_storage *sockaddr)
{
- VERIFY_NON_NULL_VOID(host, CA_ADAPTER_UTILS_TAG, "host is null");
- VERIFY_NON_NULL_VOID(sockaddr, CA_ADAPTER_UTILS_TAG, "sockaddr is null");
+ VERIFY_NON_NULL_RET(host, CA_ADAPTER_UTILS_TAG, "host is null", CA_STATUS_INVALID_PARAM);
+ VERIFY_NON_NULL_RET(sockaddr, CA_ADAPTER_UTILS_TAG, "sockaddr is null",
+ CA_STATUS_INVALID_PARAM);
struct addrinfo *addrs = NULL;
struct addrinfo hints = { .ai_family = AF_UNSPEC,
- .ai_socktype = SOCK_DGRAM,
.ai_flags = AI_NUMERICHOST };
int r = getaddrinfo(host, NULL, &hints, &addrs);
OIC_LOG_V(ERROR, CA_ADAPTER_UTILS_TAG,
"getaddrinfo failed: %s", gai_strerror(r));
#endif
- return;
+ return CA_STATUS_FAILED;
}
// assumption: in this case, getaddrinfo will only return one addrinfo
// or first is the one we want.
((struct sockaddr_in *)sockaddr)->sin_port = htons(port);
}
freeaddrinfo(addrs);
+ return CA_STATUS_OK;
}
#endif // WITH_ARDUINO
}
}
-#if !defined(WSA_WAIT_EVENT_0)
-
#define CLOSE_SOCKET(TYPE) \
if (caglobals.ip.TYPE.fd != OC_INVALID_SOCKET) \
{ \
- close(caglobals.ip.TYPE.fd); \
+ OC_CLOSE_SOCKET(caglobals.ip.TYPE.fd); \
caglobals.ip.TYPE.fd = OC_INVALID_SOCKET; \
}
+#if !defined(WSA_WAIT_EVENT_0)
+
#define SET(TYPE, FDS) \
if (caglobals.ip.TYPE.fd != OC_INVALID_SOCKET) \
{ \
#else // if defined(WSA_WAIT_EVENT_0)
-#define CLOSE_SOCKET(TYPE) \
- if (caglobals.ip.TYPE.fd != OC_INVALID_SOCKET) \
- { \
- closesocket(caglobals.ip.TYPE.fd); \
- caglobals.ip.TYPE.fd = OC_INVALID_SOCKET; \
- }
-
#define PUSH_HANDLE(HANDLE, ARRAY, INDEX) \
{ \
ARRAY[INDEX] = HANDLE; \
if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, OPTVAL_T(&on), sizeof (on)))
{
OIC_LOG_V(ERROR, TAG, "SO_REUSEADDR failed: %s", CAIPS_GET_ERROR);
-#ifdef _WIN32
- closesocket(fd);
-#else
- close(fd);
-#endif
+ OC_CLOSE_SOCKET(fd);
return OC_INVALID_SOCKET;
}
}
if (OC_SOCKET_ERROR == bind(fd, (struct sockaddr *)&sa, socklen))
{
OIC_LOG_V(ERROR, TAG, "bind socket failed: %s", CAIPS_GET_ERROR);
-#ifdef _WIN32
- closesocket(fd);
-#else
- close(fd);
-#endif
+ OC_CLOSE_SOCKET(fd);
return OC_INVALID_SOCKET;
}
if (OC_SOCKET_ERROR == getsockname(fd, (struct sockaddr *)&sa, &socklen))
{
OIC_LOG_V(ERROR, TAG, "getsockname failed: %s", CAIPS_GET_ERROR);
-#ifdef _WIN32
- closesocket(fd);
-#else
- close(fd);
-#endif
+ OC_CLOSE_SOCKET(fd);
return OC_INVALID_SOCKET;
}
*port = ntohs(family == AF_INET6 ?
return fd;
}
+#ifdef _WIN32
+#define CHECKFD(FD)
+#else
#define CHECKFD(FD) \
if (FD > caglobals.ip.maxfd) \
caglobals.ip.maxfd = FD;
+#endif
+
#define NEWSOCKET(FAMILY, NAME, MULTICAST) \
caglobals.ip.NAME.fd = CACreateSocket(FAMILY, &caglobals.ip.NAME.port, MULTICAST); \
if (caglobals.ip.NAME.fd == OC_INVALID_SOCKET) \
CAResult_t CAIPStartNetworkMonitor(CAIPAdapterStateChangeCallback callback,
CATransportAdapter_t adapter)
{
+ if (g_CAIPNetworkMonitorNotificationHandle != NULL)
+ {
+ // The monitor has already been started. This can happen when using both the
+ // IP and TCP transport adapters.
+ return CA_STATUS_OK;
+ }
+
CAResult_t res = CAIPInitializeNetworkMonitorList();
if (res != CA_STATUS_OK)
{
res = CAIPSetNetworkMonitorCallback(callback, adapter);
if (res != CA_STATUS_OK)
{
+ CAIPDestroyNetworkMonitorList();
return res;
}
- if (g_CAIPNetworkMonitorNotificationHandle == NULL)
- {
#ifdef USE_SOCKET_ADDRESS_CHANGE_EVENT
- if (!RegisterForIpAddressChange())
- {
- return CA_STATUS_FAILED;
- }
+ if (!RegisterForIpAddressChange())
+ {
+ CAIPDestroyNetworkMonitorList();
+ CAIPUnSetNetworkMonitorCallback(adapter);
+ return CA_STATUS_FAILED;
+ }
#else
- int err = NotifyUnicastIpAddressChange(AF_UNSPEC, IpAddressChangeCallback, NULL,
- true,
- &g_CAIPNetworkMonitorNotificationHandle);
- if (err != NO_ERROR)
- {
- return CA_STATUS_FAILED;
- }
-#endif
+ int err = NotifyUnicastIpAddressChange(AF_UNSPEC, IpAddressChangeCallback, NULL,
+ true,
+ &g_CAIPNetworkMonitorNotificationHandle);
+ if (err != NO_ERROR)
+ {
+ CAIPDestroyNetworkMonitorList();
+ CAIPUnSetNetworkMonitorCallback(adapter);
+ return CA_STATUS_FAILED;
}
+#endif
return CA_STATUS_OK;
}
# Source files to build common for all platforms
common_files = None
-if target_os in ['linux', 'tizen', 'android']:
+if target_os in ['linux', 'tizen', 'android', 'windows']:
common_files = [
os.path.join(src_dir, 'catcpadapter.c'),
os.path.join(src_dir, 'catcpserver.c') ]
# The list of TCP adapter source files is a combination of both the
# common and target-specific source file lists.
-env.AppendUnique(CA_SRC = common_files + target_files)
\ No newline at end of file
+env.AppendUnique(CA_SRC = common_files + target_files)
*
******************************************************************/
+#include "iotivity_config.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
*
******************************************************************/
+#include "iotivity_config.h"
+#include "iotivity_debug.h"
#include <sys/types.h>
+#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h>
+#endif
+#ifdef HAVE_WS2TCPIP_H
+#include <ws2tcpip.h>
+#endif
+#ifdef HAVE_SYS_SELECT_H
#include <sys/select.h>
+#endif
+#ifdef HAVE_SYS_IOCTL_H
#include <sys/ioctl.h>
+#endif
+#ifdef HAVE_SYS_POLL_H
#include <sys/poll.h>
+#endif
#include <stdio.h>
+#ifdef HAVE_UNISTD_H
#include <unistd.h>
+#endif
#include <fcntl.h>
+#ifdef HAVE_ARPA_INET_H
#include <arpa/inet.h>
+#endif
+#ifdef HAVE_NETINET_IN_H
#include <netinet/in.h>
+#endif
+#ifdef HAVE_NET_IF_H
#include <net/if.h>
+#endif
#include <errno.h>
+#include <assert.h>
-#ifndef WITH_ARDUINO
-#include <sys/socket.h>
-#include <netinet/in.h>
+#ifdef HAVE_NETDB_H
#include <netdb.h>
#endif
static CASocketFd_t CACreateAcceptSocket(int family, CASocket_t *sock);
static void CAAcceptConnection(CATransportFlags_t flag, CASocket_t *sock);
static void CAFindReadyMessage();
+#if !defined(WSA_WAIT_EVENT_0)
static void CASelectReturned(fd_set *readFds);
-static void CAReceiveMessage(int fd);
+#else
+static void CASocketEventReturned(CASocketFd_t socket);
+#endif
+static void CAReceiveMessage(CASocketFd_t fd);
static void CAReceiveHandler(void *data);
static CAResult_t CATCPCreateSocket(int family, CATCPSessionInfo_t *svritem);
+#if defined(WSA_WAIT_EVENT_0)
+#define CHECKFD(FD)
+#else
#define CHECKFD(FD) \
if (FD > caglobals.tcp.maxfd) \
caglobals.tcp.maxfd = FD;
+#endif
#define CLOSE_SOCKET(TYPE) \
if (caglobals.tcp.TYPE.fd != OC_INVALID_SOCKET) \
{ \
- close(caglobals.tcp.TYPE.fd); \
+ OC_CLOSE_SOCKET(caglobals.tcp.TYPE.fd); \
caglobals.tcp.TYPE.fd = OC_INVALID_SOCKET; \
}
OIC_LOG(DEBUG, TAG, "OUT - CAReceiveHandler");
}
+#if !defined(WSA_WAIT_EVENT_0)
+
static void CAFindReadyMessage()
{
fd_set readFds;
}
}
+#else // if defined(WSA_WAIT_EVENT_0)
+
+/**
+ * Push an exiting socket event to listen on
+ *
+ * @param[in] s Socket to push
+ * @param[in] socketArray Array in which to add socket
+ * @param[in] event Event to push
+ * @param[in] eventArray Array in which to add event
+ * @param[in/out] eventIndex Current length of arrays
+ * @param[in] arraySize Maximum length of arrays
+ * @return true on success, false on failure
+ */
+static bool CAPushEvent(CASocketFd_t s, CASocketFd_t* socketArray,
+ HANDLE event, HANDLE* eventArray, int* eventIndex, int arraySize)
+{
+ if (*eventIndex == arraySize)
+ {
+ return false;
+ }
+
+ assert(*eventIndex >= 0);
+ socketArray[*eventIndex] = s;
+ eventArray[(*eventIndex)++] = event;
+ return true;
+}
+
+/**
+ * Push a new socket event to listen on
+ *
+ * @param[in] s Socket to push
+ * @param[in] socketArray Array in which to add socket
+ * @param[in] eventArray Array in which to add event
+ * @param[in/out] eventIndex Current length of arrays
+ * @param[in] arraySize Maximum length of arrays
+ * @return true on success, false on failure
+ */
+static bool CAPushSocket(CASocketFd_t s, CASocketFd_t* socketArray,
+ HANDLE *eventArray, int *eventIndex, int arraySize)
+{
+ if (s == OC_INVALID_SOCKET)
+ {
+ // Nothing to push.
+ return true;
+ }
+
+ WSAEVENT newEvent = WSACreateEvent();
+ if (WSA_INVALID_EVENT == newEvent)
+ {
+ OIC_LOG_V(ERROR, TAG, "WSACreateEvent(NewEvent) failed %u", WSAGetLastError());
+ return false;
+ }
+
+ if (0 != WSAEventSelect(s, newEvent, FD_READ))
+ {
+ OIC_LOG_V(ERROR, TAG, "WSAEventSelect failed %u", WSAGetLastError());
+ OC_VERIFY(WSACloseEvent(newEvent));
+ return false;
+ }
+
+ if (!CAPushEvent(s, socketArray, newEvent, eventArray, eventIndex, arraySize))
+ {
+ OIC_LOG_V(ERROR, TAG, "CAPushEvent failed");
+ OC_VERIFY(WSACloseEvent(newEvent));
+ return false;
+ }
+
+ return true;
+}
+
+#define EVENT_ARRAY_SIZE 64
+
+/**
+ * Process any message that is ready
+ */
+static void CAFindReadyMessage()
+{
+ CASocketFd_t socketArray[EVENT_ARRAY_SIZE] = {0};
+ HANDLE eventArray[_countof(socketArray)];
+ int arraySize = 0;
+ int eventIndex;
+
+ if (OC_INVALID_SOCKET != caglobals.tcp.ipv4.fd)
+ {
+ CAPushSocket(caglobals.tcp.ipv4.fd, socketArray, eventArray, &arraySize, _countof(socketArray));
+ }
+ if (OC_INVALID_SOCKET != caglobals.tcp.ipv6.fd)
+ {
+ CAPushSocket(caglobals.tcp.ipv6.fd, socketArray, eventArray, &arraySize, _countof(socketArray));
+ }
+ if (WSA_INVALID_EVENT != caglobals.tcp.shutdownEvent)
+ {
+ CAPushEvent(OC_INVALID_SOCKET, socketArray,
+ caglobals.tcp.shutdownEvent, eventArray, &arraySize, _countof(socketArray));
+ }
+
+ uint32_t length = u_arraylist_length(caglobals.tcp.svrlist);
+ for (size_t i = 0; (i < length) && (arraySize < EVENT_ARRAY_SIZE); i++)
+ {
+ CATCPSessionInfo_t *svritem =
+ (CATCPSessionInfo_t *) u_arraylist_get(caglobals.tcp.svrlist, i);
+ if (svritem && OC_INVALID_SOCKET != svritem->fd)
+ {
+ CAPushSocket(svritem->fd, socketArray, eventArray, &arraySize, _countof(socketArray));
+ }
+ }
+
+ // Should not have overflowed buffer
+ assert(arraySize <= (_countof(socketArray)));
+
+ while (!caglobals.tcp.terminate)
+ {
+ DWORD ret = WSAWaitForMultipleEvents(arraySize, eventArray, FALSE, WSA_INFINITE, FALSE);
+ eventIndex = ret - WSA_WAIT_EVENT_0;
+ assert((eventIndex >= 0) && (eventIndex < arraySize));
+
+ if (false == WSAResetEvent(eventArray[eventIndex]))
+ {
+ OIC_LOG_V(ERROR, TAG, "WSAResetEvent failed %u", WSAGetLastError());
+ }
+
+ if ((caglobals.tcp.shutdownEvent != WSA_INVALID_EVENT) &&
+ (caglobals.tcp.shutdownEvent == eventArray[eventIndex]))
+ {
+ continue;
+ }
+
+ // All other events are socket events.
+ CASocketEventReturned(socketArray[eventIndex]);
+ }
+
+ while (arraySize > 0)
+ {
+ arraySize--;
+ OC_VERIFY(WSACloseEvent(eventArray[arraySize]));
+ }
+
+ if (caglobals.tcp.terminate)
+ {
+ caglobals.tcp.shutdownEvent = WSA_INVALID_EVENT;
+ WSACleanup();
+ }
+}
+
+/**
+ * Process an event (accept or receive) that is ready on a socket
+ *
+ * @param[in] s Socket to process
+ */
+static void CASocketEventReturned(CASocketFd_t s)
+{
+ if (caglobals.tcp.terminate)
+ {
+ return;
+ }
+
+ if ((caglobals.tcp.ipv4.fd != OC_INVALID_SOCKET) && (caglobals.tcp.ipv4.fd == s))
+ {
+ CAAcceptConnection(CA_IPV4, &caglobals.tcp.ipv4);
+ return;
+ }
+ if ((caglobals.tcp.ipv6.fd != OC_INVALID_SOCKET) && (caglobals.tcp.ipv6.fd == s))
+ {
+ CAAcceptConnection(CA_IPV6, &caglobals.tcp.ipv6);
+ return;
+ }
+
+ CAReceiveMessage(s);
+}
+
+#endif // WSA_WAIT_EVENT_0
+
static void CAAcceptConnection(CATransportFlags_t flag, CASocket_t *sock)
{
VERIFY_NON_NULL_VOID(sock, TAG, "sock is NULL");
if (!svritem)
{
OIC_LOG(ERROR, TAG, "Out of memory");
- close(sockfd);
+ OC_CLOSE_SOCKET(sockfd);
return;
}
if (!result)
{
OIC_LOG(ERROR, TAG, "u_arraylist_add failed.");
- close(sockfd);
+ OC_CLOSE_SOCKET(sockfd);
OICFree(svritem);
oc_mutex_unlock(g_mutexObjectList);
return;
return CA_STATUS_OK;
}
-static void CAReceiveMessage(int fd)
+static void CAReceiveMessage(CASocketFd_t fd)
{
CAResult_t res = CA_STATUS_OK;
{
OIC_LOG_V(ERROR, TAG, "toal tls length is too big (buffer size : %u)",
sizeof(svritem->tlsdata));
- return CA_STATUS_FAILED;
+ return;
}
nbRead = tlsLength - svritem->tlsLen;
}
}
}
+#if !defined(WSA_WAIT_EVENT_0)
static ssize_t CAWakeUpForReadFdsUpdate(const char *host)
{
if (caglobals.tcp.connectionFds[1] != -1)
}
return -1;
}
+#endif
static CAResult_t CATCPConvertNameToAddr(int family, const char *host, uint16_t port,
struct sockaddr_storage *sockaddr)
int r = getaddrinfo(host, NULL, &hints, &addrs);
if (r)
{
+#ifdef EAI_SYSTEM
if (EAI_SYSTEM == r)
{
OIC_LOG_V(ERROR, TAG, "getaddrinfo failed: errno %s", strerror(errno));
}
else
+#endif
{
OIC_LOG_V(ERROR, TAG, "getaddrinfo failed: %s", gai_strerror(r));
}
svritem->sep.endpoint.addr, svritem->sep.endpoint.port);
// #1. create tcp socket.
- int fd = socket(family, SOCK_STREAM, IPPROTO_TCP);
- if (-1 == fd)
+ CASocketFd_t fd = socket(family, SOCK_STREAM, IPPROTO_TCP);
+ if (OC_INVALID_SOCKET == fd)
{
OIC_LOG_V(ERROR, TAG, "create socket failed: %s", strerror(errno));
return CA_SOCKET_OPERATION_FAILED;
// #2. convert address from string to binary.
struct sockaddr_storage sa = { .ss_family = family };
- CAResult_t res = CATCPConvertNameToAddr(family, svritem->sep.endpoint.addr,
- svritem->sep.endpoint.port, &sa);
+ CAResult_t res = CAConvertNameToAddr(svritem->sep.endpoint.addr,
+ svritem->sep.endpoint.port, &sa);
if (CA_STATUS_OK != res)
{
OIC_LOG(ERROR, TAG, "convert name to sockaddr failed");
OIC_LOG(DEBUG, TAG, "connect socket success");
svritem->state = CONNECTED;
CHECKFD(svritem->fd);
+#if !defined(WSA_WAIT_EVENT_0)
ssize_t len = CAWakeUpForReadFdsUpdate(svritem->sep.endpoint.addr);
if (-1 == len)
{
OIC_LOG(ERROR, TAG, "wakeup receive thread failed");
return CA_SOCKET_OPERATION_FAILED;
}
+#endif
return CA_STATUS_OK;
}
static CASocketFd_t CACreateAcceptSocket(int family, CASocket_t *sock)
{
- VERIFY_NON_NULL_RET(sock, TAG, "sock", -1);
+ VERIFY_NON_NULL_RET(sock, TAG, "sock", OC_INVALID_SOCKET);
if (OC_INVALID_SOCKET != sock->fd)
{
socklen_t socklen = 0;
struct sockaddr_storage server = { .ss_family = family };
- int fd = socket(family, SOCK_STREAM, IPPROTO_TCP);
+ CASocketFd_t fd = socket(family, SOCK_STREAM, IPPROTO_TCP);
if (OC_INVALID_SOCKET == fd)
{
OIC_LOG(ERROR, TAG, "Failed to create socket");
{
// the socket is restricted to sending and receiving IPv6 packets only.
int on = 1;
- if (-1 == setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof (on)))
+ if (OC_SOCKET_ERROR == setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, OPTVAL_T(&on), sizeof (on)))
{
OIC_LOG_V(ERROR, TAG, "IPV6_V6ONLY failed: %s", strerror(errno));
goto exit;
}
int reuse = 1;
- if (-1 == setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)))
+ if (OC_SOCKET_ERROR == setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, OPTVAL_T(&reuse), sizeof(reuse)))
{
OIC_LOG(ERROR, TAG, "setsockopt SO_REUSEADDR");
goto exit;
}
- if (-1 == bind(fd, (struct sockaddr *)&server, socklen))
+ if (OC_SOCKET_ERROR == bind(fd, (struct sockaddr *)&server, socklen))
{
OIC_LOG_V(ERROR, TAG, "bind socket failed: %s", strerror(errno));
goto exit;
if (!sock->port) // return the assigned port
{
- if (-1 == getsockname(fd, (struct sockaddr *)&server, &socklen))
+ if (OC_SOCKET_ERROR == getsockname(fd, (struct sockaddr *)&server, &socklen))
{
OIC_LOG_V(ERROR, TAG, "getsockname failed: %s", strerror(errno));
goto exit;
return fd;
exit:
- if (fd >= 0)
+ if (fd != OC_INVALID_SOCKET)
{
- close(fd);
+ OC_CLOSE_SOCKET(fd);
}
return OC_INVALID_SOCKET;
}
+#if !defined(WSA_WAIT_EVENT_0)
static void CAInitializePipe(int *fds)
{
int ret = pipe(fds);
}
}
}
+#endif
#define NEWSOCKET(FAMILY, NAME) \
caglobals.tcp.NAME.fd = CACreateAcceptSocket(FAMILY, &caglobals.tcp.NAME); \
- if (caglobals.tcp.NAME.fd == -1) \
+ if (caglobals.tcp.NAME.fd == OC_INVALID_SOCKET) \
{ \
caglobals.tcp.NAME.port = 0; \
caglobals.tcp.NAME.fd = CACreateAcceptSocket(FAMILY, &caglobals.tcp.NAME); \
caglobals.tcp.ipv6s.fd, caglobals.tcp.ipv6s.port);
}
- // create pipe for fast shutdown
+ // create mechanism for fast shutdown
+#ifdef WSA_WAIT_EVENT_0
+ caglobals.tcp.shutdownEvent = WSACreateEvent();
+ if (WSA_INVALID_EVENT == caglobals.tcp.shutdownEvent)
+ {
+ OIC_LOG(ERROR, TAG, "failed to create shutdown event");
+ return res;
+ }
+#else
CAInitializePipe(caglobals.tcp.shutdownFds);
CHECKFD(caglobals.tcp.shutdownFds[0]);
CHECKFD(caglobals.tcp.shutdownFds[1]);
+#endif
- // create pipe for connection event
+#ifndef WSA_WAIT_EVENT_0
CAInitializePipe(caglobals.tcp.connectionFds);
CHECKFD(caglobals.tcp.connectionFds[0]);
CHECKFD(caglobals.tcp.connectionFds[1]);
+#endif
caglobals.tcp.terminate = false;
res = ca_thread_pool_add_task(threadPool, CAReceiveHandler, NULL);
// set terminate flag.
caglobals.tcp.terminate = true;
+#if !defined(WSA_WAIT_EVENT_0)
if (caglobals.tcp.shutdownFds[1] != -1)
{
close(caglobals.tcp.shutdownFds[1]);
close(caglobals.tcp.connectionFds[1]);
caglobals.tcp.connectionFds[1] = OC_INVALID_SOCKET;
}
+#else
+ // receive thread will stop immediately.
+ if (!WSASetEvent(caglobals.tcp.shutdownEvent))
+ {
+ OIC_LOG_V(DEBUG, TAG, "set shutdown event failed: %u", GetLastError());
+ }
+#endif
// close accept socket.
CLOSE_SOCKET(ipv4);
}
continue;
}
- data += len;
+ data = ((char*)data) + len;
remainLen -= len;
} while (remainLen > 0);
if (!res)
{
OIC_LOG(ERROR, TAG, "u_arraylist_add failed.");
- close(svritem->fd);
+ OC_CLOSE_SOCKET(svritem->fd);
OICFree(svritem);
oc_mutex_unlock(g_mutexObjectList);
return OC_INVALID_SOCKET;
}
// close the socket and remove session info in list.
- if (removedData->fd >= 0)
+ if (removedData->fd != OC_INVALID_SOCKET)
{
shutdown(removedData->fd, SHUT_RDWR);
- close(removedData->fd);
- removedData->fd = -1;
+ OC_CLOSE_SOCKET(removedData->fd);
+ removedData->fd = OC_INVALID_SOCKET;
OIC_LOG(DEBUG, TAG, "close socket");
removedData->state = (CONNECTED == removedData->state) ?
DISCONNECTED : removedData->state;
return OC_INVALID_SOCKET;
}
-CATCPSessionInfo_t *CAGetSessionInfoFromFD(int fd, size_t *index)
+CATCPSessionInfo_t *CAGetSessionInfoFromFD(CASocketFd_t fd, size_t *index)
{
oc_mutex_lock(g_mutexObjectList);
#define CAsetSslHandshakeCallback CAsetSslHandshakeCallbackTest
#define CAsetTlsCipherSuite CAsetTlsCipherSuiteTest
#define CAsslGenerateOwnerPsk CAsslGenerateOwnerPskTest
+#define CAcloseSslConnectionAll CAcloseSslConnectionAllTest
#include "../src/adapter_util/ca_adapter_net_ssl.c"
OCRepPayloadGetPropBool
OCRepPayloadGetPropByteString
OCRepPayloadGetPropInt
+OCRepPayloadGetPropString
OCRepPayloadSetBoolArray
OCRepPayloadSetBoolArrayAsOwner
OCRepPayloadSetByteStringArray
OCStopPresence
OCStopMulticastServer
OCUnBindResource
+
+; Cloud APIs used with WITH_TCP is set
+clearStringArray
+DEFAULT_PREFIX
+DEFAULT_QUERY
+DeleteCrl
+FreeRsrc
+getDeviceId
+OCCloudAclCancelInvitation
+OCCloudAclCreateGroup
+OCCloudAclDeleteDeviceFromGroup
+OCCloudAclDeleteGroup
+OCCloudAclDeleteInvitation
+OCCloudAclFindMyGroup
+OCCloudGetAclIdByDevice
+OCCloudAclGetInvitation
+OCCloudAclGroupGetInfo
+OCCloudAclIdCreate
+OCCloudAclIdDelete
+OCCloudAclIndividualDelete
+OCCloudAclIndividualDeleteAce
+OCCloudAclIndividualGetInfo
+OCCloudAclIndividualUpdate
+OCCloudAclIndividualUpdateAce
+OCCloudAclInviteUser
+OCCloudAclJoinToInvitedGroup
+OCCloudAclObserveGroup
+OCCloudAclPolicyCheck
+OCCloudAclShareDeviceIntoGroup
+OCCloudCertificateIssueRequest
+OCCloudGetCRL
+OCCloudPostCRL
+OCSaveTrustCertChain
+OIC_RSRC_DOXM_URI
+OIC_RSRC_PSTAT_URI
+printACL
+printCrl
+setCoapPrefix
provisioning_env.AppendUnique(LIBPATH = [env.get('BUILD_DIR')])
else:
provisioning_env.AppendUnique(LIBPATH = [os.path.join(env.get('BUILD_DIR'), 'resource', 'csdk')])
- provisioning_env.AppendUnique(LIBS = ['ws2_32', 'iphlpapi', 'advapi32'])
provisioning_env.PrependUnique(LIBS = ['oc', 'oc_logger', 'octbstack', 'connectivity_abstraction', 'coap'])
* limitations under the License.
*
* *****************************************************************/
+#include "iotivity_config.h"
#include "utils.h"
#include "logger.h"
#include "mbedtls/version.h"
#endif
+#ifdef HAVE_UNISTD_H
#include <unistd.h>
+#endif
#include <fcntl.h>
#define TAG "OIC_CLOUD_CSR"
set SECURED=1
set ROUTING=EP
+set WITH_TCP=1
set WITH_UPSTREAM_LIBCOAP=1
set BINDIR=debug
set PATH=!PATH!;!BUILD_DIR!;C:\msys64\mingw64\bin
)
-set BUILD_OPTIONS= TARGET_OS=%TARGET_OS% TARGET_ARCH=%TARGET_ARCH% RELEASE=%RELEASE% WITH_RA=0 TARGET_TRANSPORT=IP SECURED=%SECURED% WITH_TCP=0 BUILD_SAMPLE=ON LOGGING=%LOGGING% TEST=%TEST% RD_MODE=CLIENT ROUTING=%ROUTING% WITH_UPSTREAM_LIBCOAP=%WITH_UPSTREAM_LIBCOAP%
+set BUILD_OPTIONS= TARGET_OS=%TARGET_OS% TARGET_ARCH=%TARGET_ARCH% RELEASE=%RELEASE% WITH_RA=0 TARGET_TRANSPORT=IP SECURED=%SECURED% WITH_TCP=%WITH_TCP% BUILD_SAMPLE=ON LOGGING=%LOGGING% TEST=%TEST% RD_MODE=CLIENT ROUTING=%ROUTING% WITH_UPSTREAM_LIBCOAP=%WITH_UPSTREAM_LIBCOAP%
REM Use MSVC_VERSION=12.0 for VS2013, or MSVC_VERSION=14.0 for VS2015.
REM If MSVC_VERSION has not been defined here, SCons chooses automatically a VS version.
echo TEST=%TEST%
echo LOGGING=%LOGGING%
echo ROUTING=%ROUTING%
+ echo WITH_TCP=%WITH_TCP%
echo WITH_UPSTREAM_LIBCOAP=%WITH_UPSTREAM_LIBCOAP%
echo MSVC_VERSION=%MSVC_VERSION%
echo.scons VERBOSE=1 %BUILD_OPTIONS%