예제 #1
0
        public static unsafe SocketError Send(SafeCloseSocket handle, byte[] buffer, int offset, int size, SocketFlags socketFlags, out int bytesTransferred)
        {
            int bytesSent;

            if (buffer.Length == 0)
            {
                bytesSent = Interop.Winsock.send(handle.DangerousGetHandle(), null, 0, socketFlags);
            }
            else
            {
                fixed(byte *pinnedBuffer = buffer)
                {
                    bytesSent = Interop.Winsock.send(
                        handle.DangerousGetHandle(),
                        pinnedBuffer + offset,
                        size,
                        socketFlags);
                }
            }

            if (bytesSent == (int)SocketError.SocketError)
            {
                bytesTransferred = 0;
                return(GetLastSocketError());
            }

            bytesTransferred = bytesSent;
            return(SocketError.Success);
        }
예제 #2
0
        public static unsafe SocketError ReceiveFrom(SafeCloseSocket handle, byte[] buffer, int offset, int size, SocketFlags socketFlags, byte[] socketAddress, ref int addressLength, out int bytesTransferred)
        {
            int bytesReceived;

            if (buffer.Length == 0)
            {
                bytesReceived = Interop.Winsock.recvfrom(handle.DangerousGetHandle(), null, 0, socketFlags, socketAddress, ref addressLength);
            }
            else
            {
                fixed(byte *pinnedBuffer = buffer)
                {
                    bytesReceived = Interop.Winsock.recvfrom(handle.DangerousGetHandle(), pinnedBuffer + offset, size, socketFlags, socketAddress, ref addressLength);
                }
            }

            if (bytesReceived == (int)SocketError.SocketError)
            {
                bytesTransferred = 0;
                return(GetLastSocketError());
            }

            bytesTransferred = bytesReceived;
            return(SocketError.Success);
        }
예제 #3
0
        public static unsafe SocketError ReceiveAsync(SafeCloseSocket handle, byte[] buffer, int offset, int count, SocketFlags socketFlags, OverlappedAsyncResult asyncResult)
        {
            // Set up asyncResult for overlapped WSARecv.
            asyncResult.SetUnmanagedStructures(buffer, offset, count, null);
            try
            {
                int         bytesTransferred;
                SocketError errorCode = Interop.Winsock.WSARecv(
                    handle.DangerousGetHandle(), // to minimize chances of handle recycling from misuse, this should use DangerousAddRef/Release, but it adds too much overhead
                    ref asyncResult._singleBuffer,
                    1,
                    out bytesTransferred,
                    ref socketFlags,
                    asyncResult.DangerousOverlappedPointer, // SafeHandle was just created in SetUnmanagedStructures
                    IntPtr.Zero);
                GC.KeepAlive(handle);                       // small extra safe guard against handle getting collected/finalized while P/Invoke in progress

                return(asyncResult.ProcessOverlappedResult(errorCode == SocketError.Success, bytesTransferred));
            }
            catch
            {
                asyncResult.ReleaseUnmanagedStructures();
                throw;
            }
        }
예제 #4
0
        public static unsafe SocketError SendAsync(SafeCloseSocket handle, IList <ArraySegment <byte> > buffers, SocketFlags socketFlags, OverlappedAsyncResult asyncResult)
        {
            // Set up asyncResult for overlapped WSASend.
            asyncResult.SetUnmanagedStructures(buffers);
            try
            {
                int         bytesTransferred;
                SocketError errorCode = Interop.Winsock.WSASend(
                    handle.DangerousGetHandle(), // to minimize chances of handle recycling from misuse, this should use DangerousAddRef/Release, but it adds too much overhead
                    asyncResult._wsaBuffers,
                    asyncResult._wsaBuffers.Length,
                    out bytesTransferred,
                    socketFlags,
                    asyncResult.DangerousOverlappedPointer, // SafeHandle was just created in SetUnmanagedStructures
                    IntPtr.Zero);
                GC.KeepAlive(handle);                       // small extra safe guard against handle getting collected/finalized while P/Invoke in progress

                return(asyncResult.ProcessOverlappedResult(errorCode == SocketError.Success, bytesTransferred));
            }
            catch
            {
                asyncResult.ReleaseUnmanagedStructures();
                throw;
            }
        }
