[Mono-dev] Non-TCP/IP socket access
Andy Hume
andyhume32 at yahoo.co.uk
Mon Jul 25 09:24:39 EDT 2011
> -----Original Message-----
> From: mono-devel-list-bounces at lists.ximian.com
> [mailto:mono-devel-list-bounces at lists.ximian.com] On Behalf
> Of Robert Jordan
> Sent: 22 July 2011 17:12
> To: mono-devel-list at lists.ximian.com
> Subject: Re: [Mono-dev] Non-TCP/IP socket access
>
> On 22.07.2011 18:04, Ivo Smits wrote:
> > Op 22-7-2011 17:05, Andy Hume schreef:
[...]
> > However, looking at the mono code, there are no checks in
> the managed
> > part of the Socket construction. Did I miss anything, is it in the
> > unmanaged code perhaps? Have you tried to use the managed Socket
>
> There are checks. That's the whole point.
>
So just to explain to Ivo and any other interested parties what happens
in Sockets on Mono versus on MSFT.
On MSFT implementations there are no restriction on the sockets values
and types that can be used. For instance any address family can be used
in Socket..ctor(af,t,p)[1]. There are also no restrictions on the
EndPoint sub-classes that can be used, that class cleverly uses the
Prototype Pattern with instance methods Serialize[2] converting to
sockaddr as a byte[] and Create for the opposite direction (and noted
before which is support in Mono since 2007-08-02). For instance we have
simple BluetoothEndPoint (and e.g. IrDAEndPoint) classes that work both
on the Win32 CLR and on the NETCF. Finally there any no restriction on
socket options. Basically in all cases the values used by the caller
are passed unchanged to the Winsock calls and vice versa.
On Mono however there is the necessity to handle different platforms
(Linux, OSX, Windows etc). Code for this has been placed in the runtime
(native) code. It will convert the family values used in managed code
(System.Net.Sockets.AddressFamily) to the platform equivalent and in
reverse, it also remaps the layout of sockaddr structs, and finally does
similar things for socket options. That's all good and well and useful
for TCP/IP sockets as there is support on all platforms, it also works
for UNIX sockets for instance.
Currently other socket types are blocked. This occurs because the
mapping functions will return an error if asked to handle a different
address family. For instance see convert_family at
mono/metadata/socket-io.c[3], when given an unknown value will skip it
and return -1, similarly for the other direction convert_to_mono_family
returns AddressFamily_Unknown. For Connect and Bind, they use
create_sockaddr_from_object which for an unknown family returns:
*error = WSAEAFNOSUPPORT;
Hence why I can't use Socket directly currently. :-,(
Andy
_Footnotes/Details
[1] For Socket the given family value will be passed directly though
managed code to the CLR and to the native call.
[2] For EndPoint, in-box support on desktop includes IPEndPoint, and on
NETCF an addition is IrDAEndPoint. As a third-party we have
successfully used our BluetoothEndPoint and IrDAEndPoint classes on both
platforms.
What happens is that for Connect/Bind the EndPoint.Serialize instance
method is called by the managed Socket methods and the result byte array
is passed directly through the CLR to the relevant native calls.
Similar support exists for getting EndPoints _from_ native code, for
Local-/RemoteEndPoint properties). There the EndPoint.Create instance
method is used. (Apparently Serialize is called first to get a
correctly-size buffer to pass down to the native code.
[3] https://github.com/mono/mono/blob/master/mono/metadata/socket-io.c
More information about the Mono-devel-list
mailing list