private void ServerLoop() { _selfProcess = KernelStatic.GetCurrentProcess(); if (SmObjectFactory != null) { _context.Syscall.ManageNamedPort("sm:", 50, out int serverPortHandle); AddPort(serverPortHandle, SmObjectFactory); InitDone.Set(); } else { InitDone.Dispose(); } KThread thread = KernelStatic.GetCurrentThread(); ulong messagePtr = thread.TlsAddress; _context.Syscall.SetHeapSize(0x200000, out ulong heapAddr); _selfProcess.CpuMemory.Write(messagePtr + 0x0, 0); _selfProcess.CpuMemory.Write(messagePtr + 0x4, 2 << 10); _selfProcess.CpuMemory.Write(messagePtr + 0x8, heapAddr | ((ulong)PointerBufferSize << 48)); int replyTargetHandle = 0; while (true) { int[] portHandles = _portHandles.ToArray(); int[] sessionHandles = _sessionHandles.ToArray(); int[] handles = new int[portHandles.Length + sessionHandles.Length]; portHandles.CopyTo(handles, 0); sessionHandles.CopyTo(handles, portHandles.Length); // We still need a timeout here to allow the service to pick up and listen new sessions... var rc = _context.Syscall.ReplyAndReceive(handles, replyTargetHandle, 1000000L, out int signaledIndex); thread.HandlePostSyscall(); if (!thread.Context.Running) { break; } replyTargetHandle = 0; if (rc == KernelResult.Success && signaledIndex >= portHandles.Length) { // We got a IPC request, process it, pass to the appropriate service if needed. int signaledHandle = handles[signaledIndex]; if (Process(signaledHandle, heapAddr)) { replyTargetHandle = signaledHandle; } } else { if (rc == KernelResult.Success) { // We got a new connection, accept the session to allow servicing future requests. if (_context.Syscall.AcceptSession(handles[signaledIndex], out int serverSessionHandle) == KernelResult.Success) { IpcService obj = _ports[handles[signaledIndex]].Invoke(); AddSessionObj(serverSessionHandle, obj); } } _selfProcess.CpuMemory.Write(messagePtr + 0x0, 0); _selfProcess.CpuMemory.Write(messagePtr + 0x4, 2 << 10); _selfProcess.CpuMemory.Write(messagePtr + 0x8, heapAddr | ((ulong)PointerBufferSize << 48)); } } }
private void ServerLoop() { if (SmObject != null) { _context.Syscall.ManageNamedPort("sm:", 50, out int serverPortHandle); AddPort(serverPortHandle, SmObject); InitDone.Set(); } else { InitDone.Dispose(); } KThread thread = _context.Scheduler.GetCurrentThread(); ulong messagePtr = thread.TlsAddress; _context.Syscall.SetHeapSize(0x200000, out ulong heapAddr); _selfProcess.CpuMemory.Write(messagePtr + 0x0, 0); _selfProcess.CpuMemory.Write(messagePtr + 0x4, 2 << 10); _selfProcess.CpuMemory.Write(messagePtr + 0x8, heapAddr | ((ulong)PointerBufferSize << 48)); int replyTargetHandle = 0; while (true) { int[] handles = _portHandles.ToArray(); for (int i = 0; i < handles.Length; i++) { if (_context.Syscall.AcceptSession(handles[i], out int serverSessionHandle) == KernelResult.Success) { AddSessionObj(serverSessionHandle, _ports[handles[i]]); } } handles = _sessionHandles.ToArray(); var rc = _context.Syscall.ReplyAndReceive(handles, replyTargetHandle, 1000000L, out int signaledIndex); thread.HandlePostSyscall(); if (!thread.Context.Running) { break; } replyTargetHandle = 0; if (rc == KernelResult.Success && signaledIndex != -1) { int signaledHandle = handles[signaledIndex]; if (Process(signaledHandle, heapAddr)) { replyTargetHandle = signaledHandle; } } else { _selfProcess.CpuMemory.Write(messagePtr + 0x0, 0); _selfProcess.CpuMemory.Write(messagePtr + 0x4, 2 << 10); _selfProcess.CpuMemory.Write(messagePtr + 0x8, heapAddr | ((ulong)PointerBufferSize << 48)); } } }