예제 #5
0
        public static SocketError ReceiveMessageFrom(Socket socket, SafeCloseSocket handle, byte[] buffer, int offset, int size, ref SocketFlags socketFlags, Internals.SocketAddress socketAddress, out Internals.SocketAddress receiveAddress, out IPPacketInformation ipPacketInformation, out int bytesTransferred)
        {
            ReceiveMessageOverlappedAsyncResult asyncResult = new ReceiveMessageOverlappedAsyncResult(socket, null, null);

            asyncResult.SetUnmanagedStructures(buffer, offset, size, socketAddress, socketFlags);

            SocketError errorCode = SocketError.Success;

            bytesTransferred = 0;
            try
            {
                // This can throw ObjectDisposedException (retrieving the delegate AND resolving the handle).
                if (socket.WSARecvMsgBlocking(
                        handle.DangerousGetHandle(),
                        Marshal.UnsafeAddrOfPinnedArrayElement(asyncResult._messageBuffer, 0),
                        out bytesTransferred,
                        IntPtr.Zero,
                        IntPtr.Zero) == SocketError.SocketError)
                {
                    errorCode = (SocketError)Marshal.GetLastWin32Error();
                }
            }
            finally
            {
                asyncResult.SyncReleaseUnmanagedStructures();
            }

            socketFlags         = asyncResult.SocketFlags;
            receiveAddress      = asyncResult.SocketAddress;
            ipPacketInformation = asyncResult.IPPacketInformation;

            return(errorCode);
        }
예제 #6
0
            internal static InnerSafeCloseSocket Accept(SafeCloseSocket socketHandle, byte[] socketAddress, ref int socketAddressSize)
            {
                InnerSafeCloseSocket result = Interop.Winsock.accept(socketHandle.DangerousGetHandle(), socketAddress, ref socketAddressSize);

                if (result.IsInvalid)
                {
                    result.SetHandleAsInvalid();
                }
                return(result);
            }
예제 #7
0
        public static SocketError Receive(SafeCloseSocket handle, IList <ArraySegment <byte> > buffers, ref SocketFlags socketFlags, out int bytesTransferred)
        {
            int count = buffers.Count;

            WSABuffer[] WSABuffers   = new WSABuffer[count];
            GCHandle[]  objectsToPin = null;

            try
            {
                objectsToPin = new GCHandle[count];
                for (int i = 0; i < count; ++i)
                {
                    ArraySegment <byte> buffer = buffers[i];
                    RangeValidationHelpers.ValidateSegment(buffer);
                    objectsToPin[i]       = GCHandle.Alloc(buffer.Array, GCHandleType.Pinned);
                    WSABuffers[i].Length  = buffer.Count;
                    WSABuffers[i].Pointer = Marshal.UnsafeAddrOfPinnedArrayElement(buffer.Array, buffer.Offset);
                }

                // This can throw ObjectDisposedException.
                unsafe
                {
                    SocketError errorCode = Interop.Winsock.WSARecv(
                        handle.DangerousGetHandle(),
                        WSABuffers,
                        count,
                        out bytesTransferred,
                        ref socketFlags,
                        null,
                        IntPtr.Zero);

                    if (errorCode == SocketError.SocketError)
                    {
                        errorCode = GetLastSocketError();
                    }

                    return(errorCode);
                }
            }
            finally
            {
                if (objectsToPin != null)
                {
                    for (int i = 0; i < objectsToPin.Length; ++i)
                    {
                        if (objectsToPin[i].IsAllocated)
                        {
                            objectsToPin[i].Free();
                        }
                    }
                }
            }
        }
예제 #8
0
        public static SocketError Disconnect(Socket socket, SafeCloseSocket handle, bool reuseSocket)
        {
            SocketError errorCode = SocketError.Success;

            // This can throw ObjectDisposedException (handle, and retrieving the delegate).
            if (!socket.DisconnectExBlocking(handle.DangerousGetHandle(), IntPtr.Zero, (int)(reuseSocket ? TransmitFileOptions.ReuseSocket : 0), 0))
            {
                errorCode = GetLastSocketError();
            }

            return(errorCode);
        }
