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