+/*
+ * InspIRCd -- Internet Relay Chat Daemon
+ *
+ * Copyright (C) 2008 Craig Edwards <craigedwards@brainbox.cc>
+ *
+ * This file is part of InspIRCd. InspIRCd is free software: you can
+ * redistribute it and/or modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation, version 2.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+\r
#include "inspircd.h"\r
#include "threadengine.h"\r
#include "inspircd_namedpipe.h"\r
+#include "exitcodes.h"\r
#include <windows.h>\r
+#include <psapi.h>\r
+\r
+\r
+IPCThread::IPCThread()\r
+{\r
+ if (!initwmi())\r
+ ServerInstance->Logs->Log("IPC", DEBUG, "Could not initialise WMI. CPU percantage reports will not be available.");\r
+}\r
+\r
+IPCThread::~IPCThread()\r
+{\r
+ donewmi();\r
+}\r
\r
void IPCThread::Run()\r
{\r
LPTSTR Pipename = "\\\\.\\pipe\\InspIRCdStatus";\r
\r
- Pipe = CreateNamedPipe ( Pipename,\r
- PIPE_ACCESS_DUPLEX, // read/write access\r
- PIPE_TYPE_MESSAGE | // message type pipe\r
- PIPE_READMODE_MESSAGE | // message-read mode\r
- PIPE_WAIT, // blocking mode\r
- PIPE_UNLIMITED_INSTANCES, // max. instances\r
- MAXBUF, // output buffer size\r
- MAXBUF, // input buffer size\r
- 1000, // client time-out\r
- NULL); // no security attribute\r
-\r
- if (Pipe == INVALID_HANDLE_VALUE)\r
- return;\r
-\r
- while (GetExitFlag() == false)
+ while (GetExitFlag() == false)\r
{\r
- // Trying connectnamedpipe in sample for CreateNamedPipe\r
- // Wait for the client to connect; if it succeeds,\r
- // the function returns a nonzero value. If the function returns\r
- // zero, GetLastError returns ERROR_PIPE_CONNECTED.\r
+ Pipe = CreateNamedPipe (Pipename,\r
+ PIPE_ACCESS_DUPLEX, // read/write access\r
+ PIPE_TYPE_MESSAGE | // message type pipe\r
+ PIPE_READMODE_MESSAGE | // message-read mode\r
+ PIPE_WAIT, // blocking mode\r
+ PIPE_UNLIMITED_INSTANCES, // max. instances\r
+ MAXBUF, // output buffer size\r
+ MAXBUF, // input buffer size\r
+ 1000, // client time-out\r
+ NULL); // no security attribute\r
+\r
+ if (Pipe == INVALID_HANDLE_VALUE)\r
+ {\r
+ SleepEx(10, true);\r
+ continue;\r
+ }\r
\r
Connected = ConnectNamedPipe(Pipe, NULL) ? TRUE : (GetLastError() == ERROR_PIPE_CONNECTED);\r
\r
if (Connected)\r
{\r
Success = ReadFile (Pipe, // handle to pipe\r
- Request, // buffer to receive data\r
- MAXBUF, // size of buffer\r
+ this->status, // buffer to receive data\r
+ 1, // size of buffer\r
&BytesRead, // number of bytes read\r
NULL); // not overlapped I/O\r
\r
- Request[BytesRead] = '\0';\r
- //printf("Data Received: %s\n",chRequest);\r
-\r
if (!Success || !BytesRead)\r
- break;\r
+ {\r
+ CloseHandle(Pipe);\r
+ continue;\r
+ }\r
+\r
+ const char oldrequest = this->GetStatus();\r
+\r
+ /* Wait for main thread to pick up status change */\r
+ while (this->GetStatus())\r
+ SleepEx(10, true);\r
+\r
+ std::stringstream stat;\r
+ DWORD Written = 0;\r
+ float kbitpersec_in, kbitpersec_out, kbitpersec_total;\r
+\r
+ PROCESS_MEMORY_COUNTERS MemCounters;\r
+\r
+ ServerInstance->SE->GetStats(kbitpersec_in, kbitpersec_out, kbitpersec_total);\r
+\r
+ bool HaveMemoryStats = GetProcessMemoryInfo(GetCurrentProcess(), &MemCounters, sizeof(MemCounters));\r
+\r
+ stat << "name " << ServerInstance->Config->ServerName << std::endl;\r
+ stat << "gecos " << ServerInstance->Config->ServerDesc << std::endl;\r
+ stat << "numlocalusers " << ServerInstance->Users->LocalUserCount() << std::endl;\r
+ stat << "numusers " << ServerInstance->Users->clientlist->size() << std::endl;\r
+ stat << "numchannels " << ServerInstance->chanlist->size() << std::endl;\r
+ stat << "numopers " << ServerInstance->Users->OperCount() << std::endl;\r
+ stat << "timestamp " << ServerInstance->Time() << std::endl;\r
+ stat << "pid " << GetProcessId(GetCurrentProcess()) << std::endl;\r
+ stat << "request " << oldrequest << std::endl;\r
+ stat << "result " << this->GetResult() << std::endl;\r
+ stat << "kbitspersectotal " << kbitpersec_total << std::endl;\r
+ stat << "kbitspersecout " << kbitpersec_out << std::endl;\r
+ stat << "kbitspersecin " << kbitpersec_in << std::endl;\r
+ stat << "uptime " << ServerInstance->Time() - ServerInstance->startup_time << std::endl;\r
+ stat << "cpu " << getcpu() << std::endl;\r
+ if (HaveMemoryStats)\r
+ {\r
+ stat << "workingset " << MemCounters.WorkingSetSize << std::endl;\r
+ stat << "pagefile " << MemCounters.PagefileUsage << std::endl;\r
+ stat << "pagefaults " << MemCounters.PageFaultCount << std::endl;\r
+ }\r
+\r
+ stat << "END" << std::endl;\r
+\r
+ /* This is a blocking call and will succeed, so long as the client doesnt disconnect */\r
+ Success = WriteFile(Pipe, stat.str().data(), stat.str().length(), &Written, NULL);\r
\r
FlushFileBuffers(Pipe);\r
DisconnectNamedPipe(Pipe);\r
}\r
- else\r
- {\r
- // The client could not connect.\r
- CloseHandle(Pipe);\r
- }\r
+ CloseHandle(Pipe);\r
+ }\r
+}\r
+\r
+const char IPCThread::GetStatus()\r
+{\r
+ return *status;\r
+}\r
+\r
+void IPCThread::ClearStatus()\r
+{\r
+ *status = '\0';\r
+}\r
+\r
+int IPCThread::GetResult()\r
+{\r
+ return result;\r
+}\r
+\r
+void IPCThread::SetResult(int newresult)\r
+{\r
+ result = newresult;\r
+}\r
+\r
+\r
+IPC::IPC()\r
+{\r
+ /* The IPC pipe is threaded */\r
+ thread = new IPCThread();\r
+ ServerInstance->Threads->Start(thread);\r
+}\r
\r
- SleepEx(100, FALSE);\r
+void IPC::Check()\r
+{\r
+ switch (thread->GetStatus())\r
+ {\r
+ case 'N':\r
+ /* No-Operation */\r
+ thread->SetResult(0);\r
+ thread->ClearStatus();\r
+ break;\r
+ case '1':\r
+ /* Rehash */\r
+ ServerInstance->Rehash("due to rehash command from GUI");\r
+ thread->SetResult(0);\r
+ thread->ClearStatus();\r
+ break;\r
+ case '2':\r
+ /* Shutdown */\r
+ thread->SetResult(0);\r
+ thread->ClearStatus();\r
+ ServerInstance->Exit(EXIT_STATUS_NOERROR);\r
+ break;\r
+ case '3':\r
+ /* Restart */\r
+ thread->SetResult(0);\r
+ thread->ClearStatus();\r
+ ServerInstance->Restart("Restarting due to command from GUI");\r
+ break;\r
+ case '4':\r
+ /* Toggle debug */\r
+ thread->SetResult(0);\r
+ thread->ClearStatus();\r
+ ServerInstance->Config->cmdline.forcedebug = !ServerInstance->Config->cmdline.forcedebug;\r
+ break;\r
}\r
- CloseHandle(Pipe);\r
}\r
\r
-IPC::IPC(InspIRCd* Srv) : ServerInstance(Srv)
-{
- /* The IPC pipe is threaded */
- thread = new IPCThread(Srv);
- Srv->Threads->Create(thread);
-}
-
-void IPC::Check()
-{
-}
-
-IPC::~IPC()
-{
- thread->SetExitFlag();
- delete thread;
-}
\ No newline at end of file
+IPC::~IPC()\r
+{\r
+ thread->SetExitFlag();\r
+ delete thread;\r
+}\r