Windows sockets, or WinSock, adapts the sockets communication model to the Windows programming environment. As a result, WinSock contains many Windows-specific extension functions in addition to the core Unix stream socket calls.
Instead of implementing Winsock, we decided to support only a subset of Winsock calls, the same set of functions that were in our VMMC sockets Linux implementation. The current implementation does not support (for now) out-of-band (OOB) data, scatter/gather operations, and polling with recv() (MSG_PEEK). We call this implementation NT VMMC Sockets.
The two main issues in implementing NT VMMC sockets were: (i) seamless user-level integration of the library for binary compatibility with existing applications, and (ii) integration of user-level VMMC sockets with NT kernel sockets. The solution that satisfied both requirements was using a wrapper DLL (dynamic-link library) that intercepts WinSock calls and allowed for a user-level implementation of sockets.
NT provides support for sockets via two DLLs, wsock32.dll
(WinSock 1.1) and ws2_32.dll (WinSock 2.0). All calls in wsock32.dll end up
calling into either ws2_32.dll or mswsock.dll. Since we only
support a subset of the original Berkeley sockets functions that are
in WinSock 1.1, we just need to deal with the functions in wsock32.dll.
Our wrapper DLL for wsock32.dll, intercepts WinSock 1.1
calls and implements user-level sockets using VMMC. To disambiguate
between the two identically named files we refer to the VMMC-based
library as . By simply placing a copy of
in
the application's directory (or path) WinSock 1.1 calls are
automatically intercepted. Removing (or renaming it) allows the
application to use NT's wsock32.dll.
We also wanted to support both types of stream connections:
user-level VMMC and NT kernel (i.e. Ethernet). In order to accomplish
this, the user-level sockets library allocates a socket descriptor
table that contains one entry for each open socket, regardless of the
socket type. When NT kernel sockets are used, forwards
calls through to either ws2_32.dll or mswsock.dll, while still maintaining
a descriptor table entry. Also, our library uses calls to wsock32.dll in
order to bootstrap the VMMC connection. Figure 3
illustrates the software layers in our user-level implementation.
Building a wrapper DLL was straightforward. We used the
dumpbin utility provided by Microsoft Win32 SDK to produce the list of
exported functions in the wsock32.dll as well as their forwarding information.
We wrote a perl script to find the function prototype for each exported
function from a list of header files and produce a stub call that uses
GetProcAddress() to obtain the address of the corresponding function in either
ws2_32.dll or mswsock.dll.
This script also produces the definition (.def) file
needed to build the DLL along with the correct function ordinals.
uses LoadLibrary() to load both ws2_32.dll and mswsock.dll so
that it can, as needed, forward calls to them.