diff --git a/PInvoke/Ws2_32/WinSock2.WSA.Error.cs b/PInvoke/Ws2_32/WinSock2.WSA.Error.cs index 31a89aad..e7f9ff8b 100644 --- a/PInvoke/Ws2_32/WinSock2.WSA.Error.cs +++ b/PInvoke/Ws2_32/WinSock2.WSA.Error.cs @@ -51,6 +51,11 @@ public static partial class Ws2_32 /// The result of the conversion. public static implicit operator WSRESULT(SocketError value) => new((int)value); + /// Implements the operator !. + /// The value. + /// The result of the operator. + public static bool operator !(WSRESULT value) => value.Failed; + /// Implements the operator !=. /// The first . /// The second . @@ -81,14 +86,21 @@ public static partial class Ws2_32 /// /// The 32-bit raw WSRESULT value. /// The optional message to assign to the . + [SecurityCritical, System.Diagnostics.DebuggerStepThrough] public static void ThrowIfFailed(int value, string message = null) => new WSRESULT(value).ThrowIfFailed(message); + /// Throws the last error. + /// The message. + [SecurityCritical, System.Diagnostics.DebuggerStepThrough] + public static void ThrowLastError(string message = null) => GetLastError().ThrowIfFailed(message); + /// Throws the last error if the predicate delegate returns . /// The type of the value to evaluate. /// The value to check. /// The delegate which returns on failure. /// The message. /// The passed in on success. + [SecurityCritical, System.Diagnostics.DebuggerStepThrough] public static T ThrowLastErrorIf(T value, Func valueIsFailure, string message = null) { if (valueIsFailure(value)) @@ -99,11 +111,13 @@ public static partial class Ws2_32 /// Throws the last error if the function returns . /// The value to check. /// The message. + [SecurityCritical, System.Diagnostics.DebuggerStepThrough] public static bool ThrowLastErrorIfFalse(bool value, string message = null) => ThrowLastErrorIf(value, v => !v, message); /// Throws the last error if the value is an invalid handle. /// The SafeHandle to check. /// The message. + [SecurityCritical, System.Diagnostics.DebuggerStepThrough] public static T ThrowLastErrorIfInvalid(T value, string message = null) where T : SafeHandle => ThrowLastErrorIf(value, v => v.IsInvalid, message); /// Compares the current object with another object of the same type. @@ -180,16 +194,14 @@ public static partial class Ws2_32 /// Gets the last error. /// The last error. - [SecurityCritical] - [System.Diagnostics.DebuggerStepThrough] + [SecurityCritical, System.Diagnostics.DebuggerStepThrough] public static WSRESULT GetLastError() => WSAGetLastError(); /// /// If this represents a failure, throw the associated with the optionally supplied message. /// /// The optional message to assign to the . - [SecurityCritical] - [SecuritySafeCritical] + [SecurityCritical, SecuritySafeCritical, System.Diagnostics.DebuggerStepThrough] public void ThrowIfFailed(string message = null) { Exception exception = GetException(message); @@ -240,6 +252,55 @@ public static partial class Ws2_32 ulong IConvertible.ToUInt64(IFormatProvider provider) => ((IConvertible)unchecked((uint)_value)).ToUInt64(provider); + /// + /// Specified event object handle is invalid. + /// An application attempts to use an event object, but the specified handle is not valid. + /// + public const int WSA_INVALID_HANDLE = 6; + + /// + /// Insufficient memory available. + /// + /// An application used a Windows Sockets function that directly maps to a Windows function. The Windows function is indicating a + /// lack of required memory resources. + /// + /// + public const int WSA_NOT_ENOUGH_MEMORY = 8; + + /// + /// One or more parameters are invalid. + /// + /// An application used a Windows Sockets function which directly maps to a Windows function. The Windows function is indicating a + /// problem with one or more parameters. + /// + /// + public const int WSA_INVALID_PARAMETER = 87; + + /// + /// Overlapped operation aborted. + /// An overlapped operation was canceled due to the closure of the socket, or the execution of the SIO_FLUSH command in WSAIoctl. + /// + public const int WSA_OPERATION_ABORTED = 995; + + /// + /// Overlapped I/O event object not in signaled state. + /// + /// The application has tried to determine the status of an overlapped operation which is not yet completed. Applications that use + /// WSAGetOverlappedResult (with the fWait flag set to FALSE) in a polling mode to determine when an overlapped operation has + /// completed, get this error code until the operation is complete. + /// + /// + public const int WSA_IO_INCOMPLETE = 996; + + /// + /// Overlapped operations will complete later. + /// + /// The application has initiated an overlapped operation that cannot be completed immediately. A completion indication will be given + /// later when the operation has been completed. + /// + /// + public const int WSA_IO_PENDING = 997; + /// A blocking operation was interrupted by a call to WSACancelBlockingCall. public const int WSAEINTR = 0x00002714; diff --git a/PInvoke/Ws2_32/WinSock2.WSA.cs b/PInvoke/Ws2_32/WinSock2.WSA.cs index e914cb7b..04541016 100644 --- a/PInvoke/Ws2_32/WinSock2.WSA.cs +++ b/PInvoke/Ws2_32/WinSock2.WSA.cs @@ -2930,7 +2930,7 @@ namespace Vanara.PInvoke // WSAEnumNameSpaceProvidersW( LPDWORD lpdwBufferLength, LPWSANAMESPACE_INFOW lpnspBuffer ); [DllImport(Lib.Ws2_32, SetLastError = false, CharSet = CharSet.Unicode)] [PInvokeData("winsock2.h", MSDNShortId = "f5b6cd42-c5cb-43b6-bb96-fd260217e252")] - public static extern WSRESULT WSAEnumNameSpaceProviders(ref uint lpdwBufferLength, [Out] IntPtr lpnspBuffer); + public static extern int WSAEnumNameSpaceProviders(ref uint lpdwBufferLength, [Out] IntPtr lpnspBuffer); /// The WSAEnumNameSpaceProvidersEx function retrieves information on available namespace providers. /// @@ -3004,7 +3004,7 @@ namespace Vanara.PInvoke // WSAEnumNameSpaceProvidersExA( LPDWORD lpdwBufferLength, LPWSANAMESPACE_INFOEXA lpnspBuffer ); [DllImport(Lib.Ws2_32, SetLastError = false, CharSet = CharSet.Unicode)] [PInvokeData("winsock2.h", MSDNShortId = "34bc96aa-63f7-4ab8-9376-6f4b979225ca")] - public static extern WSRESULT WSAEnumNameSpaceProvidersEx(ref uint lpdwBufferLength, [Out] IntPtr lpnspBuffer); + public static extern int WSAEnumNameSpaceProvidersEx(ref uint lpdwBufferLength, [Out] IntPtr lpnspBuffer); /// /// The WSAEnumNetworkEvents function discovers occurrences of network events for the indicated socket, clear internal @@ -3278,7 +3278,7 @@ namespace Vanara.PInvoke // lpiProtocols, LPWSAPROTOCOL_INFOA lpProtocolBuffer, LPDWORD lpdwBufferLength ); [DllImport(Lib.Ws2_32, SetLastError = false, CharSet = CharSet.Auto)] [PInvokeData("winsock2.h", MSDNShortId = "928b6937-41a3-4268-a3bc-14c9e04870e4")] - public static extern WSRESULT WSAEnumProtocols([Optional, MarshalAs(UnmanagedType.LPArray)] int[] lpiProtocols, [Out] IntPtr lpProtocolBuffer, ref uint lpdwBufferLength); + public static extern int WSAEnumProtocols([Optional, MarshalAs(UnmanagedType.LPArray)] int[] lpiProtocols, [Out] IntPtr lpProtocolBuffer, ref uint lpdwBufferLength); /// /// The WSAEventSelect function specifies an event object to be associated with the specified set of FD_XXX network events. @@ -5912,7 +5912,7 @@ namespace Vanara.PInvoke // fds, INT timeout ); [DllImport(Lib.Ws2_32, SetLastError = false, ExactSpelling = true)] [PInvokeData("winsock2.h", MSDNShortId = "3f6f872c-5cee-49f3-bf22-2e8a5d147987")] - public static extern WSRESULT WSAPoll([In, Out, MarshalAs(UnmanagedType.LPArray)] WSAPOLLFD[] fdArray, uint fds, int timeout); + public static extern int WSAPoll([In, Out, MarshalAs(UnmanagedType.LPArray)] WSAPOLLFD[] fdArray, uint fds, int timeout); /// The WSAProviderConfigChange function notifies the application when the provider configuration is changed. /// diff --git a/PInvoke/Ws2_32/WinSock2.cs b/PInvoke/Ws2_32/WinSock2.cs index e1ab46ec..dfe32e93 100644 --- a/PInvoke/Ws2_32/WinSock2.cs +++ b/PInvoke/Ws2_32/WinSock2.cs @@ -1295,29 +1295,35 @@ namespace Vanara.PInvoke /// Gets or sets the byte array representing the IPv6 address. /// The bytes. /// Byte array must have 16 items. - value - public unsafe byte[] bytes + public byte[] bytes { get { - var v6addr = new byte[IN6_ADDR_SIZE]; - fixed (byte* usp = &v6addr[0]) + unsafe { - var ulp2 = (ulong*)usp; - ulp2[0] = lower; - ulp2[1] = upper; + var v6addr = new byte[IN6_ADDR_SIZE]; + fixed (byte* usp = &v6addr[0]) + { + var ulp2 = (ulong*)usp; + ulp2[0] = lower; + ulp2[1] = upper; + } + return v6addr; } - return v6addr; } set { - if (value == null) value = new byte[IN6_ADDR_SIZE]; - if (value.Length != IN6_ADDR_SIZE) - throw new ArgumentException("Byte array must have 16 items.", nameof(value)); - fixed (byte* bp = &value[0]) + unsafe { - var ulp = (ulong*)bp; - lower = ulp[0]; - upper = ulp[1]; + if (value == null) value = new byte[IN6_ADDR_SIZE]; + if (value.Length != IN6_ADDR_SIZE) + throw new ArgumentException("Byte array must have 16 items.", nameof(value)); + fixed (byte* bp = &value[0]) + { + var ulp = (ulong*)bp; + lower = ulp[0]; + upper = ulp[1]; + } } } } @@ -1325,29 +1331,35 @@ namespace Vanara.PInvoke /// Gets or sets the array of WORD (ushort) values representing the IPv6 address. /// The array of WORD values. /// UInt16 array must have 8 items. - value - public unsafe ushort[] words + public ushort[] words { get { - var v6addr = new ushort[IN6_ADDR_SIZE / 2]; - fixed (ushort* usp = &v6addr[0]) + unsafe { - var ulp2 = (ulong*)usp; - ulp2[0] = lower; - ulp2[1] = upper; + var v6addr = new ushort[IN6_ADDR_SIZE / 2]; + fixed (ushort* usp = &v6addr[0]) + { + var ulp2 = (ulong*)usp; + ulp2[0] = lower; + ulp2[1] = upper; + } + return v6addr; } - return v6addr; } set { - if (value == null) value = new ushort[IN6_ADDR_SIZE / 2]; - if (value.Length != IN6_ADDR_SIZE / 2) - throw new ArgumentException("UInt16 array must have 8 items.", nameof(value)); - fixed (ushort* bp = &value[0]) + unsafe { - var ulp = (ulong*)bp; - lower = ulp[0]; - upper = ulp[1]; + if (value == null) value = new ushort[IN6_ADDR_SIZE / 2]; + if (value.Length != IN6_ADDR_SIZE / 2) + throw new ArgumentException("UInt16 array must have 8 items.", nameof(value)); + fixed (ushort* bp = &value[0]) + { + var ulp = (ulong*)bp; + lower = ulp[0]; + upper = ulp[1]; + } } } } diff --git a/PInvoke/Ws2_32/WinSock2.legacy.cs b/PInvoke/Ws2_32/WinSock2.legacy.cs index 6a838eaa..3023f548 100644 --- a/PInvoke/Ws2_32/WinSock2.legacy.cs +++ b/PInvoke/Ws2_32/WinSock2.legacy.cs @@ -169,7 +169,7 @@ namespace Vanara.PInvoke // int *addrlen ); [DllImport(Lib.Ws2_32, SetLastError = true, ExactSpelling = true)] [PInvokeData("winsock2.h", MSDNShortId = "72246263-4806-4ab2-9b26-89a1782a954b")] - public static extern SOCKET accept(SOCKET s, SOCKADDR addr, ref int addrlen); + public static extern SafeSOCKET accept(SOCKET s, SOCKADDR addr, ref int addrlen); /// The accept function permits an incoming connection attempt on a socket. /// @@ -313,7 +313,7 @@ namespace Vanara.PInvoke // int *addrlen ); [DllImport(Lib.Ws2_32, SetLastError = true, ExactSpelling = true)] [PInvokeData("winsock2.h", MSDNShortId = "72246263-4806-4ab2-9b26-89a1782a954b")] - public static extern SOCKET accept(SOCKET s, [Optional] IntPtr addr, [Optional] IntPtr addrlen); + public static extern SafeSOCKET accept(SOCKET s, [Optional] IntPtr addr, [Optional] IntPtr addrlen); /// The bind function associates a local address with a socket. /// A descriptor identifying an unbound socket. @@ -2421,7 +2421,7 @@ namespace Vanara.PInvoke // *argp ); [DllImport(Lib.Ws2_32, SetLastError = true, ExactSpelling = true)] [PInvokeData("winsock.h", MSDNShortId = "048fcb8d-acd3-4917-a997-dd133db399f8")] - public static extern WSRESULT ioctlsocket(SOCKET s, int cmd, IntPtr argp); + public static extern WSRESULT ioctlsocket(SOCKET s, uint cmd, IntPtr argp); /// The listen function places a socket in a state in which it is listening for an incoming connection. /// A descriptor identifying a bound, unconnected socket. @@ -2818,7 +2818,207 @@ namespace Vanara.PInvoke // https://docs.microsoft.com/en-us/windows/win32/api/winsock/nf-winsock-recv int recv( SOCKET s, char *buf, int len, int flags ); [DllImport(Lib.Ws2_32, SetLastError = true, ExactSpelling = true)] [PInvokeData("winsock.h", MSDNShortId = "8c247cd3-479f-45d0-a038-a24e80cc7c73")] - public static extern WSRESULT recv(SOCKET s, IntPtr buf, int len, MsgFlags flags); + public static extern int recv(SOCKET s, IntPtr buf, int len, MsgFlags flags); + + /// The recv function receives data from a connected socket or a bound connectionless socket. + /// The descriptor that identifies a connected socket. + /// A pointer to the buffer to receive the incoming data. + /// The length, in bytes, of the buffer pointed to by the buf parameter. + /// + /// A set of flags that influences the behavior of this function. See remarks below. See the Remarks section for details on the + /// possible value for this parameter. + /// + /// + /// + /// If no error occurs, recv returns the number of bytes received and the buffer pointed to by the buf parameter will contain + /// this data received. If the connection has been gracefully closed, the return value is zero. + /// + /// Otherwise, a value of SOCKET_ERROR is returned, and a specific error code can be retrieved by calling WSAGetLastError. + /// + /// + /// Error code + /// Meaning + /// + /// + /// WSANOTINITIALISED + /// A successful WSAStartup call must occur before using this function. + /// + /// + /// WSAENETDOWN + /// The network subsystem has failed. + /// + /// + /// WSAEFAULT + /// The buf parameter is not completely contained in a valid part of the user address space. + /// + /// + /// WSAENOTCONN + /// The socket is not connected. + /// + /// + /// WSAEINTR + /// The (blocking) call was canceled through WSACancelBlockingCall. + /// + /// + /// WSAEINPROGRESS + /// A blocking Windows Sockets 1.1 call is in progress, or the service provider is still processing a callback function. + /// + /// + /// WSAENETRESET + /// + /// For a connection-oriented socket, this error indicates that the connection has been broken due to keep-alive activity that + /// detected a failure while the operation was in progress. For a datagram socket, this error indicates that the time to live has expired. + /// + /// + /// + /// WSAENOTSOCK + /// The descriptor is not a socket. + /// + /// + /// WSAEOPNOTSUPP + /// + /// MSG_OOB was specified, but the socket is not stream-style such as type SOCK_STREAM, OOB data is not supported in the + /// communication domain associated with this socket, or the socket is unidirectional and supports only send operations. + /// + /// + /// + /// WSAESHUTDOWN + /// + /// The socket has been shut down; it is not possible to receive on a socket after shutdown has been invoked with how set to + /// SD_RECEIVE or SD_BOTH. + /// + /// + /// + /// WSAEWOULDBLOCK + /// The socket is marked as nonblocking and the receive operation would block. + /// + /// + /// WSAEMSGSIZE + /// The message was too large to fit into the specified buffer and was truncated. + /// + /// + /// WSAEINVAL + /// + /// The socket has not been bound with bind, or an unknown flag was specified, or MSG_OOB was specified for a socket with + /// SO_OOBINLINE enabled or (for byte stream sockets only) len was zero or negative. + /// + /// + /// + /// WSAECONNABORTED + /// + /// The virtual circuit was terminated due to a time-out or other failure. The application should close the socket as it is no + /// longer usable. + /// + /// + /// + /// WSAETIMEDOUT + /// The connection has been dropped because of a network failure or because the peer system failed to respond. + /// + /// + /// WSAECONNRESET + /// + /// The virtual circuit was reset by the remote side executing a hard or abortive close. The application should close the socket as + /// it is no longer usable. On a UDP-datagram socket, this error would indicate that a previous send operation resulted in an ICMP + /// "Port Unreachable" message. + /// + /// + /// + /// + /// + /// + /// The recv function is used to read incoming data on connection-oriented sockets, or connectionless sockets. When using a + /// connection-oriented protocol, the sockets must be connected before calling recv. When using a connectionless protocol, + /// the sockets must be bound before calling recv. + /// + /// + /// The local address of the socket must be known. For server applications, use an explicit bind function or an implicit accept or + /// WSAAccept function. Explicit binding is discouraged for client applications. For client applications, the socket can become + /// bound implicitly to a local address using connect, WSAConnect, sendto, WSASendTo, or WSAJoinLeaf. + /// + /// + /// For connected or connectionless sockets, the recv function restricts the addresses from which received messages are + /// accepted. The function only returns messages from the remote address specified in the connection. Messages from other addresses + /// are (silently) discarded. + /// + /// + /// For connection-oriented sockets (type SOCK_STREAM for example), calling recv will return as much data as is currently + /// available—up to the size of the buffer specified. If the socket has been configured for in-line reception of OOB data (socket + /// option SO_OOBINLINE) and OOB data is yet unread, only OOB data will be returned. The application can use the ioctlsocket or + /// WSAIoctl SIOCATMARK command to determine whether any more OOB data remains to be read. + /// + /// + /// For connectionless sockets (type SOCK_DGRAM or other message-oriented sockets), data is extracted from the first enqueued + /// datagram (message) from the destination address specified by the connect function. + /// + /// + /// If the datagram or message is larger than the buffer specified, the buffer is filled with the first part of the datagram, and + /// recv generates the error WSAEMSGSIZE. For unreliable protocols (for example, UDP) the excess data is lost; for reliable + /// protocols, the data is retained by the service provider until it is successfully read by calling recv with a large enough buffer. + /// + /// + /// If no incoming data is available at the socket, the recv call blocks and waits for data to arrive according to the + /// blocking rules defined for WSARecv with the MSG_PARTIAL flag not set unless the socket is nonblocking. In this case, a value of + /// SOCKET_ERROR is returned with the error code set to WSAEWOULDBLOCK. The select, WSAAsyncSelect, or WSAEventSelect functions can + /// be used to determine when more data arrives. + /// + /// + /// If the socket is connection oriented and the remote side has shut down the connection gracefully, and all data has been + /// received, a recv will complete immediately with zero bytes received. If the connection has been reset, a recv will + /// fail with the error WSAECONNRESET. + /// + /// + /// The flags parameter can be used to influence the behavior of the function invocation beyond the options specified for the + /// associated socket. The semantics of this function are determined by the socket options and the flags parameter. The possible + /// value of flags parameter is constructed by using the bitwise OR operator with any of the following values. + /// + /// + /// + /// Value + /// Meaning + /// + /// + /// MSG_PEEK + /// + /// Peeks at the incoming data. The data is copied into the buffer, but is not removed from the input queue. The function + /// subsequently returns the amount of data that can be read in a single call to the recv (or recvfrom) function, which may not be + /// the same as the total amount of data queued on the socket. The amount of data that can actually be read in a single call to the + /// recv (or recvfrom) function is limited to the data size written in the send or sendto function call. + /// + /// + /// + /// MSG_OOB + /// Processes Out Of Band (OOB) data. + /// + /// + /// MSG_WAITALL + /// + /// The receive request will complete only when one of the following events occurs:Note that if the underlying transport does not + /// support MSG_WAITALL, or if the socket is in a non-blocking mode, then this call will fail with WSAEOPNOTSUPP. Also, if + /// MSG_WAITALL is specified along with MSG_OOB, MSG_PEEK, or MSG_PARTIAL, then this call will fail with WSAEOPNOTSUPP. This flag is + /// not supported on datagram sockets or message-oriented sockets. + /// + /// + /// + /// + /// Note When issuing a blocking Winsock call such as recv, Winsock may need to wait for a network event before the + /// call can complete. Winsock performs an alertable wait in this situation, which can be interrupted by an asynchronous procedure + /// call (APC) scheduled on the same thread. Issuing another blocking Winsock call inside an APC that interrupted an ongoing + /// blocking Winsock call on the same thread will lead to undefined behavior, and must never be attempted by Winsock clients. + /// + /// Example Code + /// The following code example shows the use of the recv function. + /// Example Code + /// For more information, and another example of the recv function, see Getting Started With Winsock. + /// Windows Phone 8: This function is supported for Windows Phone Store apps on Windows Phone 8 and later. + /// + /// Windows 8.1 and Windows Server 2012 R2: This function is supported for Windows Store apps on Windows 8.1, Windows + /// Server 2012 R2, and later. + /// + /// + // https://docs.microsoft.com/en-us/windows/win32/api/winsock/nf-winsock-recv int recv( SOCKET s, char *buf, int len, int flags ); + [DllImport(Lib.Ws2_32, SetLastError = true, ExactSpelling = true)] + [PInvokeData("winsock.h", MSDNShortId = "8c247cd3-479f-45d0-a038-a24e80cc7c73")] + public static extern int recv(SOCKET s, byte[] buf, int len, MsgFlags flags); /// The recvfrom function receives a datagram and stores the source address. /// A descriptor identifying a bound socket. @@ -3001,7 +3201,190 @@ namespace Vanara.PInvoke // flags, sockaddr *from, int *fromlen ); [DllImport(Lib.Ws2_32, SetLastError = true, ExactSpelling = true)] [PInvokeData("winsock.h", MSDNShortId = "3e4282e0-3ed0-43e7-9b27-72ec36b9cfa1")] - public static extern WSRESULT recvfrom(SOCKET s, IntPtr buf, int len, int flags, SOCKADDR from, ref int fromlen); + public static extern int recvfrom(SOCKET s, IntPtr buf, int len, int flags, SOCKADDR from, ref int fromlen); + + /// The recvfrom function receives a datagram and stores the source address. + /// A descriptor identifying a bound socket. + /// A buffer for the incoming data. + /// The length, in bytes, of the buffer pointed to by the buf parameter. + /// + /// A set of options that modify the behavior of the function call beyond the options specified for the associated socket. See the + /// Remarks below for more details. + /// + /// An optional pointer to a buffer in a sockaddr structure that will hold the source address upon return. + /// An optional pointer to the size, in bytes, of the buffer pointed to by the from parameter. + /// + /// + /// If no error occurs, recvfrom returns the number of bytes received. If the connection has been gracefully closed, the + /// return value is zero. Otherwise, a value of SOCKET_ERROR is returned, and a specific error code can be retrieved by calling WSAGetLastError. + /// + /// + /// + /// Error code + /// Meaning + /// + /// + /// WSANOTINITIALISED + /// A successful WSAStartup call must occur before using this function. + /// + /// + /// WSAENETDOWN + /// The network subsystem has failed. + /// + /// + /// WSAEFAULT + /// + /// The buffer pointed to by the buf or from parameters are not in the user address space, or the fromlen parameter is too small to + /// accommodate the source address of the peer address. + /// + /// + /// + /// WSAEINTR + /// The (blocking) call was canceled through WSACancelBlockingCall. + /// + /// + /// WSAEINPROGRESS + /// A blocking Windows Sockets 1.1 call is in progress, or the service provider is still processing a callback function. + /// + /// + /// WSAEINVAL + /// + /// The socket has not been bound with bind, or an unknown flag was specified, or MSG_OOB was specified for a socket with + /// SO_OOBINLINE enabled, or (for byte stream-style sockets only) len was zero or negative. + /// + /// + /// + /// WSAEISCONN + /// + /// The socket is connected. This function is not permitted with a connected socket, whether the socket is connection oriented or connectionless. + /// + /// + /// + /// WSAENETRESET + /// For a datagram socket, this error indicates that the time to live has expired. + /// + /// + /// WSAENOTSOCK + /// The descriptor in the s parameter is not a socket. + /// + /// + /// WSAEOPNOTSUPP + /// + /// MSG_OOB was specified, but the socket is not stream-style such as type SOCK_STREAM, OOB data is not supported in the + /// communication domain associated with this socket, or the socket is unidirectional and supports only send operations. + /// + /// + /// + /// WSAESHUTDOWN + /// + /// The socket has been shut down; it is not possible to recvfrom on a socket after shutdown has been invoked with how set to + /// SD_RECEIVE or SD_BOTH. + /// + /// + /// + /// WSAEWOULDBLOCK + /// The socket is marked as nonblocking and the recvfrom operation would block. + /// + /// + /// WSAEMSGSIZE + /// The message was too large to fit into the buffer pointed to by the buf parameter and was truncated. + /// + /// + /// WSAETIMEDOUT + /// + /// The connection has been dropped, because of a network failure or because the system on the other end went down without notice. + /// + /// + /// + /// WSAECONNRESET + /// + /// The virtual circuit was reset by the remote side executing a hard or abortive close. The application should close the socket; it + /// is no longer usable. On a UDP-datagram socket this error indicates a previous send operation resulted in an ICMP Port + /// Unreachable message. + /// + /// + /// + /// + /// + /// + /// The recvfrom function reads incoming data on both connected and unconnected sockets and captures the address from which + /// the data was sent. This function is typically used with connectionless sockets. The local address of the socket must be known. + /// For server applications, this is usually done explicitly through bind. Explicit binding is discouraged for client applications. + /// For client applications using this function, the socket can become bound implicitly to a local address through sendto, + /// WSASendTo, or WSAJoinLeaf. + /// + /// + /// For stream-oriented sockets such as those of type SOCK_STREAM, a call to recvfrom returns as much information as is + /// currently available—up to the size of the buffer specified. If the socket has been configured for inline reception of OOB data + /// (socket option SO_OOBINLINE) and OOB data is yet unread, only OOB data will be returned. The application can use the ioctlsocket + /// or WSAIoctl SIOCATMARK command to determine whether any more OOB data remains to be read. The from and fromlen parameters + /// are ignored for connection-oriented sockets. + /// + /// + /// For message-oriented sockets, data is extracted from the first enqueued message, up to the size of the buffer specified. If the + /// datagram or message is larger than the buffer specified, the buffer is filled with the first part of the datagram, and + /// recvfrom generates the error WSAEMSGSIZE. For unreliable protocols (for example, UDP) the excess data is lost. For UDP if + /// the packet received contains no data (empty), the return value from the recvfrom function function is zero. + /// + /// + /// If the from parameter is nonzero and the socket is not connection oriented, (type SOCK_DGRAM for example), the network address + /// of the peer that sent the data is copied to the corresponding sockaddr structure. The value pointed to by fromlen is initialized + /// to the size of this structure and is modified, on return, to indicate the actual size of the address stored in the + /// sockaddr structure. + /// + /// + /// If no incoming data is available at the socket, the recvfrom function blocks and waits for data to arrive according to + /// the blocking rules defined for WSARecv with the MSG_PARTIAL flag not set unless the socket is nonblocking. In this case, a value + /// of SOCKET_ERROR is returned with the error code set to WSAEWOULDBLOCK. The select, WSAAsyncSelect, or WSAEventSelect can be used + /// to determine when more data arrives. + /// + /// + /// If the socket is connection oriented and the remote side has shut down the connection gracefully, the call to recvfrom + /// will complete immediately with zero bytes received. If the connection has been reset recvfrom will fail with the error WSAECONNRESET. + /// + /// + /// The flags parameter can be used to influence the behavior of the function invocation beyond the options specified for the + /// associated socket. The semantics of this function are determined by the socket options and the flags parameter. The latter is + /// constructed by using the bitwise OR operator with any of the following values. + /// + /// + /// + /// Value + /// Meaning + /// + /// + /// MSG_PEEK + /// + /// Peeks at the incoming data. The data is copied into the buffer but is not removed from the input queue. The function + /// subsequently returns the amount of data that can be read in a single call to the recvfrom (or recv) function, which may not be + /// the same as the total amount of data queued on the socket. The amount of data that can actually be read in a single call to the + /// recvfrom (or recv) function is limited to the data size written in the send or sendto function call. + /// + /// + /// + /// MSG_OOB + /// Processes Out Of Band (OOB) data. + /// + /// + /// + /// Note When issuing a blocking Winsock call such as recvfrom, Winsock may need to wait for a network event before + /// the call can complete. Winsock performs an alertable wait in this situation, which can be interrupted by an asynchronous + /// procedure call (APC) scheduled on the same thread. Issuing another blocking Winsock call inside an APC that interrupted an + /// ongoing blocking Winsock call on the same thread will lead to undefined behavior, and must never be attempted by Winsock clients. + /// + /// Example Code + /// The following example demonstrates the use of the recvfrom function. + /// Windows Phone 8: This function is supported for Windows Phone Store apps on Windows Phone 8 and later. + /// + /// Windows 8.1 and Windows Server 2012 R2: This function is supported for Windows Store apps on Windows 8.1, Windows + /// Server 2012 R2, and later. + /// + /// + // https://docs.microsoft.com/en-us/windows/win32/api/winsock/nf-winsock-recvfrom int recvfrom( SOCKET s, char *buf, int len, int + // flags, sockaddr *from, int *fromlen ); + [DllImport(Lib.Ws2_32, SetLastError = true, ExactSpelling = true)] + [PInvokeData("winsock.h", MSDNShortId = "3e4282e0-3ed0-43e7-9b27-72ec36b9cfa1")] + public static extern int recvfrom(SOCKET s, byte[] buf, int len, int flags, SOCKADDR from, ref int fromlen); /// /// The select function determines the status of one or more sockets, waiting if necessary, to perform synchronous I/O. @@ -3559,7 +3942,203 @@ namespace Vanara.PInvoke // int flags ); [DllImport(Lib.Ws2_32, SetLastError = true, ExactSpelling = true)] [PInvokeData("winsock2.h", MSDNShortId = "902bb9cf-d847-43fc-8282-394d619b8f1b")] - public static extern WSRESULT send(SOCKET s, IntPtr buf, int len, int flags); + public static extern int send(SOCKET s, IntPtr buf, int len, int flags); + + /// The send function sends data on a connected socket. + /// A descriptor identifying a connected socket. + /// A pointer to a buffer containing the data to be transmitted. + /// The length, in bytes, of the data in buffer pointed to by the buf parameter. + /// + /// + /// A set of flags that specify the way in which the call is made. This parameter is constructed by using the bitwise OR operator + /// with any of the following values. + /// + /// + /// + /// Value + /// Meaning + /// + /// + /// MSG_DONTROUTE + /// + /// Specifies that the data should not be subject to routing. A Windows Sockets service provider can choose to ignore this flag. + /// + /// + /// + /// MSG_OOB + /// Sends OOB data (stream-style socket such as SOCK_STREAM only. + /// + /// + /// + /// + /// + /// If no error occurs, send returns the total number of bytes sent, which can be less than the number requested to be sent + /// in the len parameter. Otherwise, a value of SOCKET_ERROR is returned, and a specific error code can be retrieved by calling WSAGetLastError. + /// + /// + /// + /// Error code + /// Meaning + /// + /// + /// WSANOTINITIALISED + /// A successful WSAStartup call must occur before using this function. + /// + /// + /// WSAENETDOWN + /// The network subsystem has failed. + /// + /// + /// WSAEACCES + /// + /// The requested address is a broadcast address, but the appropriate flag was not set. Call setsockopt with the SO_BROADCAST socket + /// option to enable use of the broadcast address. + /// + /// + /// + /// WSAEINTR + /// A blocking Windows Sockets 1.1 call was canceled through WSACancelBlockingCall. + /// + /// + /// WSAEINPROGRESS + /// A blocking Windows Sockets 1.1 call is in progress, or the service provider is still processing a callback function. + /// + /// + /// WSAEFAULT + /// The buf parameter is not completely contained in a valid part of the user address space. + /// + /// + /// WSAENETRESET + /// The connection has been broken due to the keep-alive activity detecting a failure while the operation was in progress. + /// + /// + /// WSAENOBUFS + /// No buffer space is available. + /// + /// + /// WSAENOTCONN + /// The socket is not connected. + /// + /// + /// WSAENOTSOCK + /// The descriptor is not a socket. + /// + /// + /// WSAEOPNOTSUPP + /// + /// MSG_OOB was specified, but the socket is not stream-style such as type SOCK_STREAM, OOB data is not supported in the + /// communication domain associated with this socket, or the socket is unidirectional and supports only receive operations. + /// + /// + /// + /// WSAESHUTDOWN + /// + /// The socket has been shut down; it is not possible to send on a socket after shutdown has been invoked with how set to SD_SEND or SD_BOTH. + /// + /// + /// + /// WSAEWOULDBLOCK + /// The socket is marked as nonblocking and the requested operation would block. + /// + /// + /// WSAEMSGSIZE + /// The socket is message oriented, and the message is larger than the maximum supported by the underlying transport. + /// + /// + /// WSAEHOSTUNREACH + /// The remote host cannot be reached from this host at this time. + /// + /// + /// WSAEINVAL + /// + /// The socket has not been bound with bind, or an unknown flag was specified, or MSG_OOB was specified for a socket with + /// SO_OOBINLINE enabled. + /// + /// + /// + /// WSAECONNABORTED + /// + /// The virtual circuit was terminated due to a time-out or other failure. The application should close the socket as it is no + /// longer usable. + /// + /// + /// + /// WSAECONNRESET + /// + /// The virtual circuit was reset by the remote side executing a hard or abortive close. For UDP sockets, the remote host was unable + /// to deliver a previously sent UDP datagram and responded with a "Port Unreachable" ICMP packet. The application should close the + /// socket as it is no longer usable. + /// + /// + /// + /// WSAETIMEDOUT + /// + /// The connection has been dropped, because of a network failure or because the system on the other end went down without notice. + /// + /// + /// + /// + /// + /// The send function is used to write outgoing data on a connected socket. + /// + /// For message-oriented sockets (address family of AF_INET or AF_INET6, type of SOCK_DGRAM, and protocol of + /// IPPROTO_UDP, for example), care must be taken not to exceed the maximum packet size of the underlying provider. The + /// maximum message packet size for a provider can be obtained by calling getsockopt with the optname parameter set to + /// SO_MAX_MSG_SIZE to retrieve the value of socket option. If the data is too long to pass atomically through the underlying + /// protocol, the error WSAEMSGSIZE is returned, and no data is transmitted. + /// + /// + /// The successful completion of a send function does not indicate that the data was successfully delivered and received to + /// the recipient. This function only indicates the data was successfully sent. + /// + /// + /// If no buffer space is available within the transport system to hold the data to be transmitted, send will block unless + /// the socket has been placed in nonblocking mode. On nonblocking stream oriented sockets, the number of bytes written can be + /// between 1 and the requested length, depending on buffer availability on both the client and server computers. The select, + /// WSAAsyncSelect or WSAEventSelect functions can be used to determine when it is possible to send more data. + /// + /// + /// Calling send with a len parameter of zero is permissible and will be treated by implementations as successful. In such + /// cases, send will return zero as a valid value. For message-oriented sockets, a zero-length transport datagram is sent. + /// + /// + /// The flags parameter can be used to influence the behavior of the function beyond the options specified for the associated + /// socket. The semantics of the send function are determined by any options previously set on the socket specified in the s + /// parameter and the flags parameter passed to the send function. + /// + /// + /// The order of calls made to send is also the order in which the buffers are transmitted to the transport layer. + /// send should not be called on the same stream-oriented socket concurrently from different threads, because some Winsock + /// providers may split a large send request into multiple transmissions, and this may lead to unintended data interleaving from + /// multiple concurrent send requests on the same stream-oriented socket. + /// + /// + /// Note When issuing a blocking Winsock call such as send, Winsock may need to wait for a network event before the + /// call can complete. Winsock performs an alertable wait in this situation, which can be interrupted by an asynchronous procedure + /// call (APC) scheduled on the same thread. Issuing another blocking Winsock call inside an APC that interrupted an ongoing + /// blocking Winsock call on the same thread will lead to undefined behavior, and must never be attempted by Winsock clients. + /// + /// Example Code + /// The following example demonstrates the use of the send function. + /// Example Code + /// For a another example that uses the send function, see Getting Started With Winsock. + /// Notes for IrDA Sockets + /// + /// + /// The Af_irda.h header file must be explicitly included. + /// + /// + /// Windows Phone 8: This function is supported for Windows Phone Store apps on Windows Phone 8 and later. + /// + /// Windows 8.1 and Windows Server 2012 R2: This function is supported for Windows Store apps on Windows 8.1, Windows + /// Server 2012 R2, and later. + /// + /// + // https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-send int WSAAPI send( SOCKET s, const char *buf, int len, + // int flags ); + [DllImport(Lib.Ws2_32, SetLastError = true, ExactSpelling = true)] + [PInvokeData("winsock2.h", MSDNShortId = "902bb9cf-d847-43fc-8282-394d619b8f1b")] + public static extern int send(SOCKET s, byte[] buf, int len, int flags); /// The sendto function sends data to a specific destination. /// A descriptor identifying a (possibly connected) socket. @@ -3792,7 +4371,240 @@ namespace Vanara.PInvoke // flags, const sockaddr *to, int tolen ); [DllImport(Lib.Ws2_32, SetLastError = true, ExactSpelling = true)] [PInvokeData("winsock.h", MSDNShortId = "a1c89c6b-d11d-4d3e-a664-af2beed0cd09")] - public static extern WSRESULT sendto(SOCKET s, IntPtr buf, int len, int flags, SOCKADDR to, int tolen); + public static extern int sendto(SOCKET s, IntPtr buf, int len, int flags, SOCKADDR to, int tolen); + + /// The sendto function sends data to a specific destination. + /// A descriptor identifying a (possibly connected) socket. + /// A pointer to a buffer containing the data to be transmitted. + /// The length, in bytes, of the data pointed to by the buf parameter. + /// A set of flags that specify the way in which the call is made. + /// An optional pointer to a sockaddr structure that contains the address of the target socket. + /// The size, in bytes, of the address pointed to by the to parameter. + /// + /// + /// If no error occurs, sendto returns the total number of bytes sent, which can be less than the number indicated by len. + /// Otherwise, a value of SOCKET_ERROR is returned, and a specific error code can be retrieved by calling WSAGetLastError. + /// + /// + /// + /// Error code + /// Meaning + /// + /// + /// WSANOTINITIALISED + /// A successful WSAStartup call must occur before using this function. + /// + /// + /// WSAENETDOWN + /// The network subsystem has failed. + /// + /// + /// WSAEACCES + /// + /// The requested address is a broadcast address, but the appropriate flag was not set. Call setsockopt with the SO_BROADCAST + /// parameter to allow the use of the broadcast address. + /// + /// + /// + /// WSAEINVAL + /// An unknown flag was specified, or MSG_OOB was specified for a socket with SO_OOBINLINE enabled. + /// + /// + /// WSAEINTR + /// A blocking Windows Sockets 1.1 call was canceled through WSACancelBlockingCall. + /// + /// + /// WSAEINPROGRESS + /// A blocking Windows Sockets 1.1 call is in progress, or the service provider is still processing a callback function. + /// + /// + /// WSAEFAULT + /// The buf or to parameters are not part of the user address space, or the tolen parameter is too small. + /// + /// + /// WSAENETRESET + /// The connection has been broken due to keep-alive activity detecting a failure while the operation was in progress. + /// + /// + /// WSAENOBUFS + /// No buffer space is available. + /// + /// + /// WSAENOTCONN + /// The socket is not connected (connection-oriented sockets only). + /// + /// + /// WSAENOTSOCK + /// The descriptor is not a socket. + /// + /// + /// WSAEOPNOTSUPP + /// + /// MSG_OOB was specified, but the socket is not stream-style such as type SOCK_STREAM, OOB data is not supported in the + /// communication domain associated with this socket, or the socket is unidirectional and supports only receive operations. + /// + /// + /// + /// WSAESHUTDOWN + /// + /// The socket has been shut down; it is not possible to sendto on a socket after shutdown has been invoked with how set to SD_SEND + /// or SD_BOTH. + /// + /// + /// + /// WSAEWOULDBLOCK + /// The socket is marked as nonblocking and the requested operation would block. + /// + /// + /// WSAEMSGSIZE + /// The socket is message oriented, and the message is larger than the maximum supported by the underlying transport. + /// + /// + /// WSAEHOSTUNREACH + /// The remote host cannot be reached from this host at this time. + /// + /// + /// WSAECONNABORTED + /// + /// The virtual circuit was terminated due to a time-out or other failure. The application should close the socket as it is no + /// longer usable. + /// + /// + /// + /// WSAECONNRESET + /// + /// The virtual circuit was reset by the remote side executing a hard or abortive close. For UPD sockets, the remote host was unable + /// to deliver a previously sent UDP datagram and responded with a "Port Unreachable" ICMP packet. The application should close the + /// socket as it is no longer usable. + /// + /// + /// + /// WSAEADDRNOTAVAIL + /// The remote address is not a valid address, for example, ADDR_ANY. + /// + /// + /// WSAEAFNOSUPPORT + /// Addresses in the specified family cannot be used with this socket. + /// + /// + /// WSAEDESTADDRREQ + /// A destination address is required. + /// + /// + /// WSAENETUNREACH + /// The network cannot be reached from this host at this time. + /// + /// + /// WSAEHOSTUNREACH + /// A socket operation was attempted to an unreachable host. + /// + /// + /// WSAETIMEDOUT + /// + /// The connection has been dropped, because of a network failure or because the system on the other end went down without notice. + /// + /// + /// + /// + /// + /// + /// The sendto function is used to write outgoing data on a socket. For message-oriented sockets, care must be taken not to + /// exceed the maximum packet size of the underlying subnets, which can be obtained by using getsockopt to retrieve the value of + /// socket option SO_MAX_MSG_SIZE. If the data is too long to pass atomically through the underlying protocol, the error WSAEMSGSIZE + /// is returned and no data is transmitted. + /// + /// + /// The to parameter can be any valid address in the socket's address family, including a broadcast or any multicast address. To + /// send to a broadcast address, an application must have used setsockopt with SO_BROADCAST enabled. Otherwise, sendto will + /// fail with the error code WSAEACCES. For TCP/IP, an application can send to any multicast address (without becoming a group member). + /// + /// + /// Note If a socket is opened, a setsockopt call is made, and then a sendto call is made, Windows Sockets performs an + /// implicit bind function call. + /// + /// + /// If the socket is unbound, unique values are assigned to the local association by the system, and the socket is then marked as + /// bound. If the socket is connected, the getsockname function can be used to determine the local IP address and port associated + /// with the socket. + /// + /// + /// If the socket is not connected, the getsockname function can be used to determine the local port number associated with the + /// socket but the IP address returned is set to the wildcard address for the given protocol (for example, INADDR_ANY or "0.0.0.0" + /// for IPv4 and IN6ADDR_ANY_INIT or "::" for IPv6). + /// + /// The successful completion of a sendto does not indicate that the data was successfully delivered. + /// + /// The sendto function is normally used on a connectionless socket to send a datagram to a specific peer socket identified + /// by the to parameter. Even if the connectionless socket has been previously connected to a specific address, the to parameter + /// overrides the destination address for that particular datagram only. On a connection-oriented socket, the to and tolen + /// parameters are ignored, making sendto equivalent to send. + /// + /// + /// Note When issuing a blocking Winsock call such as sendto, Winsock may need to wait for a network event before the + /// call can complete. Winsock performs an alertable wait in this situation, which can be interrupted by an asynchronous procedure + /// call (APC) scheduled on the same thread. Issuing another blocking Winsock call inside an APC that interrupted an ongoing + /// blocking Winsock call on the same thread will lead to undefined behavior, and must never be attempted by Winsock clients. + /// + /// Example Code + /// The following example demonstrates the use of the sendto function. + /// For Sockets Using IP (Version 4) + /// + /// To send a broadcast (on a SOCK_DGRAM only), the address pointed to by the to parameter can be constructed to contain the special + /// IPv4 address INADDR_BROADCAST (defined in Winsock2.h), together with the intended port number. If the address pointed to by the + /// to parameter contains the INADDR_BROADCAST address and intended port, then the broadcast will be sent out on all interfaces to + /// that port. + /// + /// + /// If the broadcast should be sent out only on a specific interface, then the address pointed to by the to parameter should contain + /// the subnet broadcast address for the interface and the intended port. For example, an IPv4 network address of 192.168.1.0 with a + /// subnet mask of 255.255.255.0 would use a subnet broadcast address of 192.168.1.255. + /// + /// + /// It is generally inadvisable for a broadcast datagram to exceed the size at which fragmentation can occur, which implies that the + /// data portion of the datagram (excluding headers) should not exceed 512 bytes. + /// + /// + /// If no buffer space is available within the transport system to hold the data to be transmitted, sendto will block unless + /// the socket has been placed in a nonblocking mode. On nonblocking, stream oriented sockets, the number of bytes written can be + /// between 1 and the requested length, depending on buffer availability on both the client and server systems. The select, + /// WSAAsyncSelect or WSAEventSelect function can be used to determine when it is possible to send more data. + /// + /// + /// Calling sendto with a len of zero is permissible and will return zero as a valid value. For message-oriented sockets, a + /// zero-length transport datagram is sent. + /// + /// + /// The flags parameter can be used to influence the behavior of the function invocation beyond the options specified for the + /// associated socket. The semantics of this function are determined by the socket options and the flags parameter. The latter is + /// constructed by using the bitwise OR operator with any of the following values. + /// + /// + /// + /// Value + /// Meaning + /// + /// + /// MSG_DONTROUTE + /// + /// Specifies that the data should not be subject to routing. A Windows Sockets service provider can choose to ignore this flag. + /// + /// + /// + /// MSG_OOB + /// Sends OOB data (stream-style socket such as SOCK_STREAM only). + /// + /// + /// Windows Phone 8: This function is supported for Windows Phone Store apps on Windows Phone 8 and later. + /// + /// Windows 8.1 and Windows Server 2012 R2: This function is supported for Windows Store apps on Windows 8.1, Windows + /// Server 2012 R2, and later. + /// + /// + // https://docs.microsoft.com/en-us/windows/win32/api/winsock/nf-winsock-sendto int sendto( SOCKET s, const char *buf, int len, int + // flags, const sockaddr *to, int tolen ); + [DllImport(Lib.Ws2_32, SetLastError = true, ExactSpelling = true)] + [PInvokeData("winsock.h", MSDNShortId = "a1c89c6b-d11d-4d3e-a664-af2beed0cd09")] + public static extern int sendto(SOCKET s, byte[] buf, int len, int flags, SOCKADDR to, int tolen); /// The setsockopt function sets a socket option. /// A descriptor that identifies a socket. @@ -5440,7 +6252,7 @@ namespace Vanara.PInvoke // protocol ); [DllImport(Lib.Ws2_32, SetLastError = true, ExactSpelling = true)] [PInvokeData("winsock2.h", MSDNShortId = "6bf6e6c4-6268-479c-86a6-52e90cf317db")] - public static extern SafeSOCKET socket(ADDRESS_FAMILY af, SOCK type, uint protocol); + public static extern SafeSOCKET socket(ADDRESS_FAMILY af, SOCK type, uint protocol = 0U); /// /// The protoent structure contains the name and protocol numbers that correspond to a given protocol name. Applications must diff --git a/PInvoke/Ws2_32/ws2def.cs b/PInvoke/Ws2_32/ws2def.cs index 15825f88..74ecd4d4 100644 --- a/PInvoke/Ws2_32/ws2def.cs +++ b/PInvoke/Ws2_32/ws2def.cs @@ -2057,6 +2057,38 @@ namespace Vanara.PInvoke [PInvokeData("ws2def.h", MSDNShortId = "fb6447b4-28f5-4ab7-bbdc-5a57ed38a994")] public static class WinSockIOControlCode { + /// + /// Determine the amount of data that can be read atomically from socket s. The lpvOutBuffer parameter points at an unsigned long + /// in which WSAIoctl stores the result. + /// + /// If the socket passed in the s parameter is stream oriented(for example, type SOCK_STREAM), FIONREAD returns the total amount + /// of data that can be read in a single receive operation; this is normally the same as the total amount of data queued on the + /// socket(since a data stream is byte-oriented, this is not guaranteed). + /// + /// + /// If the socket passed in the s parameter is message oriented(for example, type SOCK_DGRAM), FIONREAD returns the reports the + /// total number of bytes available to read, not the size of the first datagram(message) queued on the socket. + /// + /// + public static readonly uint FIONREAD = _IOR('f', 127); /* get # bytes to read */ + + /// + /// Enable or disable non-blocking mode on socket s. The lpvInBuffer parameter points at an unsigned long (QoS), which is nonzero + /// if non-blocking mode is to be enabled and zero if it is to be disabled. When a socket is created, it operates in blocking + /// mode (that is, non-blocking mode is disabled). This is consistent with BSD sockets. + /// + /// The WSAAsyncSelect or WSAEventSelect routine automatically sets a socket to non-blocking mode.If WSAAsyncSelect or + /// WSAEventSelect has been issued on a socket, then any attempt to use WSAIoctl to set the socket back to blocking mode will + /// fail with WSAEINVAL. To set the socket back to blocking mode, an application must first disable WSAAsyncSelect by calling + /// WSAAsyncSelect with the lEvent parameter equal to zero, or disable WSAEventSelect by calling WSAEventSelect with the + /// lNetworkEvents parameter equal to zero. + /// + /// + public static readonly uint FIONBIO = _IOW('f', 126); /* set/clear non-blocking i/o */ + + /// Enable notification for when data is waiting to be received. + public static readonly uint FIOASYNC = _IOW('f', 125); /* set/clear async i/o */ + /// Requests notification of changes in information reported through SIO_ADDRESS_LIST_QUERY public static readonly uint SIO_ADDRESS_LIST_CHANGE = _WSAIO(IOC_WS2, 23); @@ -2140,12 +2172,46 @@ namespace Vanara.PInvoke [CorrespondingType(typeof(int), CorrespondingAction.Set)] public static readonly uint SIO_TRANSLATE_HANDLE = _WSAIORW(IOC_WS2, 13); + /// set high watermark + public static readonly uint SIOCSHIWAT = _IOW('s', 0); /* set high watermark */ + + /// get high watermark + public static readonly uint SIOCGHIWAT = _IOR('s', 1); /* get high watermark */ + + /// set low watermark + public static readonly uint SIOCSLOWAT = _IOW('s', 2); /* set low watermark */ + + /// get low watermark + public static readonly uint SIOCGLOWAT = _IOR('s', 3); /* get low watermark */ + + /// + /// Determine whether or not all OOB data has been read. This applies only to a socket of stream-style (for example, type + /// SOCK_STREAM) that has been configured for inline reception of any OOB data (SO_OOBINLINE). If no OOB data is waiting to be + /// read, the operation returns TRUE. Otherwise, it returns FALSE, and the next receive operation performed on the socket will + /// retrieve some or all of the data preceding the mark; the application should use the SIOCATMARK operation to determine whether + /// any remains. If there is any normal data preceding the urgent (out of band) data, it will be received in order. (Note that + /// recv operations will never mix OOB and normal data in the same call.) lpvOutBuffer points at a BOOL in which WSAIoctl stores + /// the result. + /// + public static readonly uint SIOCATMARK = _IOR('s', 7); /* at oob mark? */ + + private const uint IOCPARM_MASK = 0x7f; /* parameters must be < 128 bytes */ + private const uint IOC_VOID = 0x20000000; /* no parameters */ + private const uint IOC_OUT = 0x40000000; /* copy out parameters */ + private const uint IOC_IN = 0x80000000; /* copy in parameters */ + private const uint IOC_INOUT = IOC_IN|IOC_OUT; private const uint IOC_PROTOCOL = 0x10000000; private const uint IOC_UNIX = 0x00000000; private const uint IOC_VENDOR = 0x18000000; private const uint IOC_WS2 = 0x08000000; private const uint IOC_WSK = IOC_WS2 | 0x07000000; + private static uint _IO(uint x, uint y) => (IOC_VOID|((x)<<8)|(y)); + + private static uint _IOR(uint x, uint y) => (IOC_OUT|((sizeof(uint)&IOCPARM_MASK)<<16)|((x)<<8)|(y)); + + private static uint _IOW(uint x, uint y) => (IOC_IN|((sizeof(uint)&IOCPARM_MASK)<<16)|((x)<<8)|(y)); + private static uint _WSAIO(uint x, uint y) => IOC_VOID | (x) | (y); private static uint _WSAIOR(uint x, uint y) => IOC_OUT | (x) | (y); diff --git a/UnitTests/PInvoke/Ws2_32/WSATests.cs b/UnitTests/PInvoke/Ws2_32/WSATests.cs index 3613762a..2ecf5d86 100644 --- a/UnitTests/PInvoke/Ws2_32/WSATests.cs +++ b/UnitTests/PInvoke/Ws2_32/WSATests.cs @@ -29,7 +29,7 @@ namespace Vanara.PInvoke.Tests var addr = new SOCKADDR(localIP4); var len = 256U; var sb = new StringBuilder((int)len); - Assert.That(WSAAddressToString(addr, addr.Size, default, sb, ref len), ResultIs.Not.Value(-1)); + Assert.That(WSAAddressToString(addr, addr.Size, default, sb, ref len), ResultIs.Successful); TestContext.Write(sb); Assert.That(sb.ToString(), Is.EqualTo(localIP4.ToString())); } @@ -48,12 +48,12 @@ namespace Vanara.PInvoke.Tests public void WSAEnumNameSpaceProvidersTest() { var len = 0U; - Assert.That(WSAEnumNameSpaceProviders(ref len, default), ResultIs.Value(-1)); + Assert.That(WSAEnumNameSpaceProviders(ref len, default), ResultIs.Failure); //Assert.That(WSAGetLastError(), Is.EqualTo((Win32Error)Win32Error.WSAEFAULT)); Assert.That(len, Is.GreaterThan(0)); using var mem = new SafeHGlobalHandle(len); var cnt = WSAEnumNameSpaceProviders(ref len, mem); - Assert.That(cnt, ResultIs.Not.Value(-1)); + Assert.That(cnt, ResultIs.Successful); TestContext.Write(string.Join("\n", mem.ToEnumerable(cnt).Select(n => $"{n.lpszIdentifier.ToString()}: {n.NSProviderId}, {n.dwNameSpace}, {n.fActive}"))); } @@ -61,12 +61,12 @@ namespace Vanara.PInvoke.Tests public void WSAEnumNameSpaceProvidersExTest() { var len = 0U; - Assert.That(WSAEnumNameSpaceProvidersEx(ref len, default), ResultIs.Value(-1)); + Assert.That(WSAEnumNameSpaceProvidersEx(ref len, default), ResultIs.Failure); //Assert.That(WSAGetLastError(), Is.EqualTo((Win32Error)Win32Error.WSAEFAULT)); Assert.That(len, Is.GreaterThan(0)); using var mem = new SafeHGlobalHandle(len); var cnt = WSAEnumNameSpaceProvidersEx(ref len, mem); - Assert.That(cnt, ResultIs.Not.Value(-1)); + Assert.That(cnt, ResultIs.Successful); TestContext.Write(string.Join("\n", mem.ToEnumerable(cnt).Select(n => $"{n.lpszIdentifier.ToString()}: {n.NSProviderId}, {n.dwNameSpace}, {n.fActive}"))); } @@ -75,32 +75,32 @@ namespace Vanara.PInvoke.Tests { var ListenSocket = tcpSocket; var InetAddr = new SOCKADDR(IN_ADDR.INADDR_ANY, htons(27015)); - Assert.That(bind(ListenSocket, InetAddr, InetAddr.Size), ResultIs.Not.Value(-1)); + Assert.That(bind(ListenSocket, InetAddr, InetAddr.Size), ResultIs.Successful); using var evt = WSACreateEvent(); Assert.That(evt, ResultIs.ValidHandle); - Assert.That(WSAEventSelect(ListenSocket, evt, FD.FD_ACCEPT | FD.FD_CLOSE), ResultIs.Not.Value(-1)); - Assert.That(listen(ListenSocket, 10), ResultIs.Not.Value(-1)); + Assert.That(WSAEventSelect(ListenSocket, evt, FD.FD_ACCEPT | FD.FD_CLOSE), ResultIs.Successful); + Assert.That(listen(ListenSocket, 10), ResultIs.Successful); var EventArray = new WSAEVENT[] { evt }; WSAWaitForMultipleEvents((uint)EventArray.Length, EventArray, true, 500, false); - Assert.That(WSAEnumNetworkEvents(ListenSocket, evt, out var nets), ResultIs.Not.Value(-1)); + Assert.That(WSAEnumNetworkEvents(ListenSocket, evt, out var nets), ResultIs.Successful); } [Test] public void WSAEnumProtocolsTest() { var len = 0U; - Assert.That(WSAEnumProtocols(null, default, ref len), ResultIs.Value(-1)); + Assert.That(WSAEnumProtocols(null, default, ref len), ResultIs.Failure); Assert.That(len, Is.GreaterThan(0)); using var mem = new SafeHGlobalHandle(len); var cnt = WSAEnumProtocols(null, mem, ref len); - Assert.That(cnt, ResultIs.Not.Value(-1)); + Assert.That(cnt, ResultIs.Successful); TestContext.Write(string.Join("\n", mem.ToEnumerable(cnt).Select(p => $"{p.szProtocol}: {(ADDRESS_FAMILY)p.iAddressFamily}, {p.iSocketType}, {p.iProtocol}"))); } [Test] public void WSAHtonlTest() { - Assert.That(WSAHtonl(tcpSocket, 0x01020304, out var ret), ResultIs.Not.Value(-1)); + Assert.That(WSAHtonl(tcpSocket, 0x01020304, out var ret), ResultIs.Successful); Assert.That(ret, Is.EqualTo(0x04030201)); } } diff --git a/UnitTests/PInvoke/Ws2_32/Ws2tcpipTests.cs b/UnitTests/PInvoke/Ws2_32/Ws2tcpipTests.cs index 0447421b..924e5908 100644 --- a/UnitTests/PInvoke/Ws2_32/Ws2tcpipTests.cs +++ b/UnitTests/PInvoke/Ws2_32/Ws2tcpipTests.cs @@ -30,7 +30,7 @@ namespace Vanara.PInvoke.Tests [Test] public void gai_strerrorTest() { - Assert.That(gai_strerror((int)Win32Error.WSAEINVAL), Is.Not.Null); + Assert.That(gai_strerror(WSRESULT.WSAEINVAL), Is.Not.Null); } [Test]