예제 #1
0
파일: IClient.cs 프로젝트: mailwl/Ryujinx
        private ResultCode SocketInternal(ServiceCtx context, bool exempt)
        {
            BsdAddressFamily domain   = (BsdAddressFamily)context.RequestData.ReadInt32();
            BsdSocketType    type     = (BsdSocketType)context.RequestData.ReadInt32();
            ProtocolType     protocol = (ProtocolType)context.RequestData.ReadInt32();

            BsdSocketCreationFlags creationFlags = (BsdSocketCreationFlags)((int)type >> (int)BsdSocketCreationFlags.FlagsShift);

            type &= BsdSocketType.TypeMask;

            if (domain == BsdAddressFamily.Unknown)
            {
                return(WriteBsdResult(context, -1, LinuxError.EPROTONOSUPPORT));
            }
            else if ((type == BsdSocketType.Seqpacket || type == BsdSocketType.Raw) && !_isPrivileged)
            {
                if (domain != BsdAddressFamily.InterNetwork || type != BsdSocketType.Raw || protocol != ProtocolType.Icmp)
                {
                    return(WriteBsdResult(context, -1, LinuxError.ENOENT));
                }
            }

            AddressFamily netDomain = ConvertBsdAddressFamily(domain);

            if (protocol == ProtocolType.IP)
            {
                if (type == BsdSocketType.Stream)
                {
                    protocol = ProtocolType.Tcp;
                }
                else if (type == BsdSocketType.Dgram)
                {
                    protocol = ProtocolType.Udp;
                }
            }

            ISocket newBsdSocket = new ManagedSocket(netDomain, (SocketType)type, protocol);

            newBsdSocket.Blocking = !creationFlags.HasFlag(BsdSocketCreationFlags.NonBlocking);

            LinuxError errno = LinuxError.SUCCESS;

            int newSockFd = _context.RegisterFileDescriptor(newBsdSocket);

            if (newSockFd == -1)
            {
                errno = LinuxError.EBADF;
            }

            if (exempt)
            {
                newBsdSocket.Disconnect();
            }

            return(WriteBsdResult(context, newSockFd, errno));
        }
예제 #2
0
        public LinuxError Poll(List <PollEvent> events, int timeoutMilliseconds, out int updatedCount)
        {
            List <Socket> readEvents  = new List <Socket>();
            List <Socket> writeEvents = new List <Socket>();
            List <Socket> errorEvents = new List <Socket>();

            updatedCount = 0;

            foreach (PollEvent evnt in events)
            {
                ManagedSocket socket = (ManagedSocket)evnt.FileDescriptor;

                bool isValidEvent = false;

                if ((evnt.Data.InputEvents & PollEventTypeMask.Input) != 0)
                {
                    readEvents.Add(socket.Socket);
                    errorEvents.Add(socket.Socket);

                    isValidEvent = true;
                }

                if ((evnt.Data.InputEvents & PollEventTypeMask.UrgentInput) != 0)
                {
                    readEvents.Add(socket.Socket);
                    errorEvents.Add(socket.Socket);

                    isValidEvent = true;
                }

                if ((evnt.Data.InputEvents & PollEventTypeMask.Output) != 0)
                {
                    writeEvents.Add(socket.Socket);
                    errorEvents.Add(socket.Socket);

                    isValidEvent = true;
                }

                if ((evnt.Data.InputEvents & PollEventTypeMask.Error) != 0)
                {
                    errorEvents.Add(socket.Socket);

                    isValidEvent = true;
                }

                if (!isValidEvent)
                {
                    Logger.Warning?.Print(LogClass.ServiceBsd, $"Unsupported Poll input event type: {evnt.Data.InputEvents}");
                    return(LinuxError.EINVAL);
                }
            }

            try
            {
                int actualTimeoutMicroseconds = timeoutMilliseconds == -1 ? -1 : timeoutMilliseconds * 1000;

                Socket.Select(readEvents, writeEvents, errorEvents, actualTimeoutMicroseconds);
            }
            catch (SocketException exception)
            {
                return(WinSockHelper.ConvertError((WsaError)exception.ErrorCode));
            }

            foreach (PollEvent evnt in events)
            {
                Socket socket = ((ManagedSocket)evnt.FileDescriptor).Socket;

                PollEventTypeMask outputEvents = 0;

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

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

                if (readEvents.Contains(socket))
                {
                    if ((evnt.Data.InputEvents & PollEventTypeMask.Input) != 0)
                    {
                        outputEvents |= PollEventTypeMask.Input;
                    }
                }

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

                evnt.Data.OutputEvents = outputEvents;
            }

            updatedCount = readEvents.Count + writeEvents.Count + errorEvents.Count;

            return(LinuxError.SUCCESS);
        }