← Back to ratslair.com
aboutsummaryrefslogtreecommitdiff
path: root/LIDAR/sdk/src/arch/win32
diff options
context:
space:
mode:
Diffstat (limited to 'LIDAR/sdk/src/arch/win32')
-rw-r--r--LIDAR/sdk/src/arch/win32/arch_win32.h66
-rw-r--r--LIDAR/sdk/src/arch/win32/net_serial.cpp367
-rw-r--r--LIDAR/sdk/src/arch/win32/net_serial.h86
-rw-r--r--LIDAR/sdk/src/arch/win32/net_socket.cpp945
-rw-r--r--LIDAR/sdk/src/arch/win32/timer.cpp72
-rw-r--r--LIDAR/sdk/src/arch/win32/timer.h49
-rw-r--r--LIDAR/sdk/src/arch/win32/winthread.hpp144
7 files changed, 1729 insertions, 0 deletions
diff --git a/LIDAR/sdk/src/arch/win32/arch_win32.h b/LIDAR/sdk/src/arch/win32/arch_win32.h
new file mode 100644
index 0000000..3ae6655
--- /dev/null
+++ b/LIDAR/sdk/src/arch/win32/arch_win32.h
@@ -0,0 +1,66 @@
+/*
+ * RPLIDAR SDK
+ *
+ * Copyright (c) 2009 - 2014 RoboPeak Team
+ * http://www.robopeak.com
+ * Copyright (c) 2014 - 2020 Shanghai Slamtec Co., Ltd.
+ * http://www.slamtec.com
+ *
+ */
+/*
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+#pragma warning (disable: 4996)
+#define _CRT_SECURE_NO_WARNINGS
+
+#ifndef WINVER
+#define WINVER 0x0500
+#endif
+
+#ifndef _WIN32_WINNT
+#define _WIN32_WINNT 0x0501
+#endif
+
+
+#ifndef _WIN32_IE
+#define _WIN32_IE 0x0501
+#endif
+
+#ifndef _RICHEDIT_VER
+#define _RICHEDIT_VER 0x0200
+#endif
+
+
+#include <stddef.h>
+#include <stdio.h>
+#include <windows.h>
+#include <stdlib.h> //for memcpy etc..
+#include <process.h>
+#include <direct.h>
+
+
+#include "timer.h"
diff --git a/LIDAR/sdk/src/arch/win32/net_serial.cpp b/LIDAR/sdk/src/arch/win32/net_serial.cpp
new file mode 100644
index 0000000..f1fe025
--- /dev/null
+++ b/LIDAR/sdk/src/arch/win32/net_serial.cpp
@@ -0,0 +1,367 @@
+/*
+ * RPLIDAR SDK
+ *
+ * Copyright (c) 2009 - 2014 RoboPeak Team
+ * http://www.robopeak.com
+ * Copyright (c) 2014 - 2020 Shanghai Slamtec Co., Ltd.
+ * http://www.slamtec.com
+ *
+ */
+/*
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include "sdkcommon.h"
+#include "net_serial.h"
+
+namespace rp{ namespace arch{ namespace net{
+
+raw_serial::raw_serial()
+ : rp::hal::serial_rxtx()
+ , _serial_handle(NULL)
+ , _baudrate(0)
+ , _flags(0)
+{
+ _init();
+}
+
+raw_serial::~raw_serial()
+{
+ close();
+
+ CloseHandle(_ro.hEvent);
+ CloseHandle(_wo.hEvent);
+ CloseHandle(_wait_o.hEvent);
+}
+
+bool raw_serial::open()
+{
+ return open(_portName, _baudrate, _flags);
+}
+
+bool raw_serial::bind(const char * portname, _u32 baudrate, _u32 flags)
+{
+ strncpy(_portName, portname, sizeof(_portName));
+ _baudrate = baudrate;
+ _flags = flags;
+ return true;
+}
+
+bool raw_serial::open(const char * portname, _u32 baudrate, _u32 flags)
+{
+#ifdef _UNICODE
+ wchar_t wportname[1024];
+ mbstowcs(wportname, portname, sizeof(wportname) / sizeof(wchar_t));
+#endif
+
+ if (isOpened()) close();
+
+ _serial_handle = CreateFile(
+#ifdef _UNICODE
+ wportname,
+#else
+ portname,
+#endif
+ GENERIC_READ | GENERIC_WRITE,
+ 0,
+ NULL,
+ OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
+ NULL
+ );
+
+ if (_serial_handle == INVALID_HANDLE_VALUE) return false;
+
+ if (!SetupComm(_serial_handle, SERIAL_RX_BUFFER_SIZE, SERIAL_TX_BUFFER_SIZE))
+ {
+ close();
+ return false;
+ }
+
+ _dcb.BaudRate = baudrate;
+ _dcb.ByteSize = 8;
+ _dcb.Parity = NOPARITY;
+ _dcb.StopBits = ONESTOPBIT;
+ _dcb.fDtrControl = DTR_CONTROL_ENABLE;
+
+ if (!SetCommState(_serial_handle, &_dcb))
+ {
+ close();
+ return false;
+ }
+
+ if (!SetCommTimeouts(_serial_handle, &_co))
+ {
+ close();
+ return false;
+ }
+
+ if (!SetCommMask(_serial_handle, EV_RXCHAR | EV_ERR ))
+ {
+ close();
+ return false;
+ }
+
+ if (!PurgeComm(_serial_handle, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR ))
+ {
+ close();
+ return false;
+ }
+
+ Sleep(30);
+ _is_serial_opened = true;
+
+ //Clear the DTR bit set DTR=high
+ clearDTR();
+
+ return true;
+}
+
+void raw_serial::close()
+{
+ SetCommMask(_serial_handle, 0);
+ ResetEvent(_wait_o.hEvent);
+
+ CloseHandle(_serial_handle);
+ _serial_handle = INVALID_HANDLE_VALUE;
+
+ _is_serial_opened = false;
+}
+
+int raw_serial::senddata(const unsigned char * data, size_t size)
+{
+ DWORD error;
+ DWORD w_len = 0, o_len = -1;
+ if (!isOpened()) return ANS_DEV_ERR;
+
+ if (data == NULL || size ==0) return 0;
+
+ if(ClearCommError(_serial_handle, &error, NULL) && error > 0)
+ PurgeComm(_serial_handle, PURGE_TXABORT | PURGE_TXCLEAR);
+
+ if(!WriteFile(_serial_handle, data, (DWORD)size, &w_len, &_wo))
+ if(GetLastError() != ERROR_IO_PENDING)
+ w_len = ANS_DEV_ERR;
+
+ return w_len;
+}
+
+int raw_serial::recvdata(unsigned char * data, size_t size)
+{
+ if (!isOpened()) return 0;
+ DWORD r_len = 0;
+
+
+ if(!ReadFile(_serial_handle, data, (DWORD)size, &r_len, &_ro))
+ {
+ if(GetLastError() == ERROR_IO_PENDING)
+ {
+ if(!GetOverlappedResult(_serial_handle, &_ro, &r_len, FALSE))
+ {
+ if(GetLastError() != ERROR_IO_INCOMPLETE)
+ r_len = 0;
+ }
+ }
+ else
+ r_len = 0;
+ }
+
+ return r_len;
+}
+
+void raw_serial::flush( _u32 flags)
+{
+ PurgeComm(_serial_handle, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR );
+}
+
+int raw_serial::waitforsent(_u32 timeout, size_t * returned_size)
+{
+ if (!isOpened() ) return ANS_DEV_ERR;
+ DWORD w_len = 0;
+ _word_size_t ans =0;
+
+ if (WaitForSingleObject(_wo.hEvent, timeout) == WAIT_TIMEOUT)
+ {
+ ans = ANS_TIMEOUT;
+ goto _final;
+ }
+ if(!GetOverlappedResult(_serial_handle, &_wo, &w_len, FALSE))
+ {
+ ans = ANS_DEV_ERR;
+ }
+_final:
+ if (returned_size) *returned_size = w_len;
+ return (int)ans;
+}
+
+int raw_serial::waitforrecv(_u32 timeout, size_t * returned_size)
+{
+ if (!isOpened() ) return -1;
+ DWORD r_len = 0;
+ _word_size_t ans =0;
+
+ if (WaitForSingleObject(_ro.hEvent, timeout) == WAIT_TIMEOUT)
+ {
+ ans = ANS_TIMEOUT;
+ }
+ if(!GetOverlappedResult(_serial_handle, &_ro, &r_len, FALSE))
+ {
+ ans = ANS_DEV_ERR;
+ }
+ if (returned_size) *returned_size = r_len;
+ return (int)ans;
+}
+
+int raw_serial::waitfordata(size_t data_count, _u32 timeout, size_t * returned_size)
+{
+ COMSTAT stat;
+ DWORD error;
+ DWORD msk,length;
+ size_t dummy_length;
+
+ if (returned_size==NULL) returned_size=(size_t *)&dummy_length;
+
+
+ if ( isOpened()) {
+ size_t rxqueue_remaining = rxqueue_count();
+ if (rxqueue_remaining >= data_count) {
+ *returned_size = rxqueue_remaining;
+ return 0;
+ }
+ }
+
+ while ( isOpened() )
+ {
+ msk = 0;
+ SetCommMask(_serial_handle, EV_RXCHAR | EV_ERR );
+ if(!WaitCommEvent(_serial_handle, &msk, &_wait_o))
+ {
+ if(GetLastError() == ERROR_IO_PENDING)
+ {
+ if (WaitForSingleObject(_wait_o.hEvent, timeout) == WAIT_TIMEOUT)
+ {
+ *returned_size =0;
+ return ANS_TIMEOUT;
+ }
+
+ GetOverlappedResult(_serial_handle, &_wait_o, &length, TRUE);
+
+ ::ResetEvent(_wait_o.hEvent);
+ }else
+ {
+ ClearCommError(_serial_handle, &error, &stat);
+ *returned_size = stat.cbInQue;
+ return ANS_DEV_ERR;
+ }
+ }
+
+ if(msk & EV_ERR){
+ // FIXME: may cause problem here
+ ClearCommError(_serial_handle, &error, &stat);
+ }
+
+ if(msk & EV_RXCHAR){
+ ClearCommError(_serial_handle, &error, &stat);
+ if(stat.cbInQue >= data_count)
+ {
+ *returned_size = stat.cbInQue;
+ return 0;
+ }
+ }
+ }
+ *returned_size=0;
+ return ANS_DEV_ERR;
+}
+
+size_t raw_serial::rxqueue_count()
+{
+ if ( !isOpened() ) return 0;
+ COMSTAT com_stat;
+ DWORD error;
+ DWORD r_len = 0;
+
+ if(ClearCommError(_serial_handle, &error, &com_stat) && error > 0)
+ {
+ PurgeComm(_serial_handle, PURGE_RXABORT | PURGE_RXCLEAR);
+ return 0;
+ }
+ return com_stat.cbInQue;
+}
+
+void raw_serial::setDTR()
+{
+ if ( !isOpened() ) return;
+
+ EscapeCommFunction(_serial_handle, SETDTR);
+}
+
+void raw_serial::clearDTR()
+{
+ if ( !isOpened() ) return;
+
+ EscapeCommFunction(_serial_handle, CLRDTR);
+}
+
+
+void raw_serial::_init()
+{
+ memset(&_dcb, 0, sizeof(_dcb));
+ _dcb.DCBlength = sizeof(_dcb);
+ _serial_handle = INVALID_HANDLE_VALUE;
+ memset(&_co, 0, sizeof(_co));
+ _co.ReadIntervalTimeout = 0;
+ _co.ReadTotalTimeoutMultiplier = 0;
+ _co.ReadTotalTimeoutConstant = 0;
+ _co.WriteTotalTimeoutMultiplier = 0;
+ _co.WriteTotalTimeoutConstant = 0;
+
+ memset(&_ro, 0, sizeof(_ro));
+ memset(&_wo, 0, sizeof(_wo));
+ memset(&_wait_o, 0, sizeof(_wait_o));
+
+ _ro.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
+ _wo.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
+ _wait_o.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
+
+ _portName[0] = 0;
+}
+
+}}} //end rp::arch::net
+
+
+//begin rp::hal
+namespace rp{ namespace hal{
+
+serial_rxtx * serial_rxtx::CreateRxTx()
+{
+ return new rp::arch::net::raw_serial();
+}
+
+void serial_rxtx::ReleaseRxTx( serial_rxtx * rxtx)
+{
+ delete rxtx;
+}
+
+
+}} //end rp::hal
diff --git a/LIDAR/sdk/src/arch/win32/net_serial.h b/LIDAR/sdk/src/arch/win32/net_serial.h
new file mode 100644
index 0000000..d43137e
--- /dev/null
+++ b/LIDAR/sdk/src/arch/win32/net_serial.h
@@ -0,0 +1,86 @@
+/*
+ * RPLIDAR SDK
+ *
+ * Copyright (c) 2009 - 2014 RoboPeak Team
+ * http://www.robopeak.com
+ * Copyright (c) 2014 - 2020 Shanghai Slamtec Co., Ltd.
+ * http://www.slamtec.com
+ *
+ */
+/*
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+#include "hal/abs_rxtx.h"
+
+namespace rp{ namespace arch{ namespace net{
+
+class raw_serial : public rp::hal::serial_rxtx
+{
+public:
+ enum{
+ SERIAL_RX_BUFFER_SIZE = 512,
+ SERIAL_TX_BUFFER_SIZE = 128,
+ SERIAL_RX_TIMEOUT = 2000,
+ SERIAL_TX_TIMEOUT = 2000,
+ };
+
+ raw_serial();
+ virtual ~raw_serial();
+ virtual bool bind(const char * portname, _u32 baudrate, _u32 flags = 0);
+ virtual bool open();
+ virtual void close();
+ virtual void flush( _u32 flags);
+
+ virtual int waitfordata(size_t data_count,_u32 timeout = -1, size_t * returned_size = NULL);
+
+ virtual int senddata(const unsigned char * data, size_t size);
+ virtual int recvdata(unsigned char * data, size_t size);
+
+ virtual int waitforsent(_u32 timeout = -1, size_t * returned_size = NULL);
+ virtual int waitforrecv(_u32 timeout = -1, size_t * returned_size = NULL);
+
+ virtual size_t rxqueue_count();
+
+ virtual void setDTR();
+ virtual void clearDTR();
+
+protected:
+ bool open(const char * portname, _u32 baudrate, _u32 flags);
+ void _init();
+
+ char _portName[20];
+ uint32_t _baudrate;
+ uint32_t _flags;
+
+ OVERLAPPED _ro, _wo;
+ OVERLAPPED _wait_o;
+ volatile HANDLE _serial_handle;
+ DCB _dcb;
+ COMMTIMEOUTS _co;
+};
+
+}}}
diff --git a/LIDAR/sdk/src/arch/win32/net_socket.cpp b/LIDAR/sdk/src/arch/win32/net_socket.cpp
new file mode 100644
index 0000000..611c9d1
--- /dev/null
+++ b/LIDAR/sdk/src/arch/win32/net_socket.cpp
@@ -0,0 +1,945 @@
+/*
+ * RoboPeak Project
+ * HAL Layer - Socket Interface
+ * Copyright 2009 - 2013 RoboPeak Project
+ *
+ * Win32 Implementation
+ */
+
+#define _WINSOCKAPI_
+
+#include "sdkcommon.h"
+#include "..\..\hal\socket.h"
+#include <windows.h>
+#include <winsock2.h>
+#include <ws2tcpip.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+#pragma comment (lib, "Ws2_32.lib")
+
+namespace rp{ namespace net {
+
+static volatile bool _isWSAStartupCalled = false;
+
+static inline bool _checkWSAStartup() {
+ int iResult;
+ WSADATA wsaData;
+ if (!_isWSAStartupCalled) {
+ iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
+ if (iResult != 0) {
+ return false;
+ }
+ _isWSAStartupCalled = true;
+ }
+ return true;
+}
+
+static const char* _inet_ntop(int af, const void* src, char* dst, int cnt){
+
+ struct sockaddr_storage srcaddr;
+
+
+ memset(dst, 0, cnt);
+
+ memset(&srcaddr, 0, sizeof(struct sockaddr_storage));
+
+
+ srcaddr.ss_family = af;
+
+ switch (af) {
+ case AF_INET:
+ {
+ struct sockaddr_in * ipv4 = reinterpret_cast< struct sockaddr_in *>(&srcaddr);
+ memcpy(&(ipv4->sin_addr), src, sizeof(ipv4->sin_addr));
+ }
+ break;
+ case AF_INET6:
+ {
+ struct sockaddr_in6 * ipv6 = reinterpret_cast< struct sockaddr_in6 *>(&srcaddr);
+ memcpy(&(ipv6->sin6_addr), src, sizeof(ipv6->sin6_addr));
+ }
+ break;
+ }
+
+ if (WSAAddressToStringA((struct sockaddr*) &srcaddr, sizeof(struct sockaddr_storage), 0, dst, (LPDWORD) &cnt) != 0) {
+ DWORD rv = WSAGetLastError();
+ return NULL;
+ }
+ return dst;
+}
+
+static int _inet_pton(int Family, const char * pszAddrString, void* pAddrBuf)
+{
+ struct sockaddr_storage tmpholder;
+ int actualSize = sizeof(sockaddr_storage);
+
+ int result = WSAStringToAddressA((char *)pszAddrString, Family, NULL, (sockaddr*)&tmpholder, &actualSize);
+ if (result) return -1;
+
+ switch (Family) {
+ case AF_INET:
+ {
+ struct sockaddr_in * ipv4 = reinterpret_cast< struct sockaddr_in *>(&tmpholder);
+ memcpy(pAddrBuf, &(ipv4->sin_addr), sizeof(ipv4->sin_addr));
+ }
+ break;
+ case AF_INET6:
+ {
+ struct sockaddr_in6 * ipv6 = reinterpret_cast< struct sockaddr_in6 *>(&tmpholder);
+ memcpy(pAddrBuf, &(ipv6->sin6_addr), sizeof(ipv6->sin6_addr));
+ }
+ break;
+ }
+ return 1;
+}
+
+static inline int _halAddrTypeToOSType(SocketAddress::address_type_t type)
+{
+ switch (type) {
+ case SocketAddress::ADDRESS_TYPE_INET:
+ return AF_INET;
+ case SocketAddress::ADDRESS_TYPE_INET6:
+ return AF_INET6;
+ case SocketAddress::ADDRESS_TYPE_UNSPEC:
+ return AF_UNSPEC;
+
+ default:
+ assert(!"should not reach here");
+ return AF_UNSPEC;
+ }
+}
+
+
+SocketAddress::SocketAddress()
+{
+ _checkWSAStartup();
+ _platform_data = reinterpret_cast<void *>(new sockaddr_storage);
+ memset(_platform_data, 0, sizeof(sockaddr_storage));
+
+ reinterpret_cast<sockaddr_storage *>(_platform_data)->ss_family = AF_INET;
+}
+
+SocketAddress::SocketAddress(const SocketAddress & src)
+{
+ _platform_data = reinterpret_cast<void *>(new sockaddr_storage);
+ memcpy(_platform_data, src._platform_data, sizeof(sockaddr_storage));
+}
+
+
+
+SocketAddress::SocketAddress(const char * addrString, int port, SocketAddress::address_type_t type)
+{
+ _checkWSAStartup();
+ _platform_data = reinterpret_cast<void *>(new sockaddr_storage);
+ memset(_platform_data, 0, sizeof(sockaddr_storage));
+
+ // default to ipv4 in case the following operation fails
+ reinterpret_cast<sockaddr_storage *>(_platform_data)->ss_family = AF_INET;
+
+ setAddressFromString(addrString, type);
+ setPort(port);
+}
+
+SocketAddress::SocketAddress(void * platform_data)
+ : _platform_data(platform_data)
+{ _checkWSAStartup(); }
+
+SocketAddress & SocketAddress::operator = (const SocketAddress &src)
+{
+ memcpy(_platform_data, src._platform_data, sizeof(sockaddr_storage));
+ return *this;
+}
+
+
+SocketAddress::~SocketAddress()
+{
+ delete reinterpret_cast<sockaddr_storage *>(_platform_data);
+}
+
+SocketAddress::address_type_t SocketAddress::getAddressType() const
+{
+ switch(reinterpret_cast<const sockaddr_storage *>(_platform_data)->ss_family) {
+ case AF_INET:
+ return ADDRESS_TYPE_INET;
+ case AF_INET6:
+ return ADDRESS_TYPE_INET6;
+ default:
+ assert(!"should not reach here");
+ return ADDRESS_TYPE_INET;
+ }
+}
+
+int SocketAddress::getPort() const
+{
+ switch (getAddressType()) {
+ case ADDRESS_TYPE_INET:
+ return (int)ntohs(reinterpret_cast<const sockaddr_in *>(_platform_data)->sin_port);
+ case ADDRESS_TYPE_INET6:
+ return (int)ntohs(reinterpret_cast<const sockaddr_in6 *>(_platform_data)->sin6_port);
+ default:
+ return 0;
+ }
+}
+
+u_result SocketAddress::setPort(int port)
+{
+ switch (getAddressType()) {
+ case ADDRESS_TYPE_INET:
+ reinterpret_cast<sockaddr_in *>(_platform_data)->sin_port = htons((short)port);
+ break;
+ case ADDRESS_TYPE_INET6:
+ reinterpret_cast<sockaddr_in6 *>(_platform_data)->sin6_port = htons((short)port);
+ break;
+ default:
+ return RESULT_OPERATION_FAIL;
+ }
+ return RESULT_OK;
+}
+
+u_result SocketAddress::setAddressFromString(const char * address_string, SocketAddress::address_type_t type)
+{
+ int ans = 0;
+ int prevPort = getPort();
+ switch (type) {
+ case ADDRESS_TYPE_INET:
+ reinterpret_cast<sockaddr_storage *>(_platform_data)->ss_family = AF_INET;
+ ans = _inet_pton(AF_INET,
+ address_string,
+ &reinterpret_cast<sockaddr_in *>(_platform_data)->sin_addr);
+ break;
+
+
+ case ADDRESS_TYPE_INET6:
+
+ reinterpret_cast<sockaddr_storage *>(_platform_data)->ss_family = AF_INET6;
+ ans = _inet_pton(AF_INET6,
+ address_string,
+ &reinterpret_cast<sockaddr_in6 *>(_platform_data)->sin6_addr);
+ break;
+
+ default:
+ return RESULT_INVALID_DATA;
+
+ }
+ setPort(prevPort);
+
+ return ans<=0?RESULT_INVALID_DATA:RESULT_OK;
+}
+
+
+u_result SocketAddress::getAddressAsString(char * buffer, size_t buffersize) const
+{
+ int net_family = reinterpret_cast<const sockaddr_storage *>(_platform_data)->ss_family;
+ const char *ans = NULL;
+ switch (net_family) {
+ case AF_INET:
+ ans = _inet_ntop(net_family, &reinterpret_cast<const sockaddr_in *>(_platform_data)->sin_addr,
+ buffer, (int)buffersize);
+ break;
+
+ case AF_INET6:
+ ans = _inet_ntop(net_family, &reinterpret_cast<const sockaddr_in6 *>(_platform_data)->sin6_addr,
+ buffer, (int)buffersize);
+
+ break;
+ }
+ return (ans==NULL)?RESULT_OPERATION_FAIL:RESULT_OK;
+}
+
+
+
+size_t SocketAddress::LoopUpHostName(const char * hostname, const char * sevicename, std::vector<SocketAddress> &addresspool , bool performDNS, SocketAddress::address_type_t type)
+{
+ struct addrinfo hints;
+ struct addrinfo *result;
+ int ans;
+ _checkWSAStartup();
+ memset(&hints, 0, sizeof(struct addrinfo));
+ hints.ai_family = _halAddrTypeToOSType(type);
+ hints.ai_flags = AI_PASSIVE;
+
+ if (!performDNS) {
+ hints.ai_family |= AI_NUMERICSERV | AI_NUMERICHOST;
+
+ }
+
+ ans = getaddrinfo(hostname, sevicename, &hints, &result);
+
+ addresspool.clear();
+
+ if (ans != 0) {
+ // hostname loopup failed
+ return 0;
+ }
+
+
+ for (struct addrinfo * cursor = result; cursor != NULL; cursor = cursor->ai_next) {
+ if (cursor->ai_family == ADDRESS_TYPE_INET || cursor->ai_family == ADDRESS_TYPE_INET6) {
+ sockaddr_storage * storagebuffer = new sockaddr_storage;
+ assert(sizeof(sockaddr_storage) >= cursor->ai_addrlen);
+ memcpy(storagebuffer, cursor->ai_addr, cursor->ai_addrlen);
+ addresspool.push_back(SocketAddress(storagebuffer));
+ }
+ }
+
+
+ freeaddrinfo(result);
+
+ return addresspool.size();
+}
+
+
+u_result SocketAddress::getRawAddress(_u8 * buffer, size_t bufferSize) const
+{
+ switch (getAddressType()) {
+ case ADDRESS_TYPE_INET:
+ if (bufferSize < sizeof(reinterpret_cast<const sockaddr_in *>(_platform_data)->sin_addr.s_addr)) return RESULT_INSUFFICIENT_MEMORY;
+
+ memcpy(buffer, &reinterpret_cast<const sockaddr_in *>(_platform_data)->sin_addr.s_addr, sizeof(reinterpret_cast<const sockaddr_in *>(_platform_data)->sin_addr.s_addr));
+
+
+ break;
+ case ADDRESS_TYPE_INET6:
+ if (bufferSize < sizeof(reinterpret_cast<const sockaddr_in6 *>(_platform_data)->sin6_addr.s6_addr)) return RESULT_INSUFFICIENT_MEMORY;
+ memcpy(buffer, reinterpret_cast<const sockaddr_in6 *>(_platform_data)->sin6_addr.s6_addr, sizeof(reinterpret_cast<const sockaddr_in6 *>(_platform_data)->sin6_addr.s6_addr));
+
+ break;
+ default:
+ return RESULT_OPERATION_FAIL;
+ }
+ return RESULT_OK;
+}
+
+
+void SocketAddress::setLoopbackAddress(SocketAddress::address_type_t type)
+{
+
+ int prevPort = getPort();
+ switch (type) {
+ case ADDRESS_TYPE_INET:
+ {
+ sockaddr_in * addrv4 = reinterpret_cast<sockaddr_in *>(_platform_data);
+ addrv4->sin_family = AF_INET;
+ addrv4->sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+ }
+ break;
+ case ADDRESS_TYPE_INET6:
+ {
+ sockaddr_in6 * addrv6 = reinterpret_cast<sockaddr_in6 *>(_platform_data);
+ addrv6->sin6_family = AF_INET6;
+ addrv6->sin6_addr = in6addr_loopback;
+
+ }
+ break;
+ default:
+ return;
+ }
+
+ setPort(prevPort);
+}
+
+void SocketAddress::setBroadcastAddressIPv4()
+{
+
+ int prevPort = getPort();
+ sockaddr_in * addrv4 = reinterpret_cast<sockaddr_in *>(_platform_data);
+ addrv4->sin_family = AF_INET;
+ addrv4->sin_addr.s_addr = htonl(INADDR_BROADCAST);
+ setPort(prevPort);
+
+}
+
+void SocketAddress::setAnyAddress(SocketAddress::address_type_t type)
+{
+ int prevPort = getPort();
+ switch (type) {
+ case ADDRESS_TYPE_INET:
+ {
+ sockaddr_in * addrv4 = reinterpret_cast<sockaddr_in *>(_platform_data);
+ addrv4->sin_family = AF_INET;
+ addrv4->sin_addr.s_addr = htonl(INADDR_ANY);
+ }
+ break;
+ case ADDRESS_TYPE_INET6:
+ {
+ sockaddr_in6 * addrv6 = reinterpret_cast<sockaddr_in6 *>(_platform_data);
+ addrv6->sin6_family = AF_INET6;
+ addrv6->sin6_addr = in6addr_any;
+
+ }
+ break;
+ default:
+ return;
+ }
+
+ setPort(prevPort);
+
+
+}
+
+
+}}
+
+
+
+///--------------------------------
+
+
+namespace rp { namespace arch { namespace net{
+
+using namespace rp::net;
+
+class _single_thread StreamSocketImpl : public StreamSocket
+{
+public:
+
+ StreamSocketImpl(SOCKET fd)
+ : _socket_fd(fd)
+ {
+ assert(fd>=0);
+ int bool_true = 1;
+ ::setsockopt( _socket_fd, SOL_SOCKET, SO_REUSEADDR , (char *)&bool_true, (int)sizeof(bool_true) );
+
+ enableNoDelay(true);
+ this->setTimeout(DEFAULT_SOCKET_TIMEOUT, SOCKET_DIR_BOTH);
+ }
+
+ virtual ~StreamSocketImpl()
+ {
+ closesocket(_socket_fd);
+ }
+
+ virtual void dispose()
+ {
+ delete this;
+ }
+
+
+ virtual u_result bind(const SocketAddress & localaddr)
+ {
+ const struct sockaddr * addr = reinterpret_cast<const struct sockaddr *>(localaddr.getPlatformData());
+ assert(addr);
+ int ans = ::bind(_socket_fd, addr, (int)sizeof(sockaddr_storage));
+ if (ans) {
+ return RESULT_OPERATION_FAIL;
+ } else {
+ return RESULT_OK;
+ }
+ }
+
+ virtual u_result getLocalAddress(SocketAddress & localaddr)
+ {
+ struct sockaddr * addr = reinterpret_cast<struct sockaddr *>( const_cast<void *>(localaddr.getPlatformData())); //donnot do this at home...
+ assert(addr);
+
+ int actualsize = sizeof(sockaddr_storage);
+ int ans = ::getsockname(_socket_fd, addr, &actualsize);
+
+ assert(actualsize <= sizeof(sockaddr_storage));
+ assert(addr->sa_family == AF_INET || addr->sa_family == AF_INET6);
+
+ return ans?RESULT_OPERATION_FAIL:RESULT_OK;
+ }
+
+ virtual u_result setTimeout(_u32 timeout, socket_direction_mask msk)
+ {
+ int ans;
+ timeval tv;
+ tv.tv_sec = timeout / 1000;
+ tv.tv_usec = (timeout % 1000) * 1000;
+
+ if (msk & SOCKET_DIR_RD) {
+ ans = ::setsockopt( _socket_fd, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, (int)sizeof(tv) );
+ if (ans) return RESULT_OPERATION_FAIL;
+ }
+
+ if (msk & SOCKET_DIR_WR) {
+ ans = ::setsockopt( _socket_fd, SOL_SOCKET, SO_SNDTIMEO, (char *)&tv, (int)sizeof(tv) );
+ if (ans) return RESULT_OPERATION_FAIL;
+ }
+
+ return RESULT_OK;
+ }
+
+ virtual u_result connect(const SocketAddress & pairAddress)
+ {
+ u_long mode_block = 0;
+ u_long mode_notBlock = 1;
+
+ //set to non block mode
+ if (SOCKET_ERROR == ioctlsocket(_socket_fd, (long)FIONBIO, &mode_notBlock))
+ {
+ return RESULT_OPERATION_FAIL;
+ }
+
+ struct timeval tm;
+ tm.tv_sec = 2;
+ tm.tv_usec = 0;
+ int ret = -1;
+
+ const struct sockaddr * addr = reinterpret_cast<const struct sockaddr *>(pairAddress.getPlatformData());
+ int ans = ::connect(_socket_fd, addr, (int)sizeof(sockaddr_storage));
+ if (!ans) return RESULT_OK;
+
+ fd_set set;
+ FD_ZERO(&set);
+ FD_SET(_socket_fd, &set);
+
+ if (select(-1, NULL, &set, NULL, &tm) <= 0)
+ {
+ ret = -1; // error(select error or timeout)
+ return RESULT_OPERATION_TIMEOUT;
+ }
+
+ int error = -1;
+ int optLen = sizeof(int);
+ getsockopt(_socket_fd, SOL_SOCKET, SO_ERROR, (char*)&error, &optLen);
+
+ if (0 != error)
+ {
+ ret = -1; // error
+ }
+ else
+ {
+ ret = 1; // correct
+ }
+
+ //set back to block mode
+ if (SOCKET_ERROR == ioctlsocket(_socket_fd, (long)FIONBIO, &mode_block))
+ {
+ return RESULT_OPERATION_FAIL;
+ }
+ if(1 == ret)
+ {
+ return RESULT_OK;
+ }
+ else
+ {
+ return RESULT_OPERATION_FAIL;
+ }
+ }
+
+ virtual u_result listen(int backlog)
+ {
+ int ans = ::listen( _socket_fd, backlog);
+
+ return ans?RESULT_OPERATION_FAIL:RESULT_OK;
+ }
+
+ virtual StreamSocket * accept(SocketAddress * pairAddress)
+ {
+ int addrsize;
+ addrsize = sizeof(sockaddr_storage);
+ SOCKET pair_socket = ::accept( _socket_fd, pairAddress?reinterpret_cast<struct sockaddr *>(const_cast<void *>(pairAddress->getPlatformData())):NULL
+ , &addrsize);
+
+ if (pair_socket>=0) {
+ return new StreamSocketImpl(pair_socket);
+ } else {
+ return NULL;
+ }
+ }
+
+ virtual u_result waitforIncomingConnection(_u32 timeout)
+ {
+ return waitforData(timeout);
+ }
+
+ virtual u_result send(const void * buffer, size_t len)
+ {
+ int ans = ::send( _socket_fd, (const char *)buffer, (int)len, 0);
+ if (ans != SOCKET_ERROR ) {
+ assert(ans == (int)len);
+
+ return RESULT_OK;
+ } else {
+ switch(WSAGetLastError()) {
+ case WSAETIMEDOUT:
+ return RESULT_OPERATION_TIMEOUT;
+ default:
+ return RESULT_OPERATION_FAIL;
+ }
+
+ }
+
+ }
+
+ virtual u_result recv(void *buf, size_t len, size_t & recv_len)
+ {
+ int ans = ::recv( _socket_fd, (char *)buf, (int)len, 0);
+ //::setsockopt(_socket_fd, IPPROTO_TCP, TCP_QUICKACK, (const char *)1, sizeof(int));
+ //::setsockopt(_socket_fd, IPPROTO_TCP, TCP_QUICKACK, (int[]){1}, sizeof(int))
+ if (ans == SOCKET_ERROR) {
+ recv_len = 0;
+ switch(WSAGetLastError()) {
+ case WSAETIMEDOUT:
+ return RESULT_OPERATION_TIMEOUT;
+ default:
+ return RESULT_OPERATION_FAIL;
+ }
+ } else {
+ recv_len = ans;
+ return RESULT_OK;
+ }
+ }
+
+ virtual u_result getPeerAddress(SocketAddress & peerAddr)
+ {
+ struct sockaddr * addr = reinterpret_cast<struct sockaddr *>(const_cast<void *>(peerAddr.getPlatformData())); //donnot do this at home...
+ assert(addr);
+ int actualsize = (int)sizeof(sockaddr_storage);
+ int ans = ::getpeername(_socket_fd, addr, &actualsize);
+
+ assert(actualsize <= (int)sizeof(sockaddr_storage));
+ assert(addr->sa_family == AF_INET || addr->sa_family == AF_INET6);
+
+ return ans?RESULT_OPERATION_FAIL:RESULT_OK;
+
+ }
+
+ virtual u_result shutdown(socket_direction_mask mask)
+ {
+ int shutdw_opt ;
+
+ switch (mask) {
+ case SOCKET_DIR_RD:
+ shutdw_opt = SD_RECEIVE;
+ break;
+ case SOCKET_DIR_WR:
+ shutdw_opt = SD_SEND;
+ break;
+ case SOCKET_DIR_BOTH:
+ default:
+ shutdw_opt = SD_BOTH;
+ }
+
+ int ans = ::shutdown(_socket_fd, shutdw_opt);
+ return ans?RESULT_OPERATION_FAIL:RESULT_OK;
+ }
+
+ virtual u_result enableKeepAlive(bool enable)
+ {
+ int bool_true = enable?1:0;
+ return ::setsockopt( _socket_fd, SOL_SOCKET, SO_KEEPALIVE , (const char *)&bool_true, (int)sizeof(bool_true) )?RESULT_OPERATION_FAIL:RESULT_OK;
+ }
+
+ virtual u_result enableNoDelay(bool enable )
+ {
+ int bool_true = enable?1:0;
+ return ::setsockopt( _socket_fd, IPPROTO_TCP, TCP_NODELAY, (const char *)&bool_true, (int)sizeof(bool_true) )?RESULT_OPERATION_FAIL:RESULT_OK;
+ }
+
+ virtual u_result waitforSent(_u32 timeout )
+ {
+ fd_set wrset;
+ FD_ZERO(&wrset);
+ FD_SET(_socket_fd, &wrset);
+
+ timeval tv;
+ tv.tv_sec = timeout / 1000;
+ tv.tv_usec = (timeout % 1000) * 1000;
+ int ans = ::select(NULL, NULL, &wrset, NULL, &tv);
+
+ switch (ans) {
+ case 1:
+ // fired
+ return RESULT_OK;
+ case 0:
+ // timeout
+ return RESULT_OPERATION_TIMEOUT;
+ default:
+ delay(0); //relax cpu
+ return RESULT_OPERATION_FAIL;
+ }
+ }
+
+ virtual u_result waitforData(_u32 timeout )
+ {
+ fd_set rdset;
+ FD_ZERO(&rdset);
+ FD_SET(_socket_fd, &rdset);
+
+ timeval tv;
+ tv.tv_sec = timeout / 1000;
+ tv.tv_usec = (timeout % 1000) * 1000;
+ int ans = ::select((int)_socket_fd+1, &rdset, NULL, NULL, &tv);
+
+ switch (ans) {
+ case 1:
+ // fired
+ return RESULT_OK;
+ case 0:
+ // timeout
+ return RESULT_OPERATION_TIMEOUT;
+ default:
+ delay(0); //relax cpu
+ return RESULT_OPERATION_FAIL;
+ }
+ }
+
+protected:
+
+ SOCKET _socket_fd;
+
+
+};
+
+
+class _single_thread DGramSocketImpl : public DGramSocket
+{
+public:
+
+ DGramSocketImpl(SOCKET fd)
+ : _socket_fd(fd)
+ {
+ assert(fd>=0);
+ int bool_true = 1;
+ ::setsockopt( _socket_fd, SOL_SOCKET, SO_REUSEADDR | SO_BROADCAST , (char *)&bool_true, (int)sizeof(bool_true) );
+ setTimeout(DEFAULT_SOCKET_TIMEOUT, SOCKET_DIR_BOTH);
+ }
+
+ virtual ~DGramSocketImpl()
+ {
+ closesocket(_socket_fd);
+ }
+
+ virtual void dispose()
+ {
+ delete this;
+ }
+
+
+ virtual u_result bind(const SocketAddress & localaddr)
+ {
+ const struct sockaddr * addr = reinterpret_cast<const struct sockaddr *>(localaddr.getPlatformData());
+ assert(addr);
+ int ans = ::bind(_socket_fd, addr, (int)sizeof(sockaddr_storage));
+ if (ans) {
+ return RESULT_OPERATION_FAIL;
+ } else {
+ return RESULT_OK;
+ }
+ }
+
+ virtual u_result getLocalAddress(SocketAddress & localaddr)
+ {
+ struct sockaddr * addr = reinterpret_cast<struct sockaddr *>(const_cast<void *>((localaddr.getPlatformData()))); //donnot do this at home...
+ assert(addr);
+
+ int actualsize = (int)sizeof(sockaddr_storage);
+ int ans = ::getsockname(_socket_fd, addr, &actualsize);
+
+ assert(actualsize <= (int)sizeof(sockaddr_storage));
+ assert(addr->sa_family == AF_INET || addr->sa_family == AF_INET6);
+
+ return ans?RESULT_OPERATION_FAIL:RESULT_OK;
+ }
+
+ virtual u_result setTimeout(_u32 timeout, socket_direction_mask msk)
+ {
+ int ans;
+ timeval tv;
+ tv.tv_sec = timeout / 1000;
+ tv.tv_usec = (timeout % 1000) * 1000;
+
+ if (msk & SOCKET_DIR_RD) {
+ ans = ::setsockopt( _socket_fd, SOL_SOCKET, SO_RCVTIMEO, (const char *)&tv, (int)sizeof(tv) );
+ if (ans) return RESULT_OPERATION_FAIL;
+ }
+
+ if (msk & SOCKET_DIR_WR) {
+ ans = ::setsockopt( _socket_fd, SOL_SOCKET, SO_SNDTIMEO, (const char *)&tv, (int)sizeof(tv) );
+ if (ans) return RESULT_OPERATION_FAIL;
+ }
+
+ return RESULT_OK;
+ }
+
+
+ virtual u_result waitforSent(_u32 timeout )
+ {
+ fd_set wrset;
+ FD_ZERO(&wrset);
+ FD_SET(_socket_fd, &wrset);
+
+ timeval tv;
+ tv.tv_sec = timeout / 1000;
+ tv.tv_usec = (timeout % 1000) * 1000;
+ int ans = ::select(NULL, NULL, &wrset, NULL, &tv);
+
+ switch (ans) {
+ case 1:
+ // fired
+ return RESULT_OK;
+ case 0:
+ // timeout
+ return RESULT_OPERATION_TIMEOUT;
+ default:
+ delay(0); //relax cpu
+ return RESULT_OPERATION_FAIL;
+ }
+ }
+
+ virtual u_result waitforData(_u32 timeout )
+ {
+ fd_set rdset;
+ FD_ZERO(&rdset);
+ FD_SET(_socket_fd, &rdset);
+
+ timeval tv;
+ tv.tv_sec = timeout / 1000;
+ tv.tv_usec = (timeout % 1000) * 1000;
+ int ans = ::select(NULL, &rdset, NULL, NULL, &tv);
+
+ switch (ans) {
+ case 1:
+ // fired
+ return RESULT_OK;
+ case 0:
+ // timeout
+ return RESULT_OPERATION_TIMEOUT;
+ default:
+ delay(0); //relax cpu
+ return RESULT_OPERATION_FAIL;
+ }
+ }
+
+ virtual u_result setPairAddress(const SocketAddress * pairAddress)
+ {
+ sockaddr_storage unspecAddr;
+ unspecAddr.ss_family = AF_UNSPEC;
+
+ const struct sockaddr * addr = pairAddress ? reinterpret_cast<const struct sockaddr *>(pairAddress->getPlatformData()) : reinterpret_cast<const struct sockaddr *>(&unspecAddr);
+ int ans = ::connect(_socket_fd, addr, (int)sizeof(sockaddr_storage));
+ return ans? RESULT_OPERATION_FAIL: RESULT_OK;
+
+ }
+
+ virtual u_result sendTo(const SocketAddress * target, const void * buffer, size_t len)
+ {
+
+ const struct sockaddr * addr = target?reinterpret_cast<const struct sockaddr *>(target->getPlatformData()): NULL;
+ int dest_addr_size = (target ? sizeof(sockaddr_storage) : 0);
+ int ans = ::sendto( _socket_fd, (const char *)buffer, (int)len, 0, addr, dest_addr_size);
+ if (ans != SOCKET_ERROR) {
+ assert(ans == (int)len);
+ return RESULT_OK;
+ } else {
+ switch(WSAGetLastError()) {
+ case WSAETIMEDOUT:
+ return RESULT_OPERATION_TIMEOUT;
+ case WSAEMSGSIZE:
+ return RESULT_INVALID_DATA;
+ default:
+ return RESULT_OPERATION_FAIL;
+ }
+ }
+
+ }
+
+ virtual u_result clearRxCache()
+ {
+ timeval tv;
+ tv.tv_sec = 0;
+ tv.tv_usec = 0;
+ fd_set rdset;
+ FD_ZERO(&rdset);
+ FD_SET(_socket_fd, &rdset);
+
+ int res = -1;
+ char recv_data[2];
+ memset(recv_data, 0, sizeof(recv_data));
+ while (true) {
+ res = select(FD_SETSIZE, &rdset, nullptr, nullptr, &tv);
+ if (res == 0) break;
+ recv(_socket_fd, recv_data, 1, 0);
+ }
+ return RESULT_OK;
+ }
+
+
+ virtual u_result recvFrom(void *buf, size_t len, size_t & recv_len, SocketAddress * sourceAddr)
+ {
+ struct sockaddr * addr = (sourceAddr?reinterpret_cast<struct sockaddr *>(const_cast<void *>(sourceAddr->getPlatformData())):NULL);
+ int source_addr_size = (sourceAddr?sizeof(sockaddr_storage):0);
+
+ int ans = ::recvfrom( _socket_fd, (char *)buf, (int)len, 0, addr, addr?&source_addr_size:NULL);
+ if (ans == SOCKET_ERROR) {
+ recv_len = 0;
+ int errCode = WSAGetLastError();
+ switch(errCode) {
+ case WSAETIMEDOUT:
+ return RESULT_OPERATION_TIMEOUT;
+ default:
+ return RESULT_OPERATION_FAIL;
+ }
+ } else {
+ recv_len = ans;
+ return RESULT_OK;
+ }
+
+ }
+
+
+
+protected:
+ SOCKET _socket_fd;
+
+};
+
+
+}}}
+
+
+namespace rp { namespace net{
+
+
+
+static inline int _socketHalFamilyToOSFamily(SocketBase::socket_family_t family)
+{
+ switch (family) {
+ case SocketBase::SOCKET_FAMILY_INET:
+ return AF_INET;
+ case SocketBase::SOCKET_FAMILY_INET6:
+ return AF_INET6;
+ case SocketBase::SOCKET_FAMILY_RAW:
+ return AF_UNSPEC; //win32 doesn't support RAW Packet
+ default:
+ assert(!"should not reach here");
+ return AF_INET; // force treating as IPv4 in release mode
+ }
+
+}
+
+StreamSocket * StreamSocket::CreateSocket(SocketBase::socket_family_t family)
+{
+ _checkWSAStartup();
+ if (family == SOCKET_FAMILY_RAW) return NULL;
+
+
+ int socket_family = _socketHalFamilyToOSFamily(family);
+ SOCKET socket_fd = ::socket(socket_family, SOCK_STREAM, 0);
+ if (socket_fd == -1) return NULL;
+ StreamSocket * newborn = static_cast<StreamSocket *>(new rp::arch::net::StreamSocketImpl(socket_fd));
+ return newborn;
+
+}
+
+
+DGramSocket * DGramSocket::CreateSocket(SocketBase::socket_family_t family)
+{
+ _checkWSAStartup();
+ int socket_family = _socketHalFamilyToOSFamily(family);
+
+
+ SOCKET socket_fd = ::socket(socket_family, (family == SOCKET_FAMILY_RAW) ? SOCK_RAW : SOCK_DGRAM, 0);
+ if (socket_fd == -1) return NULL;
+ DGramSocket * newborn = static_cast<DGramSocket *>(new rp::arch::net::DGramSocketImpl(socket_fd));
+ return newborn;
+
+}
+
+
+}}
+
diff --git a/LIDAR/sdk/src/arch/win32/timer.cpp b/LIDAR/sdk/src/arch/win32/timer.cpp
new file mode 100644
index 0000000..d153cc4
--- /dev/null
+++ b/LIDAR/sdk/src/arch/win32/timer.cpp
@@ -0,0 +1,72 @@
+/*
+ * RPLIDAR SDK
+ *
+ * Copyright (c) 2009 - 2014 RoboPeak Team
+ * http://www.robopeak.com
+ * Copyright (c) 2014 - 2020 Shanghai Slamtec Co., Ltd.
+ * http://www.slamtec.com
+ *
+ */
+/*
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include "sdkcommon.h"
+#include <mmsystem.h>
+#pragma comment(lib, "Winmm.lib")
+
+namespace rp{ namespace arch{
+
+static LARGE_INTEGER _current_freq;
+
+void HPtimer_reset()
+{
+ BOOL ans=QueryPerformanceFrequency(&_current_freq);
+ _current_freq.QuadPart/=1000ULL;
+ assert(ans);
+}
+
+_u64 getHDTimer_us()
+{
+ LARGE_INTEGER current;
+ QueryPerformanceCounter(&current);
+
+ return (_u64)(current.QuadPart / (_current_freq.QuadPart/1000ULL));
+
+}
+
+_u64 getHDTimer()
+{
+ LARGE_INTEGER current;
+ QueryPerformanceCounter(&current);
+
+ return (_u64)(current.QuadPart/_current_freq.QuadPart);
+}
+
+BEGIN_STATIC_CODE(timer_cailb)
+{
+ HPtimer_reset();
+}END_STATIC_CODE(timer_cailb)
+
+}}
diff --git a/LIDAR/sdk/src/arch/win32/timer.h b/LIDAR/sdk/src/arch/win32/timer.h
new file mode 100644
index 0000000..27b7a76
--- /dev/null
+++ b/LIDAR/sdk/src/arch/win32/timer.h
@@ -0,0 +1,49 @@
+/*
+ * RPLIDAR SDK
+ *
+ * Copyright (c) 2009 - 2014 RoboPeak Team
+ * http://www.robopeak.com
+ * Copyright (c) 2014 - 2020 Shanghai Slamtec Co., Ltd.
+ * http://www.slamtec.com
+ *
+ */
+/*
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+#include "hal/types.h"
+
+#define delay(x) ::Sleep(x)
+
+namespace rp{ namespace arch{
+ void HPtimer_reset();
+ _u64 getHDTimer();
+ _u64 getHDTimer_us();
+
+}}
+
+#define getms() rp::arch::getHDTimer()
+#define getus() rp::arch::getHDTimer_us()
diff --git a/LIDAR/sdk/src/arch/win32/winthread.hpp b/LIDAR/sdk/src/arch/win32/winthread.hpp
new file mode 100644
index 0000000..590794d
--- /dev/null
+++ b/LIDAR/sdk/src/arch/win32/winthread.hpp
@@ -0,0 +1,144 @@
+/*
+ * RPLIDAR SDK
+ *
+ * Copyright (c) 2009 - 2014 RoboPeak Team
+ * http://www.robopeak.com
+ * Copyright (c) 2014 - 2020 Shanghai Slamtec Co., Ltd.
+ * http://www.slamtec.com
+ *
+ */
+/*
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include "sdkcommon.h"
+#include <process.h>
+
+namespace rp{ namespace hal{
+
+Thread Thread::create(thread_proc_t proc, void * data)
+{
+ Thread newborn(proc, data);
+
+ newborn._handle = (_word_size_t)(
+ _beginthreadex(NULL, 0, (unsigned int (_stdcall * )( void * ))proc,
+ data, 0, NULL));
+ return newborn;
+}
+
+u_result Thread::terminate()
+{
+ if (!this->_handle) return RESULT_OK;
+ if (TerminateThread( reinterpret_cast<HANDLE>(this->_handle), -1))
+ {
+ CloseHandle(reinterpret_cast<HANDLE>(this->_handle));
+ this->_handle = NULL;
+ return RESULT_OK;
+ }else
+ {
+ return RESULT_OPERATION_FAIL;
+ }
+}
+
+u_result Thread::SetSelfPriority( priority_val_t p)
+{
+ HANDLE selfHandle = GetCurrentThread();
+
+ int win_priority = THREAD_PRIORITY_NORMAL;
+ switch(p)
+ {
+ case PRIORITY_REALTIME:
+ win_priority = THREAD_PRIORITY_TIME_CRITICAL;
+ break;
+ case PRIORITY_HIGH:
+ win_priority = THREAD_PRIORITY_HIGHEST;
+ break;
+ case PRIORITY_NORMAL:
+ win_priority = THREAD_PRIORITY_NORMAL;
+ break;
+ case PRIORITY_LOW:
+ win_priority = THREAD_PRIORITY_LOWEST;
+ break;
+ case PRIORITY_IDLE:
+ win_priority = THREAD_PRIORITY_IDLE;
+ break;
+ }
+
+ if (SetThreadPriority(selfHandle, win_priority))
+ {
+ return RESULT_OK;
+ }
+ return RESULT_OPERATION_FAIL;
+}
+
+Thread::priority_val_t Thread::getPriority()
+{
+ if (!this->_handle) return PRIORITY_NORMAL;
+ int win_priority = ::GetThreadPriority(reinterpret_cast<HANDLE>(this->_handle));
+
+ if (win_priority == THREAD_PRIORITY_ERROR_RETURN)
+ {
+ return PRIORITY_NORMAL;
+ }
+
+ if (win_priority >= THREAD_PRIORITY_TIME_CRITICAL )
+ {
+ return PRIORITY_REALTIME;
+ }
+ else if (win_priority<THREAD_PRIORITY_TIME_CRITICAL && win_priority>=THREAD_PRIORITY_ABOVE_NORMAL)
+ {
+ return PRIORITY_HIGH;
+ }
+ else if (win_priority<THREAD_PRIORITY_ABOVE_NORMAL && win_priority>THREAD_PRIORITY_BELOW_NORMAL)
+ {
+ return PRIORITY_NORMAL;
+ }else if (win_priority<=THREAD_PRIORITY_BELOW_NORMAL && win_priority>THREAD_PRIORITY_IDLE)
+ {
+ return PRIORITY_LOW;
+ }else if (win_priority<=THREAD_PRIORITY_IDLE)
+ {
+ return PRIORITY_IDLE;
+ }
+ return PRIORITY_NORMAL;
+}
+
+u_result Thread::join(unsigned long timeout)
+{
+ if (!this->_handle) return RESULT_OK;
+ switch ( WaitForSingleObject(reinterpret_cast<HANDLE>(this->_handle), timeout))
+ {
+ case WAIT_OBJECT_0:
+ CloseHandle(reinterpret_cast<HANDLE>(this->_handle));
+ this->_handle = NULL;
+ return RESULT_OK;
+ case WAIT_ABANDONED:
+ return RESULT_OPERATION_FAIL;
+ case WAIT_TIMEOUT:
+ return RESULT_OPERATION_TIMEOUT;
+ }
+
+ return RESULT_OK;
+}
+
+}}