From 6e1a010a72880ae9b4aedced53591249a098a2fd Mon Sep 17 00:00:00 2001 From: Christopher Kohlhoff Date: Sun, 4 Nov 2007 21:25:49 +0000 Subject: [PATCH] Some changes to enable support for WinCE. [SVN r40759] --- include/boost/asio/detail/socket_ops.hpp | 156 +++++++++++++++--- include/boost/asio/detail/socket_types.hpp | 4 +- include/boost/asio/detail/thread.hpp | 10 +- .../asio/detail/win_iocp_io_service_fwd.hpp | 2 + include/boost/asio/detail/win_thread.hpp | 4 +- include/boost/asio/detail/win_tss_ptr.hpp | 8 +- include/boost/asio/detail/wince_thread.hpp | 126 ++++++++++++++ .../boost/asio/ip/detail/socket_option.hpp | 17 +- 8 files changed, 298 insertions(+), 29 deletions(-) create mode 100644 include/boost/asio/detail/wince_thread.hpp diff --git a/include/boost/asio/detail/socket_ops.hpp b/include/boost/asio/detail/socket_ops.hpp index 3df37c16..352d1b1d 100644 --- a/include/boost/asio/detail/socket_ops.hpp +++ b/include/boost/asio/detail/socket_ops.hpp @@ -101,6 +101,10 @@ inline socket_type accept(socket_type s, socket_addr_type* addr, } #endif +#if defined(BOOST_WINDOWS) && defined(UNDER_CE) + clear_error(ec); +#endif + return new_s; } @@ -115,14 +119,25 @@ inline int bind(socket_type s, const socket_addr_type* addr, std::size_t addrlen, boost::system::error_code& ec) { clear_error(ec); - return error_wrapper(call_bind(&msghdr::msg_namelen, s, addr, addrlen), ec); + int result = error_wrapper(call_bind( + &msghdr::msg_namelen, s, addr, addrlen), ec); +#if defined(BOOST_WINDOWS) && defined(UNDER_CE) + if (result == 0) + clear_error(ec); +#endif + return result; } inline int close(socket_type s, boost::system::error_code& ec) { clear_error(ec); #if defined(BOOST_WINDOWS) || defined(__CYGWIN__) - return error_wrapper(::closesocket(s), ec); + int result = error_wrapper(::closesocket(s), ec); +# if defined(UNDER_CE) + if (result == 0) + clear_error(ec); +# endif + return result; #else // defined(BOOST_WINDOWS) || defined(__CYGWIN__) return error_wrapper(::close(s), ec); #endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__) @@ -131,7 +146,12 @@ inline int close(socket_type s, boost::system::error_code& ec) inline int shutdown(socket_type s, int what, boost::system::error_code& ec) { clear_error(ec); - return error_wrapper(::shutdown(s, what), ec); + int result = error_wrapper(::shutdown(s, what), ec); +#if defined(BOOST_WINDOWS) && defined(UNDER_CE) + if (result == 0) + clear_error(ec); +#endif + return result; } template @@ -145,14 +165,24 @@ inline int connect(socket_type s, const socket_addr_type* addr, std::size_t addrlen, boost::system::error_code& ec) { clear_error(ec); - return error_wrapper(call_connect( + int result = error_wrapper(call_connect( &msghdr::msg_namelen, s, addr, addrlen), ec); +#if defined(BOOST_WINDOWS) && defined(UNDER_CE) + if (result == 0) + clear_error(ec); +#endif + return result; } inline int listen(socket_type s, int backlog, boost::system::error_code& ec) { clear_error(ec); - return error_wrapper(::listen(s, backlog), ec); + int result = error_wrapper(::listen(s, backlog), ec); +#if defined(BOOST_WINDOWS) && defined(UNDER_CE) + if (result == 0) + clear_error(ec); +#endif + return result; } #if defined(BOOST_WINDOWS) || defined(__CYGWIN__) @@ -218,6 +248,9 @@ inline int recv(socket_type s, buf* bufs, size_t count, int flags, recv_buf_count, &bytes_transferred, &recv_flags, 0, 0), ec); if (result != 0) return -1; +# if defined(UNDER_CE) + clear_error(ec); +# endif return bytes_transferred; #else // defined(BOOST_WINDOWS) || defined(__CYGWIN__) msghdr msg = msghdr(); @@ -243,6 +276,9 @@ inline int recvfrom(socket_type s, buf* bufs, size_t count, int flags, *addrlen = (std::size_t)tmp_addrlen; if (result != 0) return -1; +# if defined(UNDER_CE) + clear_error(ec); +# endif return bytes_transferred; #else // defined(BOOST_WINDOWS) || defined(__CYGWIN__) msghdr msg = msghdr(); @@ -269,6 +305,9 @@ inline int send(socket_type s, const buf* bufs, size_t count, int flags, send_buf_count, &bytes_transferred, send_flags, 0, 0), ec); if (result != 0) return -1; +# if defined(UNDER_CE) + clear_error(ec); +# endif return bytes_transferred; #else // defined(BOOST_WINDOWS) || defined(__CYGWIN__) msghdr msg = msghdr(); @@ -291,9 +330,13 @@ inline int sendto(socket_type s, const buf* bufs, size_t count, int flags, DWORD send_buf_count = static_cast(count); DWORD bytes_transferred = 0; int result = error_wrapper(::WSASendTo(s, const_cast(bufs), - send_buf_count, &bytes_transferred, flags, addr, addrlen, 0, 0), ec); + send_buf_count, &bytes_transferred, flags, addr, + static_cast(addrlen), 0, 0), ec); if (result != 0) return -1; +# if defined(UNDER_CE) + clear_error(ec); +# endif return bytes_transferred; #else // defined(BOOST_WINDOWS) || defined(__CYGWIN__) msghdr msg = msghdr(); @@ -328,6 +371,10 @@ inline socket_type socket(int af, int type, int protocol, reinterpret_cast(&optval), sizeof(optval)); } +# if defined(UNDER_CE) + clear_error(ec); +# endif + return s; #elif defined(__MACH__) && defined(__APPLE__) || defined(__FreeBSD__) socket_type s = error_wrapper(::socket(af, type, protocol), ec); @@ -386,8 +433,13 @@ inline int setsockopt(socket_type s, int level, int optname, return -1; #else // defined(__BORLANDC__) clear_error(ec); - return error_wrapper(call_setsockopt(&msghdr::msg_namelen, + int result = error_wrapper(call_setsockopt(&msghdr::msg_namelen, s, level, optname, optval, optlen), ec); +# if defined(BOOST_WINDOWS) && defined(UNDER_CE) + if (result == 0) + clear_error(ec); +# endif + return result; #endif // defined(__BORLANDC__) } @@ -456,6 +508,10 @@ inline int getsockopt(socket_type s, int level, int optname, void* optval, *static_cast(optval) = 1; clear_error(ec); } +# if defined(UNDER_CE) + if (result == 0) + clear_error(ec); +# endif return result; #else // defined(BOOST_WINDOWS) || defined(__CYGWIN__) clear_error(ec); @@ -491,8 +547,13 @@ inline int getpeername(socket_type s, socket_addr_type* addr, std::size_t* addrlen, boost::system::error_code& ec) { clear_error(ec); - return error_wrapper(call_getpeername( + int result = error_wrapper(call_getpeername( &msghdr::msg_namelen, s, addr, addrlen), ec); +#if defined(BOOST_WINDOWS) && defined(UNDER_CE) + if (result == 0) + clear_error(ec); +#endif + return result; } template @@ -509,8 +570,13 @@ inline int getsockname(socket_type s, socket_addr_type* addr, std::size_t* addrlen, boost::system::error_code& ec) { clear_error(ec); - return error_wrapper(call_getsockname( + int result = error_wrapper(call_getsockname( &msghdr::msg_namelen, s, addr, addrlen), ec); +#if defined(BOOST_WINDOWS) && defined(UNDER_CE) + if (result == 0) + clear_error(ec); +#endif + return result; } inline int ioctl(socket_type s, long cmd, ioctl_arg_type* arg, @@ -518,7 +584,12 @@ inline int ioctl(socket_type s, long cmd, ioctl_arg_type* arg, { clear_error(ec); #if defined(BOOST_WINDOWS) || defined(__CYGWIN__) - return error_wrapper(::ioctlsocket(s, cmd, arg), ec); + int result = error_wrapper(::ioctlsocket(s, cmd, arg), ec); +# if defined(UNDER_CE) + if (result == 0) + clear_error(ec); +# endif + return result; #else // defined(BOOST_WINDOWS) || defined(__CYGWIN__) return error_wrapper(::ioctl(s, cmd, arg), ec); #endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__) @@ -557,8 +628,13 @@ inline int select(int nfds, fd_set* readfds, fd_set* writefds, return error_wrapper(::pselect(nfds, readfds, writefds, exceptfds, timeout ? &ts : 0, 0), ec); #else - return error_wrapper(::select(nfds, readfds, + int result = error_wrapper(::select(nfds, readfds, writefds, exceptfds, timeout), ec); +# if defined(BOOST_WINDOWS) && defined(UNDER_CE) + if (result >= 0) + clear_error(ec); +# endif + return result; #endif } @@ -569,7 +645,12 @@ inline int poll_read(socket_type s, boost::system::error_code& ec) FD_ZERO(&fds); FD_SET(s, &fds); clear_error(ec); - return error_wrapper(::select(s, &fds, 0, 0, 0), ec); + int result = error_wrapper(::select(s, &fds, 0, 0, 0), ec); +# if defined(UNDER_CE) + if (result >= 0) + clear_error(ec); +# endif + return result; #else // defined(BOOST_WINDOWS) || defined(__CYGWIN__) pollfd fds; fds.fd = s; @@ -587,7 +668,12 @@ inline int poll_write(socket_type s, boost::system::error_code& ec) FD_ZERO(&fds); FD_SET(s, &fds); clear_error(ec); - return error_wrapper(::select(s, 0, &fds, 0, 0), ec); + int result = error_wrapper(::select(s, 0, &fds, 0, 0), ec); +# if defined(UNDER_CE) + if (result >= 0) + clear_error(ec); +# endif + return result; #else // defined(BOOST_WINDOWS) || defined(__CYGWIN__) pollfd fds; fds.fd = s; @@ -635,9 +721,17 @@ inline const char* inet_ntop(int af, const void* src, char* dest, size_t length, } DWORD string_length = static_cast(length); +#if defined(BOOST_NO_ANSI_APIS) + LPWSTR string_buffer = (LPWSTR)_alloca(length * sizeof(WCHAR)); + int result = error_wrapper(::WSAAddressToStringW( + reinterpret_cast(&address), + address_length, 0, string_buffer, &string_length), ec); + ::WideCharToMultiByte(CP_ACP, 0, string_buffer, -1, dest, length, 0, 0); +#else int result = error_wrapper(::WSAAddressToStringA( reinterpret_cast(&address), address_length, 0, dest, &string_length), ec); +#endif // Windows may set error code on success. if (result != socket_error_retval) @@ -681,10 +775,20 @@ inline int inet_pton(int af, const char* src, void* dest, sockaddr_storage_type address; int address_length = sizeof(sockaddr_storage_type); +#if defined(BOOST_NO_ANSI_APIS) + int num_wide_chars = strlen(src) + 1; + LPWSTR wide_buffer = (LPWSTR)_alloca(num_wide_chars * sizeof(WCHAR)); + ::MultiByteToWideChar(CP_ACP, 0, src, -1, wide_buffer, num_wide_chars); + int result = error_wrapper(::WSAStringToAddressW( + wide_buffer, af, 0, + reinterpret_cast(&address), + &address_length), ec); +#else int result = error_wrapper(::WSAStringToAddressA( const_cast(src), af, 0, reinterpret_cast(&address), &address_length), ec); +#endif if (af == AF_INET) { @@ -718,6 +822,11 @@ inline int inet_pton(int af, const char* src, void* dest, if (result == socket_error_retval && !ec) ec = boost::asio::error::invalid_argument; +#if defined(UNDER_CE) + if (result != socket_error_retval) + clear_error(ec); +#endif + return result == socket_error_retval ? -1 : 1; #else // defined(BOOST_WINDOWS) || defined(__CYGWIN__) int result = error_wrapper(::inet_pton(af, src, dest), ec); @@ -744,7 +853,12 @@ inline int inet_pton(int af, const char* src, void* dest, inline int gethostname(char* name, int namelen, boost::system::error_code& ec) { clear_error(ec); - return error_wrapper(::gethostname(name, namelen), ec); + int result = error_wrapper(::gethostname(name, namelen), ec); +#if defined(BOOST_WINDOWS) && defined(UNDER_CE) + if (result == 0) + clear_error(ec); +#endif + return result; } #if defined(BOOST_WINDOWS) || defined(__CYGWIN__) \ @@ -783,6 +897,9 @@ inline hostent* gethostbyaddr(const char* addr, int length, int af, hostent* retval = error_wrapper(::gethostbyaddr(addr, length, af), ec); if (!retval) return 0; +# if defined(UNDER_CE) + clear_error(ec); +# endif *result = *retval; return retval; #elif defined(__sun) || defined(__QNX__) @@ -831,6 +948,9 @@ inline hostent* gethostbyname(const char* name, int af, struct hostent* result, hostent* retval = error_wrapper(::gethostbyname(name), ec); if (!retval) return 0; +# if defined(UNDER_CE) + clear_error(ec); +# endif *result = *retval; return result; #elif defined(__sun) || defined(__QNX__) @@ -1616,7 +1736,7 @@ inline boost::system::error_code getaddrinfo(const char* host, { clear_error(ec); #if defined(BOOST_WINDOWS) || defined(__CYGWIN__) -# if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0501) +# if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0501) || defined(UNDER_CE) // Building for Windows XP, Windows Server 2003, or later. int error = ::getaddrinfo(host, service, hints, result); return ec = translate_addrinfo_error(error); @@ -1647,7 +1767,7 @@ inline boost::system::error_code getaddrinfo(const char* host, inline void freeaddrinfo(addrinfo_type* ai) { #if defined(BOOST_WINDOWS) || defined(__CYGWIN__) -# if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0501) +# if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0501) || defined(UNDER_CE) // Building for Windows XP, Windows Server 2003, or later. ::freeaddrinfo(ai); # else @@ -1675,7 +1795,7 @@ inline boost::system::error_code getnameinfo(const socket_addr_type* addr, char* serv, std::size_t servlen, int flags, boost::system::error_code& ec) { #if defined(BOOST_WINDOWS) || defined(__CYGWIN__) -# if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0501) +# if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0501) || defined(UNDER_CE) // Building for Windows XP, Windows Server 2003, or later. clear_error(ec); int error = ::getnameinfo(addr, addrlen, host, static_cast(hostlen), @@ -1739,8 +1859,6 @@ inline u_short_type host_to_network_short(u_short_type value) } // namespace asio } // namespace boost -#undef BOOST_ASIO_SOCKET_CALL - #include #endif // BOOST_ASIO_DETAIL_SOCKET_OPS_HPP diff --git a/include/boost/asio/detail/socket_types.hpp b/include/boost/asio/detail/socket_types.hpp index 124aff5c..26535b86 100644 --- a/include/boost/asio/detail/socket_types.hpp +++ b/include/boost/asio/detail/socket_types.hpp @@ -80,7 +80,9 @@ # undef BOOST_ASIO_WSPIAPI_H_DEFINED # endif // defined(BOOST_ASIO_WSPIAPI_H_DEFINED) # if !defined(BOOST_ASIO_NO_DEFAULT_LINKED_LIBS) -# if defined(_MSC_VER) || defined(__BORLANDC__) +# if defined(UNDER_CE) +# pragma comment(lib, "ws2.lib") +# elif defined(_MSC_VER) || defined(__BORLANDC__) # pragma comment(lib, "ws2_32.lib") # pragma comment(lib, "mswsock.lib") # endif // defined(_MSC_VER) || defined(__BORLANDC__) diff --git a/include/boost/asio/detail/thread.hpp b/include/boost/asio/detail/thread.hpp index 02b2df39..4ec585e7 100644 --- a/include/boost/asio/detail/thread.hpp +++ b/include/boost/asio/detail/thread.hpp @@ -24,7 +24,11 @@ #if !defined(BOOST_HAS_THREADS) # include #elif defined(BOOST_WINDOWS) -# include +# if defined(UNDER_CE) +# include +# else +# include +# endif #elif defined(BOOST_HAS_PTHREADS) # include #else @@ -38,7 +42,11 @@ namespace detail { #if !defined(BOOST_HAS_THREADS) typedef null_thread thread; #elif defined(BOOST_WINDOWS) +# if defined(UNDER_CE) +typedef wince_thread thread; +# else typedef win_thread thread; +# endif #elif defined(BOOST_HAS_PTHREADS) typedef posix_thread thread; #endif diff --git a/include/boost/asio/detail/win_iocp_io_service_fwd.hpp b/include/boost/asio/detail/win_iocp_io_service_fwd.hpp index d126c32a..6f7e57b4 100644 --- a/include/boost/asio/detail/win_iocp_io_service_fwd.hpp +++ b/include/boost/asio/detail/win_iocp_io_service_fwd.hpp @@ -27,6 +27,7 @@ #if !defined(BOOST_ASIO_DISABLE_IOCP) #if defined(BOOST_WINDOWS) || defined(__CYGWIN__) #if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0400) +#if !defined(UNDER_CE) // Define this to indicate that IOCP is supported on the target platform. #define BOOST_ASIO_HAS_IOCP 1 @@ -41,6 +42,7 @@ class win_iocp_io_service; } // namespace asio } // namespace boost +#endif // !defined(UNDER_CE) #endif // defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0400) #endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__) #endif // !defined(BOOST_ASIO_DISABLE_IOCP) diff --git a/include/boost/asio/detail/win_thread.hpp b/include/boost/asio/detail/win_thread.hpp index b838ce78..97bbeb7c 100644 --- a/include/boost/asio/detail/win_thread.hpp +++ b/include/boost/asio/detail/win_thread.hpp @@ -22,7 +22,7 @@ #include #include -#if defined(BOOST_WINDOWS) +#if defined(BOOST_WINDOWS) && !defined(UNDER_CE) #include #include @@ -120,7 +120,7 @@ inline unsigned int __stdcall win_thread_function(void* arg) } // namespace asio } // namespace boost -#endif // defined(BOOST_WINDOWS) +#endif // defined(BOOST_WINDOWS) && !defined(UNDER_CE) #include diff --git a/include/boost/asio/detail/win_tss_ptr.hpp b/include/boost/asio/detail/win_tss_ptr.hpp index 32144540..7d578fce 100644 --- a/include/boost/asio/detail/win_tss_ptr.hpp +++ b/include/boost/asio/detail/win_tss_ptr.hpp @@ -41,11 +41,17 @@ class win_tss_ptr : private noncopyable { public: +#if defined(UNDER_CE) + enum { out_of_indexes = 0xFFFFFFFF }; +#else + enum { out_of_indexes = TLS_OUT_OF_INDEXES }; +#endif + // Constructor. win_tss_ptr() { tss_key_ = ::TlsAlloc(); - if (tss_key_ == TLS_OUT_OF_INDEXES) + if (tss_key_ == out_of_indexes) { DWORD last_error = ::GetLastError(); boost::system::system_error e( diff --git a/include/boost/asio/detail/wince_thread.hpp b/include/boost/asio/detail/wince_thread.hpp new file mode 100644 index 00000000..99aeadfe --- /dev/null +++ b/include/boost/asio/detail/wince_thread.hpp @@ -0,0 +1,126 @@ +// +// wince_thread.hpp +// ~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2007 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_WINCE_THREAD_HPP +#define BOOST_ASIO_DETAIL_WINCE_THREAD_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include +#include + +#if defined(BOOST_WINDOWS) && defined(UNDER_CE) + +#include +#include +#include + +#include +#include +#include +#include + +namespace boost { +namespace asio { +namespace detail { + +DWORD WINAPI wince_thread_function(LPVOID arg); + +class wince_thread + : private noncopyable +{ +public: + // Constructor. + template + wince_thread(Function f) + { + std::auto_ptr arg(new func(f)); + DWORD thread_id = 0; + thread_ = ::CreateThread(0, 0, wince_thread_function, + arg.get(), 0, &thread_id); + if (!thread_) + { + DWORD last_error = ::GetLastError(); + boost::system::system_error e( + boost::system::error_code(last_error, + boost::asio::error::system_category), + "thread"); + boost::throw_exception(e); + } + arg.release(); + } + + // Destructor. + ~wince_thread() + { + ::CloseHandle(thread_); + } + + // Wait for the thread to exit. + void join() + { + ::WaitForSingleObject(thread_, INFINITE); + } + +private: + friend DWORD WINAPI wince_thread_function(LPVOID arg); + + class func_base + { + public: + virtual ~func_base() {} + virtual void run() = 0; + }; + + template + class func + : public func_base + { + public: + func(Function f) + : f_(f) + { + } + + virtual void run() + { + f_(); + } + + private: + Function f_; + }; + + ::HANDLE thread_; +}; + +inline DWORD WINAPI wince_thread_function(LPVOID arg) +{ + std::auto_ptr func( + static_cast(arg)); + func->run(); + return 0; +} + +} // namespace detail +} // namespace asio +} // namespace boost + +#endif // defined(BOOST_WINDOWS) && defined(UNDER_CE) + +#include + +#endif // BOOST_ASIO_DETAIL_WINCE_THREAD_HPP diff --git a/include/boost/asio/ip/detail/socket_option.hpp b/include/boost/asio/ip/detail/socket_option.hpp index 2f538cc9..980c5746 100644 --- a/include/boost/asio/ip/detail/socket_option.hpp +++ b/include/boost/asio/ip/detail/socket_option.hpp @@ -253,6 +253,13 @@ template class multicast_hops { public: +#if defined(BOOST_WINDOWS) && defined(UNDER_CE) + typedef int ipv4_value_type; +#else + typedef unsigned char ipv4_value_type; +#endif + typedef int ipv6_value_type; + // Default constructor. multicast_hops() : ipv4_value_(0), @@ -265,7 +272,7 @@ public: { if (v < 0 || v > 255) throw std::out_of_range("multicast hops value out of range"); - ipv4_value_ = static_cast(v); + ipv4_value_ = (ipv4_value_type)v; ipv6_value_ = v; } @@ -274,7 +281,7 @@ public: { if (v < 0 || v > 255) throw std::out_of_range("multicast hops value out of range"); - ipv4_value_ = static_cast(v); + ipv4_value_ = (ipv4_value_type)v; ipv6_value_ = v; return *this; } @@ -343,7 +350,7 @@ public: else if (ipv6_value_ > 255) ipv4_value_ = 255; else - ipv4_value_ = static_cast(ipv6_value_); + ipv4_value_ = (ipv4_value_type)ipv6_value_; } else { @@ -354,8 +361,8 @@ public: } private: - unsigned char ipv4_value_; - int ipv6_value_; + ipv4_value_type ipv4_value_; + ipv6_value_type ipv6_value_; }; // Helper template for implementing ip_mreq-based options.