예제 #9
0
        public static SocketError Connect(SafeCloseSocket handle, byte[] peerAddress, int peerAddressLen)
        {
            SocketError errorCode = Interop.Winsock.WSAConnect(
                handle.DangerousGetHandle(),
                peerAddress,
                peerAddressLen,
                IntPtr.Zero,
                IntPtr.Zero,
                IntPtr.Zero,
                IntPtr.Zero);

            return(errorCode == SocketError.SocketError ? GetLastSocketError() : SocketError.Success);
        }
예제 #10
0
        public static SocketError Send(SafeCloseSocket handle, BufferOffsetSize[] buffers, SocketFlags socketFlags, out int bytesTransferred)
        {
            WSABuffer[] WSABuffers   = new WSABuffer[buffers.Length];
            GCHandle[]  objectsToPin = null;

            try
            {
                objectsToPin = new GCHandle[buffers.Length];
                for (int i = 0; i < buffers.Length; ++i)
                {
                    objectsToPin[i]       = GCHandle.Alloc(buffers[i].Buffer, GCHandleType.Pinned);
                    WSABuffers[i].Length  = buffers[i].Size;
                    WSABuffers[i].Pointer = Marshal.UnsafeAddrOfPinnedArrayElement(buffers[i].Buffer, buffers[i].Offset);
                }

                // This can throw ObjectDisposedException.
                SocketError errorCode = Interop.Winsock.WSASend_Blocking(
                    handle.DangerousGetHandle(),
                    WSABuffers,
                    WSABuffers.Length,
                    out bytesTransferred,
                    socketFlags,
                    SafeNativeOverlapped.Zero,
                    IntPtr.Zero);

                if (errorCode == SocketError.SocketError)
                {
                    errorCode = (SocketError)Marshal.GetLastWin32Error();
                }

                return(errorCode);
            }
            finally
            {
                if (objectsToPin != null)
                {
                    for (int i = 0; i < objectsToPin.Length; ++i)
                    {
                        if (objectsToPin[i].IsAllocated)
                        {
                            objectsToPin[i].Free();
                        }
                    }
                }
            }
        }
예제 #11
0
        public bool TryRegister(SafeCloseSocket socket, Interop.Sys.SocketEvents current, Interop.Sys.SocketEvents events, GCHandle handle, out Interop.Error error)
        {
            if (current == events)
            {
                error = Interop.Error.SUCCESS;
                return(true);
            }

            //
            // @TODO: work out a better way to handle this.  For now, just do the "dangerous" thing; this is called
            // from SafeCloseSocket.ReleaseHandle, so it can't access the file descriptor in the normal way.
            //
            int fd = (int)socket.DangerousGetHandle();

            error = Interop.Sys.DangerousTryChangeSocketEventRegistration(_port, fd, current, events, (IntPtr)handle);
            return(error == Interop.Error.SUCCESS);
        }
예제 #12
0
        public static unsafe SocketError Send(SafeCloseSocket handle, ReadOnlySpan <byte> buffer, SocketFlags socketFlags, out int bytesTransferred)
        {
            int bytesSent;

            fixed(byte *bufferPtr = &MemoryMarshal.GetReference(buffer))
            {
                bytesSent = Interop.Winsock.send(handle.DangerousGetHandle(), bufferPtr, buffer.Length, socketFlags);
            }

            if (bytesSent == (int)SocketError.SocketError)
            {
                bytesTransferred = 0;
                return(GetLastSocketError());
            }

            bytesTransferred = bytesSent;
            return(SocketError.Success);
        }
예제 #13
0
        public static unsafe SocketError Receive(SafeCloseSocket handle, Span <byte> buffer, SocketFlags socketFlags, out int bytesTransferred)
        {
            int bytesReceived;

            fixed(byte *bufferPtr = &buffer.DangerousGetPinnableReference())
            {
                bytesReceived = Interop.Winsock.recv(handle.DangerousGetHandle(), bufferPtr, buffer.Length, socketFlags);
            }

            if (bytesReceived == (int)SocketError.SocketError)
            {
                bytesTransferred = 0;
                return(GetLastSocketError());
            }

            bytesTransferred = bytesReceived;
            return(SocketError.Success);
        }
