Created attachment 109 [details]
Mono currently only allows access to a very restricted set of socket types, effectively TCP/IP, UDP and UNIX. Various other socket types can be present on current systems however. In particular I need to access Bluetooth sockets on Linux BlueZ. This is currently not possible; if sockets-io.c does not have explicit support for an AddressFamily then usage is disallowed. However all other support is in place.
To otherwise add support for Bluetooth on Linux one would need to P/Invoke to all the sockets functions which would be very difficult. Various workarounds were then suggested to me by Mono people, but none could be successfully implemented. When that failed I got another suggestion from mono-devel-list, which was to patch sockets-io.c to not disallow non-explicitly supported address families.
So I modified sockets-io.c so that it simply doesn't block the user from using Address Families and sockaddr structs which it does not explicitly support. With these minor changes I can simply use Bluetooth sockets with "new Socket(AF_BLUETOOTH, SocketType.Stream, Rfcomm)". Success.
I attach that patch. I'd be very pleased if this could be considered for inclusion.
It makes four changes:
1. convert_family (convert managed AF -> native AF): Change one line so that if the AF is not explicitly supported, don't block it, but allow it to be used.
2. convert_to_mono_family (native AF -> managed AF) : Ditto.
3. create_sockaddr_from_object (SocketAddress->sockaddr): If the AF is not explicitly supported, don't block it, but just copy use the SocketAddress as is.
4. create_object_from_sockaddr (sockaddr->SocketAddress): If the AF is not explicitly supported, don't block it, but just use the sockaddr as is. Uses sockaddr_storage type (in get_sockaddr_size).
No other changes were required. With that, socket, bind, connect, getsockname, getpeername and the I/Os method all work.
 To otherwise add support for Bluetooth on Linux would need one to P/Invoke to all the socket functions e.g. socket, recv, send, connect, etc. Whilst implementing some (socket and close) might be fairly simple, reimplementing all the I/O methods would be difficult, and very very difficult if the end-developer wanted to use a Socket or NetworkStream. And all that facility exists in Mono already...
 The second workaround suggested to me by the Mono team was to P/Invoke to create the Bluetooth native socket, then create a managed TCP/IP Socket, and use Reflection to overwrite its handle with the handle from the call to socket. I implemented this but unfortunately this does not work as the handles used in Mono are WAPI Handles, and after various suggestions and attempts we found that there is no way to convert the socket handle to a WAPI handle.
Would you mind doing a pull request, so we can have others comment on the patch?
Will do. Once I work out how to do that. :-,)
Patch looks ok. My only concern here is where do we fail if an invalid AF is passed in.
Can you state that this change is under MIT/X11 so it can be included?
Andy, can you release your patch under the MIT license so it can be merged?
Glad to. Is this sufficient?
This patch is released under the MIT/X11 license by Andy Hume <firstname.lastname@example.org>.
Hope my release sentence is ok. Let me know if not.
I am surprised I did not catch this on the first review.
The problem with this is that the code in question handles a number of well-known managed values and returns the system defined version of that value (convert_to_mono_family).
The issue with allowing any values is that allowing any values assumes that an arbitrary managed value will happen to be the same one as the system value. This will break in cases where the arbitrary value that you want in unmanaged world happens to be identical to one of the defined constants in the managed world.
I suspect that ideally what we want is a series of new entry points that allow the creation of the objects from a sockaddr that completely skip over the mapping of address families.
While not directly applicable to this "bug", the original need for this change may or may not be met by using BlueZ 5 and DBus to establish a bluetooth socket rather than using interop. I can provide a link to a blog post on how to do this using Mono 4.33 if requested, but I will refrain from posting it for now to avoid coming off as spammy.
PS, Thanks for your work on this Andy, your patch helped me limp along on BlueZ 4 for the last year or so on my project before finally getting things up and going on BlueZ 5.
Moving to BCL as it needs the manage sockets code to deal with other families.