public static SocketError CreateSocket(AddressFamily addressFamily, SocketType socketType, ProtocolType protocolType, out SafeSocketHandle socket) { Interop.Winsock.EnsureInitialized(); IntPtr handle = Interop.Winsock.WSASocketW(addressFamily, socketType, protocolType, IntPtr.Zero, 0, Interop.Winsock.SocketConstructorFlags.WSA_FLAG_OVERLAPPED | Interop.Winsock.SocketConstructorFlags.WSA_FLAG_NO_HANDLE_INHERIT); socket = new SafeSocketHandle(handle, ownsHandle: true); if (socket.IsInvalid) { SocketError error = GetLastSocketError(); if (NetEventSource.Log.IsEnabled()) { NetEventSource.Error(null, $"WSASocketW failed with error {error}"); } socket.Dispose(); return(error); } if (NetEventSource.Log.IsEnabled()) { NetEventSource.Info(null, socket); } return(SocketError.Success); }
public static unsafe SocketError CreateSocket( SocketInformation socketInformation, out SafeSocketHandle socket, ref AddressFamily addressFamily, ref SocketType socketType, ref ProtocolType protocolType) { if (socketInformation.ProtocolInformation == null || socketInformation.ProtocolInformation.Length < sizeof(Interop.Winsock.WSAPROTOCOL_INFOW)) { throw new ArgumentException(SR.net_sockets_invalid_socketinformation, nameof(socketInformation)); } Interop.Winsock.EnsureInitialized(); fixed(byte *protocolInfoBytes = socketInformation.ProtocolInformation) { // Sockets are non-inheritable in .NET Core. // Handle properties like HANDLE_FLAG_INHERIT are not cloned with socket duplication, therefore // we need to disable handle inheritance when constructing the new socket handle from Protocol Info. // Additionally, it looks like WSA_FLAG_NO_HANDLE_INHERIT has no effect when being used with the Protocol Info // variant of WSASocketW, so it is being passed to that call only for consistency. // Inheritance is being disabled with SetHandleInformation(...) after the WSASocketW call. IntPtr handle = Interop.Winsock.WSASocketW( (AddressFamily)(-1), (SocketType)(-1), (ProtocolType)(-1), (IntPtr)protocolInfoBytes, 0, Interop.Winsock.SocketConstructorFlags.WSA_FLAG_OVERLAPPED | Interop.Winsock.SocketConstructorFlags.WSA_FLAG_NO_HANDLE_INHERIT); socket = new SafeSocketHandle(handle, ownsHandle: true); if (socket.IsInvalid) { SocketError error = GetLastSocketError(); if (NetEventSource.Log.IsEnabled()) { NetEventSource.Error(null, $"WSASocketW failed with error {error}"); } socket.Dispose(); return(error); } if (!Interop.Kernel32.SetHandleInformation(socket, Interop.Kernel32.HandleFlags.HANDLE_FLAG_INHERIT, 0)) { // Returning SocketError for consistency, since the call site can deal with conversion, and // the most common SetHandleInformation error (AccessDenied) is included in SocketError anyways: SocketError error = GetLastSocketError(); if (NetEventSource.Log.IsEnabled()) { NetEventSource.Error(null, $"SetHandleInformation failed with error {error}"); } socket.Dispose(); return(error); } if (NetEventSource.Log.IsEnabled()) { NetEventSource.Info(null, socket); } Interop.Winsock.WSAPROTOCOL_INFOW *protocolInfo = (Interop.Winsock.WSAPROTOCOL_INFOW *)protocolInfoBytes; addressFamily = protocolInfo->iAddressFamily; socketType = protocolInfo->iSocketType; protocolType = protocolInfo->iProtocol; return(SocketError.Success); } }
internal SocketError ReplaceHandle() { // Copy out values from key options. The copied values should be kept in sync with the // handling in SafeSocketHandle.TrackOption. Note that we copy these values out first, before // we change _handle, so that we can use the helpers on Socket which internally access _handle. // Then once _handle is switched to the new one, we can call the setters to propagate the retrieved // values back out to the new underlying socket. bool broadcast = false, dontFragment = false, noDelay = false; int receiveSize = -1, receiveTimeout = -1, sendSize = -1, sendTimeout = -1; short ttl = -1; LingerOption?linger = null; if (_handle.IsTrackedOption(TrackedSocketOptions.DontFragment)) { dontFragment = DontFragment; } if (_handle.IsTrackedOption(TrackedSocketOptions.EnableBroadcast)) { broadcast = EnableBroadcast; } if (_handle.IsTrackedOption(TrackedSocketOptions.LingerState)) { linger = LingerState; } if (_handle.IsTrackedOption(TrackedSocketOptions.NoDelay)) { noDelay = NoDelay; } if (_handle.IsTrackedOption(TrackedSocketOptions.ReceiveBufferSize)) { receiveSize = ReceiveBufferSize; } if (_handle.IsTrackedOption(TrackedSocketOptions.ReceiveTimeout)) { receiveTimeout = ReceiveTimeout; } if (_handle.IsTrackedOption(TrackedSocketOptions.SendBufferSize)) { sendSize = SendBufferSize; } if (_handle.IsTrackedOption(TrackedSocketOptions.SendTimeout)) { sendTimeout = SendTimeout; } if (_handle.IsTrackedOption(TrackedSocketOptions.Ttl)) { ttl = Ttl; } // Then replace the handle with a new one SafeSocketHandle oldHandle = _handle; SocketError errorCode = SocketPal.CreateSocket(_addressFamily, _socketType, _protocolType, out _handle); oldHandle.TransferTrackedState(_handle); oldHandle.Dispose(); if (errorCode != SocketError.Success) { return(errorCode); } // And put back the copied settings. For DualMode, we use the value stored in the _handle // rather than querying the socket itself, as on Unix stacks binding a dual-mode socket to // an IPv6 address may cause the IPv6Only setting to revert to true. if (_handle.IsTrackedOption(TrackedSocketOptions.DualMode)) { DualMode = _handle.DualMode; } if (_handle.IsTrackedOption(TrackedSocketOptions.DontFragment)) { DontFragment = dontFragment; } if (_handle.IsTrackedOption(TrackedSocketOptions.EnableBroadcast)) { EnableBroadcast = broadcast; } if (_handle.IsTrackedOption(TrackedSocketOptions.LingerState)) { LingerState = linger !; } if (_handle.IsTrackedOption(TrackedSocketOptions.NoDelay)) { NoDelay = noDelay; } if (_handle.IsTrackedOption(TrackedSocketOptions.ReceiveBufferSize)) { ReceiveBufferSize = receiveSize; } if (_handle.IsTrackedOption(TrackedSocketOptions.ReceiveTimeout)) { ReceiveTimeout = receiveTimeout; } if (_handle.IsTrackedOption(TrackedSocketOptions.SendBufferSize)) { SendBufferSize = sendSize; } if (_handle.IsTrackedOption(TrackedSocketOptions.SendTimeout)) { SendTimeout = sendTimeout; } if (_handle.IsTrackedOption(TrackedSocketOptions.Ttl)) { Ttl = ttl; } return(SocketError.Success); }