]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - win/inspircd_namedpipe.cpp
more fixes
[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)
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                         if (HaveMemoryStats)\r
87                         {\r
88                                 stat << "workingset " << MemCounters.WorkingSetSize << std::endl;\r
89                                 stat << "pagefile " << MemCounters.PagefileUsage << std::endl;\r
90                                 stat << "pagefaults " << MemCounters.PageFaultCount << std::endl;\r
91                         }\r
92 \r
93                         stat << "END" << std::endl;\r
94 \r
95                         /* This is a blocking call and will succeed, so long as the client doesnt disconnect */\r
96                         Success = WriteFile(Pipe, stat.str().data(), stat.str().length(), &Written, NULL);\r
97 \r
98                         FlushFileBuffers(Pipe);\r
99                         DisconnectNamedPipe(Pipe);\r
100                 }\r
101                 CloseHandle(Pipe);\r
102         }\r
103 }\r
104 \r
105 const  char IPCThread::GetStatus()\r
106 {\r
107         return *status;\r
108 }\r
109 \r
110 void IPCThread::ClearStatus()\r
111 {\r
112         *status = '\0';\r
113 }\r
114 \r
115 int IPCThread::GetResult()\r
116 {\r
117         return result;\r
118 }\r
119 \r
120 void IPCThread::SetResult(int newresult)\r
121 {\r
122         result = newresult;\r
123 }\r
124 \r
125 \r
126 IPC::IPC(InspIRCd* Srv) : ServerInstance(Srv)
127 {
128         /* The IPC pipe is threaded */
129         thread = new IPCThread(Srv);
130         Srv->Threads->Create(thread);
131 }
132
133 void IPC::Check()
134 {
135         switch (thread->GetStatus())
136         {
137                 case 'N':
138                         /* No-Operation */
139                         thread->SetResult(0);
140                         thread->ClearStatus();
141                 break;
142                 case '1':
143                         /* Rehash */
144                         ServerInstance->Rehash("due to rehash command from GUI");
145                         thread->SetResult(0);
146                         thread->ClearStatus();
147                 break;
148                 case '2':
149                         /* Shutdown */
150                         thread->SetResult(0);
151                         thread->ClearStatus();
152                         ServerInstance->Exit(EXIT_STATUS_NOERROR);
153                 break;
154                 case '3':
155                         /* Restart */
156                         thread->SetResult(0);
157                         thread->ClearStatus();
158                         ServerInstance->Restart("Restarting due to command from GUI");
159                 break;
160         }
161 }
162
163 IPC::~IPC()
164 {
165         thread->SetExitFlag();
166         delete thread;
167 }