Ejemplo n.º 1
0
        // Poll(u32 nfds, u32 timeout, buffer<unknown, 0x21, 0> fds) -> (i32 ret, u32 bsd_errno, buffer<unknown, 0x22, 0>)
        public ResultCode Poll(ServiceCtx context)
        {
            int fdsCount = context.RequestData.ReadInt32();
            int timeout  = context.RequestData.ReadInt32();

            (long bufferPosition, long bufferSize) = context.Request.GetBufferType0x21();


            if (timeout < -1 || fdsCount < 0 || (fdsCount * 8) > bufferSize)
            {
                return(WriteBsdResult(context, -1, LinuxError.EINVAL));
            }

            PollEvent[] events = new PollEvent[fdsCount];

            for (int i = 0; i < fdsCount; i++)
            {
                int socketFd = context.Memory.ReadInt32(bufferPosition + i * 8);

                BsdSocket socket = RetrieveSocket(socketFd);

                if (socket == null)
                {
                    return(WriteBsdResult(context, -1, LinuxError.EBADF));
                }

                PollEvent.EventTypeMask inputEvents  = (PollEvent.EventTypeMask)context.Memory.ReadInt16(bufferPosition + i * 8 + 4);
                PollEvent.EventTypeMask outputEvents = (PollEvent.EventTypeMask)context.Memory.ReadInt16(bufferPosition + i * 8 + 6);

                events[i] = new PollEvent(socketFd, socket, inputEvents, outputEvents);
            }

            List <Socket> readEvents  = new List <Socket>();
            List <Socket> writeEvents = new List <Socket>();
            List <Socket> errorEvents = new List <Socket>();

            foreach (PollEvent Event in events)
            {
                bool isValidEvent = false;

                if ((Event.InputEvents & PollEvent.EventTypeMask.Input) != 0)
                {
                    readEvents.Add(Event.Socket.Handle);
                    errorEvents.Add(Event.Socket.Handle);

                    isValidEvent = true;
                }

                if ((Event.InputEvents & PollEvent.EventTypeMask.UrgentInput) != 0)
                {
                    readEvents.Add(Event.Socket.Handle);
                    errorEvents.Add(Event.Socket.Handle);

                    isValidEvent = true;
                }

                if ((Event.InputEvents & PollEvent.EventTypeMask.Output) != 0)
                {
                    writeEvents.Add(Event.Socket.Handle);
                    errorEvents.Add(Event.Socket.Handle);

                    isValidEvent = true;
                }

                if ((Event.InputEvents & PollEvent.EventTypeMask.Error) != 0)
                {
                    errorEvents.Add(Event.Socket.Handle);
                    isValidEvent = true;
                }

                if (!isValidEvent)
                {
                    Logger.PrintWarning(LogClass.ServiceBsd, $"Unsupported Poll input event type: {Event.InputEvents}");
                    return(WriteBsdResult(context, -1, LinuxError.EINVAL));
                }
            }

            try
            {
                System.Net.Sockets.Socket.Select(readEvents, writeEvents, errorEvents, timeout);
            }
            catch (SocketException exception)
            {
                return(WriteWinSock2Error(context, (WsaError)exception.ErrorCode));
            }

            for (int i = 0; i < fdsCount; i++)
            {
                PollEvent Event = events[i];
                context.Memory.WriteInt32(bufferPosition + i * 8, Event.SocketFd);
                context.Memory.WriteInt16(bufferPosition + i * 8 + 4, (short)Event.InputEvents);

                PollEvent.EventTypeMask outputEvents = 0;

                Socket socket = Event.Socket.Handle;

                if (errorEvents.Contains(socket))
                {
                    outputEvents |= PollEvent.EventTypeMask.Error;

                    if (!socket.Connected || !socket.IsBound)
                    {
                        outputEvents |= PollEvent.EventTypeMask.Disconnected;
                    }
                }

                if (readEvents.Contains(socket))
                {
                    if ((Event.InputEvents & PollEvent.EventTypeMask.Input) != 0)
                    {
                        outputEvents |= PollEvent.EventTypeMask.Input;
                    }
                }

                if (writeEvents.Contains(socket))
                {
                    outputEvents |= PollEvent.EventTypeMask.Output;
                }

                context.Memory.WriteInt16(bufferPosition + i * 8 + 6, (short)outputEvents);
            }

            return(WriteBsdResult(context, readEvents.Count + writeEvents.Count + errorEvents.Count, LinuxError.SUCCESS));
        }
