]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - win/inspircd_namedpipe.cpp
632c2cca0084ee836f79e7ea2ae62bd3d2a65cfe
[user/henk/code/inspircd.git] / win / inspircd_namedpipe.cpp
1 /*
2  * InspIRCd -- Internet Relay Chat Daemon
3  *
4  *   Copyright (C) 2008 Craig Edwards <craigedwards@brainbox.cc>
5  *
6  * This file is part of InspIRCd.  InspIRCd is free software: you can
7  * redistribute it and/or modify it under the terms of the GNU General Public
8  * License as published by the Free Software Foundation, version 2.
9  *
10  * This program is distributed in the hope that it will be useful, but WITHOUT
11  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
12  * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
13  * details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
17  */
18
19 \r
20 #include "inspircd.h"\r
21 #include "threadengine.h"\r
22 #include "inspircd_namedpipe.h"\r
23 #include "exitcodes.h"\r
24 #include <windows.h>\r
25 #include <psapi.h>\r
26 \r
27 \r
28 IPCThread::IPCThread()\r
29 {\r
30         if (!initwmi())\r
31                 ServerInstance->Logs->Log("IPC", DEBUG, "Could not initialise WMI. CPU percantage reports will not be available.");\r
32 }\r
33 \r
34 IPCThread::~IPCThread()\r
35 {\r
36         donewmi();\r
37 }\r
38 \r
39 void IPCThread::Run()\r
40 {\r
41         LPTSTR Pipename = "\\\\.\\pipe\\InspIRCdStatus";\r
42 \r
43         while (GetExitFlag() == false)\r
44         {\r
45                 Pipe = CreateNamedPipe (Pipename,\r
46                                         PIPE_ACCESS_DUPLEX, // read/write access\r
47                                         PIPE_TYPE_MESSAGE | // message type pipe\r
48                                         PIPE_READMODE_MESSAGE | // message-read mode\r
49                                         PIPE_WAIT, // blocking mode\r
50                                         PIPE_UNLIMITED_INSTANCES, // max. instances\r
51                                         MAXBUF, // output buffer size\r
52                                         MAXBUF, // input buffer size\r
53                                         1000, // client time-out\r
54                                         NULL); // no security attribute\r
55 \r
56                 if (Pipe == INVALID_HANDLE_VALUE)\r
57                 {\r
58                         SleepEx(10, true);\r
59                         continue;\r
60                 }\r
61 \r
62                 Connected = ConnectNamedPipe(Pipe, NULL) ? TRUE : (GetLastError() == ERROR_PIPE_CONNECTED);\r
63 \r
64                 if (Connected)\r
65                 {\r
66                         Success = ReadFile (Pipe, // handle to pipe\r
67                                 this->status, // buffer to receive data\r
68                                 1, // size of buffer\r
69                                 &BytesRead, // number of bytes read\r
70                                 NULL); // not overlapped I/O\r
71 \r
72                         if (!Success || !BytesRead)\r
73                         {\r
74                                 CloseHandle(Pipe);\r
75                                 continue;\r
76                         }\r
77 \r
78                         const char oldrequest = this->GetStatus();\r
79 \r
80                         /* Wait for main thread to pick up status change */\r
81                         while (this->GetStatus())\r
82                                 SleepEx(10, true);\r
83 \r
84                         std::stringstream stat;\r
85                         DWORD Written = 0;\r
86                         float kbitpersec_in, kbitpersec_out, kbitpersec_total;\r
87 \r
88                         PROCESS_MEMORY_COUNTERS MemCounters;\r
89 \r
90                         ServerInstance->SE->GetStats(kbitpersec_in, kbitpersec_out, kbitpersec_total);\r
91 \r
92                         bool HaveMemoryStats = GetProcessMemoryInfo(GetCurrentProcess(), &MemCounters, sizeof(MemCounters));\r
93 \r
94                         stat << "name " << ServerInstance->Config->ServerName << std::endl;\r
95                         stat << "gecos " << ServerInstance->Config->ServerDesc << std::endl;\r
96                         stat << "numlocalusers " << ServerInstance->Users->LocalUserCount() << std::endl;\r
97                         stat << "numusers " << ServerInstance->Users->clientlist->size() << std::endl;\r
98                         stat << "numchannels " << ServerInstance->chanlist->size() << std::endl;\r
99                         stat << "numopers " << ServerInstance->Users->OperCount() << std::endl;\r
100                         stat << "timestamp " << ServerInstance->Time() << std::endl;\r
101                         stat << "pid " << GetProcessId(GetCurrentProcess()) << std::endl;\r
102                         stat << "request " << oldrequest << std::endl;\r
103                         stat << "result " << this->GetResult() << std::endl;\r
104                         stat << "kbitspersectotal " << kbitpersec_total << std::endl;\r
105                         stat << "kbitspersecout " << kbitpersec_out << std::endl;\r
106                         stat << "kbitspersecin " << kbitpersec_in << std::endl;\r
107                         stat << "uptime " << ServerInstance->Time() - ServerInstance->startup_time << std::endl;\r
108                         stat << "cpu " << getcpu() << std::endl;\r
109                         if (HaveMemoryStats)\r
110                         {\r
111                                 stat << "workingset " << MemCounters.WorkingSetSize << std::endl;\r
112                                 stat << "pagefile " << MemCounters.PagefileUsage << std::endl;\r
113                                 stat << "pagefaults " << MemCounters.PageFaultCount << std::endl;\r
114                         }\r
115 \r
116                         stat << "END" << std::endl;\r
117 \r
118                         /* This is a blocking call and will succeed, so long as the client doesnt disconnect */\r
119                         Success = WriteFile(Pipe, stat.str().data(), stat.str().length(), &Written, NULL);\r
120 \r
121                         FlushFileBuffers(Pipe);\r
122                         DisconnectNamedPipe(Pipe);\r
123                 }\r
124                 CloseHandle(Pipe);\r
125         }\r
126 }\r
127 \r
128 const  char IPCThread::GetStatus()\r
129 {\r
130         return *status;\r
131 }\r
132 \r
133 void IPCThread::ClearStatus()\r
134 {\r
135         *status = '\0';\r
136 }\r
137 \r
138 int IPCThread::GetResult()\r
139 {\r
140         return result;\r
141 }\r
142 \r
143 void IPCThread::SetResult(int newresult)\r
144 {\r
145         result = newresult;\r
146 }\r
147 \r
148 \r
149 IPC::IPC()\r
150 {\r
151         /* The IPC pipe is threaded */\r
152         thread = new IPCThread();\r
153         ServerInstance->Threads->Start(thread);\r
154 }\r
155 \r
156 void IPC::Check()\r
157 {\r
158         switch (thread->GetStatus())\r
159         {\r
160                 case 'N':\r
161                         /* No-Operation */\r
162                         thread->SetResult(0);\r
163                         thread->ClearStatus();\r
164                 break;\r
165                 case '1':\r
166                         /* Rehash */\r
167                         ServerInstance->Rehash("due to rehash command from GUI");\r
168                         thread->SetResult(0);\r
169                         thread->ClearStatus();\r
170                 break;\r
171                 case '2':\r
172                         /* Shutdown */\r
173                         thread->SetResult(0);\r
174                         thread->ClearStatus();\r
175                         ServerInstance->Exit(EXIT_STATUS_NOERROR);\r
176                 break;\r
177                 case '3':\r
178                         /* Restart */\r
179                         thread->SetResult(0);\r
180                         thread->ClearStatus();\r
181                         ServerInstance->Restart("Restarting due to command from GUI");\r
182                 break;\r
183                 case '4':\r
184                         /* Toggle debug */\r
185                         thread->SetResult(0);\r
186                         thread->ClearStatus();\r
187                         ServerInstance->Config->cmdline.forcedebug = !ServerInstance->Config->cmdline.forcedebug;\r
188                 break;\r
189         }\r
190 }\r
191 \r
192 IPC::~IPC()\r
193 {\r
194         thread->SetExitFlag();\r
195         delete thread;\r
196 }\r