예제 #14
0
        public static SocketError Poll(SafeCloseSocket handle, int microseconds, SelectMode mode, out bool status)
        {
            IntPtr rawHandle = handle.DangerousGetHandle();

            IntPtr[] fileDescriptorSet = new IntPtr[2] {
                (IntPtr)1, rawHandle
            };
            Interop.Winsock.TimeValue IOwait = new Interop.Winsock.TimeValue();

            // A negative timeout value implies an indefinite wait.
            int socketCount;

            if (microseconds != -1)
            {
                MicrosecondsToTimeValue((long)(uint)microseconds, ref IOwait);
                socketCount =
                    Interop.Winsock.select(
                        0,
                        mode == SelectMode.SelectRead ? fileDescriptorSet : null,
                        mode == SelectMode.SelectWrite ? fileDescriptorSet : null,
                        mode == SelectMode.SelectError ? fileDescriptorSet : null,
                        ref IOwait);
            }
            else
            {
                socketCount =
                    Interop.Winsock.select(
                        0,
                        mode == SelectMode.SelectRead ? fileDescriptorSet : null,
                        mode == SelectMode.SelectWrite ? fileDescriptorSet : null,
                        mode == SelectMode.SelectError ? fileDescriptorSet : null,
                        IntPtr.Zero);
            }

            if ((SocketError)socketCount == SocketError.SocketError)
            {
                status = false;
                return(GetLastSocketError());
            }

            status = (int)fileDescriptorSet[0] != 0 && fileDescriptorSet[1] == rawHandle;
            return(SocketError.Success);
        }
예제 #15
0
        public static SocketError WindowsIoctl(SafeCloseSocket handle, int ioControlCode, byte[] optionInValue, byte[] optionOutValue, out int optionLength)
        {
            if (ioControlCode == Interop.Winsock.IoctlSocketConstants.FIONBIO)
            {
                throw new InvalidOperationException(SR.net_sockets_useblocking);
            }

            SocketError errorCode = Interop.Winsock.WSAIoctl_Blocking(
                handle.DangerousGetHandle(),
                ioControlCode,
                optionInValue,
                optionInValue != null ? optionInValue.Length : 0,
                optionOutValue,
                optionOutValue != null ? optionOutValue.Length : 0,
                out optionLength,
                SafeNativeOverlapped.Zero,
                IntPtr.Zero);

            return(errorCode == SocketError.SocketError ? GetLastSocketError() : SocketError.Success);
        }
예제 #16
0
        public static SocketError IoctlInternal(SafeCloseSocket handle, IOControlCode ioControlCode, IntPtr optionInValue, int inValueLength, IntPtr optionOutValue, int outValueLength, out int optionLength)
        {
            if ((unchecked ((int)ioControlCode)) == Interop.Winsock.IoctlSocketConstants.FIONBIO)
            {
                throw new InvalidOperationException(SR.net_sockets_useblocking);
            }

            SocketError errorCode = Interop.Winsock.WSAIoctl_Blocking_Internal(
                handle.DangerousGetHandle(),
                (uint)ioControlCode,
                optionInValue,
                inValueLength,
                optionOutValue,
                outValueLength,
                out optionLength,
                SafeNativeOverlapped.Zero,
                IntPtr.Zero);

            return(errorCode == SocketError.SocketError ? GetLastSocketError() : SocketError.Success);
        }
예제 #17
0
 internal static InnerSafeCloseSocket Accept(SafeCloseSocket socketHandle, byte[] socketAddress, ref int socketAddressSize)
 {
     InnerSafeCloseSocket result = Interop.Winsock.accept(socketHandle.DangerousGetHandle(), socketAddress, ref socketAddressSize);
     if (result.IsInvalid)
     {
         result.SetHandleAsInvalid();
     }
     return result;
 }
