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)); }
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); }