Boost logo

Boost Users :

From: Klebsch, Mario (Mario.Klebsch_at_[hidden])
Date: 2019-12-20 10:02:07


Hello,

I am using boost asio in a cross platform project. The project consists of two libraries, having a C call API in between.

Until now, each of those two libraries uses boost::asio internally. Each of these libraries have their own instance of boost::asio::io_service.

I now need to implement a change, that requires to pass a connected socket from one library to the other one via the C call API:

This is what I want to do it.

* Lib1 calls new method connect() in lib2
* lib2::connect() creates a boost::asio::ip::tcp::socket
* lib2::connect() connects to a service
* lib2::connect() does some async communication with that service.
* when the service is initialized, lib2::connect() shall
   pass the native handle back to its caller (Lib1).
* Lib1 then creates a boost::asio::ip::tcp::socket from the native handle

I have learned, that there is no way to destroy a boost::asio::ip::tcp::socket without closing the native handle.

So, I have to dup() it. No problem on POSIX systems, on Windows I can use a combination of WSADuplicateSocket () and WSASocket () to achieve the same.

Everything works fine on Linux, but on Windows, the parts do not work together :)

The individual parts are working find.
* I can use the boost::asio::ip::tcp::socket to communicate with the service.
* I can use WSADuplicateSocket () and WSASocket () to get a 2nd, native handle to the socket
* I can use the 2nd, native handle to communicate to the service, even after destroying the boost::asio::ip::tcp::socket instance.
* I also can create a working boost::asio::ip::tcp::socket from a native socket handle, created with socket() and connected to a service with connect().

BUT: If I try to create a boost::asio::ip::tcp::socket on the socket created by the WSADuplicateSocket () and WSASocket () sequence, I get an exception.

The call to CreateIoCompletionPort() in win_iocp_io_service.ipp, win_iocp_io_service::register_handle() fails with error 87 (Invalid Parameter).

I have no idea, why CreateIoCompletionPort() is failing and how to avoid this.

Here is a sample program demonstrating my problem. If BUG is #defined, the code fails with std::exception "assign: Falscher Parameter" (invalid parameter).

#ifdef _WIN32
#include <winsock2.h>
#include <ws2tcpip.h>
#else
#include <sys/socket.h>
#endif

#include <boost/asio.hpp>

#define ADDR "127.0.0.1"
#define PORT "7" /* echo */

#include <stdio.h>

#ifndef _WIN32
inline int WSAGetLastError() { return errno; }
#endif

int main()
{
       char Request[]="Hello";
       char Buffer[256];
       int n;

       try
       {
#ifdef _WIN32
             SOCKET s1 = INVALID_SOCKET;
#else
             int s1=-1;
#endif
#ifdef BUG
             {
                    printf("The programm does not work with this code on windows :-(\n");
                    boost::asio::io_service IoService;
                    boost::asio::ip::tcp::resolver Resolver(IoService);
                    boost::asio::ip::tcp::resolver::query Query(ADDR, PORT);
                    boost::asio::ip::tcp::socket s(IoService);
                    s.connect(*Resolver.resolve(Query));
                    printf("connected\n");

#ifdef _WIN32
                    WSAPROTOCOL_INFO ProtocolInfo;
                    DWORD MyProcId = GetCurrentProcessId();
                    int x = WSADuplicateSocket((SOCKET)s.native_handle(), MyProcId, &ProtocolInfo);
                    if (x)
                           throw boost::system::error_code(WSAGetLastError(), boost::system::system_category());

                    s1 = WSASocket(FROM_PROTOCOL_INFO, FROM_PROTOCOL_INFO, FROM_PROTOCOL_INFO, &ProtocolInfo, 0, WSA_FLAG_OVERLAPPED);
#else /* !_WIN32 */
                    s1=dup(s.native_handle());
#endif /* !_WIN32 */
                    if (s1<0)
                           throw boost::system::error_code(WSAGetLastError(), boost::system::system_category());
             }
#else
             s1 = socket(PF_INET, SOCK_STREAM, 0);
             if (s1 < 0)
                    throw boost::system::error_code(WSAGetLastError(), boost::system::system_category());
             struct sockaddr_in Addr;
             Addr.sin_family = AF_INET;
             Addr.sin_port = htons(atoi(PORT));
             inet_pton(AF_INET, ADDR, &Addr.sin_addr);
             if (connect(s1, (struct sockaddr*)&Addr, sizeof(Addr)) < 0)
                    throw boost::system::error_code(WSAGetLastError(), boost::system::system_category());
#endif
             printf("s1=%d\n", s1);
             {
                    boost::asio::io_service IoService;
                    boost::asio::ip::tcp::socket s(IoService, boost::asio::ip::tcp::v4(), (boost::asio::ip::tcp::socket::native_handle_type)s1);
                    n = s.write_some(boost::asio::buffer(&Request, sizeof(Request)));
                    printf("write_some() returned %d\n", n);
                    n = s.read_some(boost::asio::buffer(Buffer, sizeof(Buffer)));
                    printf("read_some() returned %d\n", n);

             }
             return 0;
       }
       catch (boost::system::error_code &ec)
       {
             fprintf(stderr, "boost::system::error_code: %s\n", ec.message().c_str());
             return -1;
       }
       catch (std::exception &e)
       {
             fprintf(stderr, "std::exception: %s\n", e.what());
             return -1;
       }
}

Thanks in advance,

Mario

--
Mario Klebsch                      Actia I+ME GmbH
Mario.klebsch_at_[hidden]<mailto:Mario.klebsch_at_[hidden]>         Dresdenstrasse 17/18
Fon: +49 531 38 701 716            38124 Braunschweig
Fax: +49 531 38 701 88            German


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net