Ejemplo n.º 2
0
        // Poll(u32 nfds, u32 timeout, buffer<unknown, 0x21, 0> fds) -> (i32 ret, u32 bsd_errno, buffer<unknown, 0x22, 0>)
        public long Poll(ServiceCtx Context)
        {
            int FdsCount = Context.RequestData.ReadInt32();
            int Timeout  = Context.RequestData.ReadInt32();

            (long BufferPosition, long BufferSize) = Context.Request.GetBufferType0x21();


            if (Timeout < -1 || FdsCount < 0 || (FdsCount * 8) > BufferSize)
            {
                return(WriteBsdResult(Context, -1, LinuxError.EINVAL));
            }

            PollEvent[] Events = new PollEvent[FdsCount];

            for (int i = 0; i < FdsCount; i++)
            {
                int SocketFd = Context.Memory.ReadInt32(BufferPosition + i * 8);

                BsdSocket Socket = RetrieveSocket(SocketFd);

                if (Socket == null)
                {
                    return(WriteBsdResult(Context, -1, LinuxError.EBADF));
                }

                PollEvent.EventTypeMask InputEvents  = (PollEvent.EventTypeMask)Context.Memory.ReadInt16(BufferPosition + i * 8 + 4);
                PollEvent.EventTypeMask OutputEvents = (PollEvent.EventTypeMask)Context.Memory.ReadInt16(BufferPosition + i * 8 + 6);

                Events[i] = new PollEvent(SocketFd, Socket, InputEvents, OutputEvents);
            }

            List <Socket> ReadEvents  = new List <Socket>();
            List <Socket> WriteEvents = new List <Socket>();
            List <Socket> ErrorEvents = new List <Socket>();

            foreach (PollEvent Event in Events)
            {
                bool IsValidEvent = false;

                if ((Event.InputEvents & PollEvent.EventTypeMask.Input) != 0)
                {
                    ReadEvents.Add(Event.Socket.Handle);
                    ErrorEvents.Add(Event.Socket.Handle);

                    IsValidEvent = true;
                }

                if ((Event.InputEvents & PollEvent.EventTypeMask.UrgentInput) != 0)
                {
                    ReadEvents.Add(Event.Socket.Handle);
                    ErrorEvents.Add(Event.Socket.Handle);

                    IsValidEvent = true;
                }

                if ((Event.InputEvents & PollEvent.EventTypeMask.Output) != 0)
                {
                    WriteEvents.Add(Event.Socket.Handle);
                    ErrorEvents.Add(Event.Socket.Handle);

                    IsValidEvent = true;
                }

                if ((Event.InputEvents & PollEvent.EventTypeMask.Error) != 0)
                {
                    ErrorEvents.Add(Event.Socket.Handle);
                    IsValidEvent = true;
                }

                if (!IsValidEvent)
                {
                    Logger.PrintWarning(LogClass.ServiceBsd, $"Unsupported Poll input event type: {Event.InputEvents}");
                    return(WriteBsdResult(Context, -1, LinuxError.EINVAL));
                }
            }

            try
            {
                System.Net.Sockets.Socket.Select(ReadEvents, WriteEvents, ErrorEvents, Timeout);
            }
            catch (SocketException Exception)
            {
                return(WriteWinSock2Error(Context, (WSAError)Exception.ErrorCode));
            }

            for (int i = 0; i < FdsCount; i++)
            {
                PollEvent Event = Events[i];
                Context.Memory.WriteInt32(BufferPosition + i * 8, Event.SocketFd);
                Context.Memory.WriteInt16(BufferPosition + i * 8 + 4, (short)Event.InputEvents);

                PollEvent.EventTypeMask OutputEvents = 0;

                Socket Socket = Event.Socket.Handle;

                if (ErrorEvents.Contains(Socket))
                {
                    OutputEvents |= PollEvent.EventTypeMask.Error;

                    if (!Socket.Connected || !Socket.IsBound)
                    {
                        OutputEvents |= PollEvent.EventTypeMask.Disconnected;
                    }
                }

                if (ReadEvents.Contains(Socket))
                {
                    if ((Event.InputEvents & PollEvent.EventTypeMask.Input) != 0)
                    {
                        OutputEvents |= PollEvent.EventTypeMask.Input;
                    }
                }

                if (WriteEvents.Contains(Socket))
                {
                    OutputEvents |= PollEvent.EventTypeMask.Output;
                }

                Context.Memory.WriteInt16(BufferPosition + i * 8 + 6, (short)OutputEvents);
            }

            return(WriteBsdResult(Context, ReadEvents.Count + WriteEvents.Count + ErrorEvents.Count, LinuxError.SUCCESS));
        }