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