예제 #18
0
        public static unsafe SocketError Poll(SafeCloseSocket handle, int microseconds, SelectMode mode, out bool status)
        {
            uint* fdSet = stackalloc uint[Interop.Sys.FD_SETSIZE_UINTS];
            Interop.Sys.FD_ZERO(fdSet);

            bool releaseHandle = false;
            try
            {
                handle.DangerousAddRef(ref releaseHandle);
                int fd = (int)handle.DangerousGetHandle();
                Interop.Sys.FD_SET(fd, fdSet);

                int fdCount = 0;
                uint* readFds = null;
                uint* writeFds = null;
                uint* errorFds = null;
                switch (mode)
                {
                    case SelectMode.SelectRead:
                        readFds = fdSet;
                        fdCount = fd + 1;
                        break;

                    case SelectMode.SelectWrite:
                        writeFds = fdSet;
                        fdCount = fd + 1;
                        break;

                    case SelectMode.SelectError:
                        errorFds = fdSet;
                        fdCount = fd + 1;
                        break;
                }

                int socketCount = 0;
                Interop.Error err = Interop.Sys.Select(fdCount, readFds, writeFds, errorFds, microseconds, &socketCount);
                if (err != Interop.Error.SUCCESS)
                {
                    status = false;
                    return GetSocketErrorForErrorCode(err);
                }

                status = Interop.Sys.FD_ISSET(fd, fdSet);
            }
            finally
            {
                if (releaseHandle)
                {
                    handle.DangerousRelease();
                }
            }
            return SocketError.Success;
        }
예제 #19
0
        public static unsafe SocketError ReceiveMessageFrom(Socket socket, SafeCloseSocket handle, byte[] buffer, int offset, int size, ref SocketFlags socketFlags, Internals.SocketAddress socketAddress, out Internals.SocketAddress receiveAddress, out IPPacketInformation ipPacketInformation, out int bytesTransferred)
        {
            bool ipv4, ipv6;

            Socket.GetIPProtocolInformation(socket.AddressFamily, socketAddress, out ipv4, out ipv6);

            bytesTransferred    = 0;
            receiveAddress      = socketAddress;
            ipPacketInformation = default(IPPacketInformation);

            fixed(byte *ptrBuffer = buffer)
            fixed(byte *ptrSocketAddress = socketAddress.Buffer)
            {
                Interop.Winsock.WSAMsg wsaMsg;
                wsaMsg.socketAddress = (IntPtr)ptrSocketAddress;
                wsaMsg.addressLength = (uint)socketAddress.Size;
                wsaMsg.flags         = socketFlags;

                WSABuffer wsaBuffer;

                wsaBuffer.Length  = size;
                wsaBuffer.Pointer = (IntPtr)(ptrBuffer + offset);
                wsaMsg.buffers    = (IntPtr)(&wsaBuffer);
                wsaMsg.count      = 1;

                if (ipv4)
                {
                    Interop.Winsock.ControlData controlBuffer;
                    wsaMsg.controlBuffer.Pointer = (IntPtr)(&controlBuffer);
                    wsaMsg.controlBuffer.Length  = sizeof(Interop.Winsock.ControlData);

                    if (socket.WSARecvMsgBlocking(
                            handle.DangerousGetHandle(),
                            (IntPtr)(&wsaMsg),
                            out bytesTransferred,
                            IntPtr.Zero,
                            IntPtr.Zero) == SocketError.SocketError)
                    {
                        return(GetLastSocketError());
                    }

                    ipPacketInformation = GetIPPacketInformation(&controlBuffer);
                }
                else if (ipv6)
                {
                    Interop.Winsock.ControlDataIPv6 controlBuffer;
                    wsaMsg.controlBuffer.Pointer = (IntPtr)(&controlBuffer);
                    wsaMsg.controlBuffer.Length  = sizeof(Interop.Winsock.ControlDataIPv6);

                    if (socket.WSARecvMsgBlocking(
                            handle.DangerousGetHandle(),
                            (IntPtr)(&wsaMsg),
                            out bytesTransferred,
                            IntPtr.Zero,
                            IntPtr.Zero) == SocketError.SocketError)
                    {
                        return(GetLastSocketError());
                    }

                    ipPacketInformation = GetIPPacketInformation(&controlBuffer);
                }
                else
                {
                    wsaMsg.controlBuffer.Pointer = IntPtr.Zero;
                    wsaMsg.controlBuffer.Length  = 0;

                    if (socket.WSARecvMsgBlocking(
                            handle.DangerousGetHandle(),
                            (IntPtr)(&wsaMsg),
                            out bytesTransferred,
                            IntPtr.Zero,
                            IntPtr.Zero) == SocketError.SocketError)
                    {
                        return(GetLastSocketError());
                    }
                }

                socketFlags = wsaMsg.flags;
            }

            return(SocketError.Success);
        }