private static bool IsUnixExecutable(string path) { var platform = Environment.OSVersion.Platform; if (platform != PlatformID.Unix && platform != PlatformID.MacOSX) { return(false); } return(Posix.access(path, Posix.X_OK) == 0); }
private IntPtr RegisterPlatformSpecific(string absoluteFilePath, out NativeLibrary.SymbolLookupDelegate symbolLookup) { if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) { var handle = Posix.dlopen(absoluteFilePath, Posix.RTLD_LAZY | Posix.RTLD_GLOBAL); if (handle == IntPtr.Zero) { throw new NativeLoaderException( $"Failed to load '{absoluteFilePath}'. dlerror: {Marshal.PtrToStringAnsi(Posix.dlerror())}"); } symbolLookup = Posix.dlsym; return(handle); } if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) { var handle = Posix.dlopen(absoluteFilePath, Posix.RTLD_LAZY | Posix.RTLD_GLOBAL); if (handle == IntPtr.Zero) { throw new NativeLoaderException( $"Failed to load '{absoluteFilePath}'. dlerror: {Marshal.PtrToStringAnsi(Posix.dlerror())}"); } symbolLookup = Posix.dlsym; return(handle); } if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { var dllDirectory = Path.GetDirectoryName(absoluteFilePath); var fileName = Path.GetFileName(absoluteFilePath); Windows.SetDllDirectory(dllDirectory); var handle = Windows.LoadLibrary(fileName); if (handle == IntPtr.Zero) { throw new NativeLoaderException( $"Failed to load '{absoluteFilePath}'. LoadLibrary: {Windows.GetLastError():X8}"); } symbolLookup = Windows.GetProcAddress; return(handle); } throw new NativeLoaderException($"Platform '{Environment.OSVersion.Platform}' is not supported."); }
static internal void UnregisterCallResult(IntPtr pCallback, SteamAPICall_t callback) { if (Config.Os == OsType.Windows) { Win64.SteamAPI_UnregisterCallResult(pCallback, callback); } else if (Config.Os == OsType.Posix) { Posix.SteamAPI_UnregisterCallResult(pCallback, callback); } else { throw new System.Exception("this platform isn't supported"); } }
static internal bool GameServer_Init(uint unIP, ushort usPort, ushort usGamePort, ushort usQueryPort, int eServerMode, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(Utf8StringToNative))] string pchVersionString) { if (Config.Os == OsType.Windows) { return(Win64.SteamInternal_GameServer_Init(unIP, usPort, usGamePort, usQueryPort, eServerMode, pchVersionString)); } else if (Config.Os == OsType.Posix) { return(Posix.SteamInternal_GameServer_Init(unIP, usPort, usGamePort, usQueryPort, eServerMode, pchVersionString)); } else { throw new System.Exception("this platform isn't supported"); } }
static internal HSteamPipe GetHSteamPipe() { if (Config.Os == OsType.Windows) { return(Win64.SteamGameServer_GetHSteamPipe()); } else if (Config.Os == OsType.Posix) { return(Posix.SteamGameServer_GetHSteamPipe()); } else { throw new System.Exception("this platform isn't supported"); } }
static internal void Shutdown() { if (Config.Os == OsType.Windows) { Win64.SteamGameServer_Shutdown(); } else if (Config.Os == OsType.Posix) { Posix.SteamGameServer_Shutdown(); } else { throw new System.Exception("this platform isn't supported"); } }
static internal void RunCallbacks() { if (Config.Os == OsType.Windows) { Win64.SteamAPI_RunCallbacks(); } else if (Config.Os == OsType.Posix) { Posix.SteamAPI_RunCallbacks(); } else { throw new System.Exception("this platform isn't supported"); } }
static internal bool Init() { if (Config.Os == OsType.Windows) { return(Win64.SteamAPI_Init()); } else if (Config.Os == OsType.Posix) { return(Posix.SteamAPI_Init()); } else { throw new System.Exception("this platform isn't supported"); } }
static internal bool RestartAppIfNecessary(uint unOwnAppID) { if (Config.Os == OsType.Windows) { return(Win64.SteamAPI_RestartAppIfNecessary(unOwnAppID)); } else if (Config.Os == OsType.Posix) { return(Posix.SteamAPI_RestartAppIfNecessary(unOwnAppID)); } else { throw new System.Exception("this platform isn't supported"); } }
static internal IntPtr CreateInterface([MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(Utf8StringToNative))] string version) { if (Config.Os == OsType.Windows) { return(Win64.SteamInternal_CreateInterface(version)); } else if (Config.Os == OsType.Posix) { return(Posix.SteamInternal_CreateInterface(version)); } else { throw new System.Exception("this platform isn't supported"); } }
public static void PreloadDll(string dllName) { var dllDir = GetDirectedDllDirectory(); // Not using OperatingSystem.Platform. // See: https://www.mono-project.com/docs/faq/technical/#how-to-detect-the-execution-platform if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { Win32.LoadDll(dllDir, dllName); } else { Posix.LoadDll(dllDir, dllName); } }
static internal IntPtr CreateInterface(string version) { if (Config.Os == OsType.Windows) { return(Win64.SteamInternal_CreateInterface(version)); } else if (Config.Os == OsType.Posix) { return(Posix.SteamInternal_CreateInterface(version)); } else { throw new System.Exception("this platform isn't supported"); } }
static internal IntPtr FindOrCreateGameServerInterface(int steamuser, string versionname) { if (Config.Os == OsType.Windows) { return(Win64.SteamInternal_FindOrCreateGameServerInterface(steamuser, versionname)); } else if (Config.Os == OsType.Posix) { return(Posix.SteamInternal_FindOrCreateGameServerInterface(steamuser, versionname)); } else { throw new System.Exception("this platform isn't supported"); } }
static internal bool GameServer_Init(uint unIP, ushort usPort, ushort usGamePort, ushort usQueryPort, int eServerMode, string pchVersionString) { if (Config.Os == OsType.Windows) { return(Win64.SteamInternal_GameServer_Init(unIP, usPort, usGamePort, usQueryPort, eServerMode, pchVersionString)); } else if (Config.Os == OsType.Posix) { return(Posix.SteamInternal_GameServer_Init(unIP, usPort, usGamePort, usQueryPort, eServerMode, pchVersionString)); } else { throw new System.Exception("this platform isn't supported"); } }
private static bool IsMusl() { #if NETSTANDARD1_1 var cpu = RuntimeInformation.ProcessArchitecture; switch (cpu) { case Architecture.X86: return(Posix.AccessCheck("/lib/libc.musl-x86.so.1", 0) == 0); case Architecture.X64: return(Posix.AccessCheck("/lib/libc.musl-x86_64.so.1", 0) == 0); case Architecture.Arm: return(Posix.AccessCheck("/lib/libc.musl-armv7.so.1", 0) == 0); case Architecture.Arm64: return(Posix.AccessCheck("/lib/libc.musl-aarch64.so.1", 0) == 0); default: throw new PlatformNotSupportedException(cpu.ToString()); } #else using (var proc = Process.GetCurrentProcess()) { foreach (ProcessModule mod in proc.Modules) { var fileName = mod.FileName; if (!fileName.Contains("libc")) { continue; } if (fileName.Contains("musl")) { return(true); } break; } } return(false); #endif }
/// <summary> /// unix specific code, we want to poll for packets /// otherwise if we call pcap_dispatch() the read() will block /// and won't resume until a packet arrives OR until a signal /// occurs /// </summary> /// <param name="timeout"> /// Timeout chosen to allow the capture thread to loop frequently enough /// to enable it to properly exit when the user requests it to but /// infrequently enough to cause any noticable performance overhead /// </param> /// <returns>true if poll was successfull and we have data to read, false otherwise</returns> protected internal bool PollFileDescriptor(int timeout = 500) { if (FileDescriptor < 0) { // Either this is a File Capture, or Windows // Assume we have data to read return(true); } var pollFds = new Posix.Pollfd[1]; pollFds[0].fd = FileDescriptor; pollFds[0].events = Posix.PollEvents.POLLPRI | Posix.PollEvents.POLLIN; var result = Posix.Poll(pollFds, (uint)pollFds.Length, timeout); // if we have no poll results, we don't have anything to read // -1 means error // 0 means timeout // non-negative means we got something return(result != 0); }
/// <summary> /// The capture thread /// </summary> protected virtual void CaptureThread(CancellationToken cancellationToken) { if (!Opened) { throw new DeviceNotReadyException("Capture called before PcapDevice.Open()"); } var Callback = new LibPcapSafeNativeMethods.pcap_handler(PacketHandler); Posix.Pollfd[] pollFds = null; // unix specific code if (UsePosixPoll) { // retrieve the file descriptor of the adapter for use with poll() var captureFileDescriptor = LibPcapSafeNativeMethods.pcap_fileno(PcapHandle); if (captureFileDescriptor == -1) { SendCaptureStoppedEvent(CaptureStoppedEventStatus.ErrorWhileCapturing); return; } pollFds = new Posix.Pollfd[1]; pollFds[0].fd = captureFileDescriptor; pollFds[0].events = Posix.PollEvents.POLLPRI | Posix.PollEvents.POLLIN; } while (!cancellationToken.IsCancellationRequested) { // unix specific code, we want to poll for packets // otherwise if we call pcap_dispatch() the read() will block // and won't resume until a packet arrives OR until a signal // occurs if (pollFds != null) { // Timeout chosen to allow the capture thread to loop frequently enough // to enable it to properly exit when the user requests it to but // infrequently enough to cause any noticable performance overhead const int millisecondTimeout = 500; // block here var result = Posix.Poll(pollFds, (uint)pollFds.Length, millisecondTimeout); // if we have no poll results, just loop if (result <= 0) { continue; } // fall through here to the pcap_dispatch() call } int res = LibPcapSafeNativeMethods.pcap_dispatch(PcapHandle, m_pcapPacketCount, Callback, IntPtr.Zero); // pcap_dispatch() returns the number of packets read or, a status value if the value // is negative if (res <= 0) { switch (res) // Check pcap loop status results and notify upstream. { case Pcap.LOOP_USER_TERMINATED: // User requsted loop termination with StopCapture() SendCaptureStoppedEvent(CaptureStoppedEventStatus.CompletedWithoutError); return; case Pcap.LOOP_COUNT_EXHAUSTED: // m_pcapPacketCount exceeded (successful exit) { // NOTE: pcap_dispatch() returns 0 when a timeout occurrs so to prevent timeouts // from causing premature exiting from the capture loop we only consider // exhausted events to cause an escape from the loop when they are from // offline devices, ie. files read from disk if (this is CaptureFileReaderDevice) { SendCaptureStoppedEvent(CaptureStoppedEventStatus.CompletedWithoutError); return; } break; } case Pcap.LOOP_EXIT_WITH_ERROR: // An error occurred whilst capturing. SendCaptureStoppedEvent(CaptureStoppedEventStatus.ErrorWhileCapturing); return; default: // This can only be triggered by a bug in libpcap. throw new PcapException("Unknown pcap_loop exit status."); } } else // res > 0 { // if we aren't capturing infinitely we need to account for // the packets that we read if (m_pcapPacketCount != Pcap.InfinitePacketCount) { // take away for the packets read if (m_pcapPacketCount >= res) { m_pcapPacketCount -= res; } else { m_pcapPacketCount = 0; } // no more packets to capture, we are finished capturing if (m_pcapPacketCount == 0) { SendCaptureStoppedEvent(CaptureStoppedEventStatus.CompletedWithoutError); return; } } } } SendCaptureStoppedEvent(CaptureStoppedEventStatus.CompletedWithoutError); }
// TODO return better error messages here. public static string GetError(uint status) => OperatingSystem.IsWindows() ? Windows.GetError(status) : Posix.GetError(status);