]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - win/inspircd_namedpipe.cpp
30aab9cd49874d1d8db060ed14bf08570d82667f
[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 \r
66                         PROCESS_MEMORY_COUNTERS MemCounters;\r
67 \r
68                         bool HaveMemoryStats = GetProcessMemoryInfo(GetCurrentProcess(), &MemCounters, sizeof(MemCounters));\r
69 \r
70                         stat << "name " << ServerInstance->Config->ServerName << std::endl;\r
71                         stat << "gecos " << ServerInstance->Config->ServerDesc << std::endl;\r
72                         stat << "numlocalusers " << ServerInstance->Users->LocalUserCount() << std::endl;\r
73                         stat << "numusers " << ServerInstance->Users->clientlist->size() << std::endl;\r
74                         stat << "numchannels " << ServerInstance->chanlist->size() << std::endl;\r
75                         stat << "numopers " << ServerInstance->Users->OperCount() << std::endl;\r
76                         stat << "timestamp " << ServerInstance->Time() << std::endl;\r
77                         stat << "pid " << GetProcessId(GetCurrentProcess()) << std::endl;\r
78                         stat << "request " << oldrequest << std::endl;\r
79                         stat << "result " << this->GetResult() << std::endl;\r
80                         if (HaveMemoryStats)\r
81                         {\r
82                                 stat << "workingset " << MemCounters.WorkingSetSize << std::endl;\r
83                                 stat << "pagefile " << MemCounters.PagefileUsage << std::endl;\r
84                                 stat << "pagefaults " << MemCounters.PageFaultCount << std::endl;\r
85                         }\r
86 \r
87                         stat << "END" << std::endl;\r
88 \r
89                         /* This is a blocking call and will succeed, so long as the client doesnt disconnect */\r
90                         Success = WriteFile(Pipe, stat.str().data(), stat.str().length(), &Written, NULL);\r
91 \r
92                         FlushFileBuffers(Pipe);\r
93                         DisconnectNamedPipe(Pipe);\r
94                 }\r
95                 CloseHandle(Pipe);\r
96         }\r
97 }\r
98 \r
99 const  char IPCThread::GetStatus()\r
100 {\r
101         return *status;\r
102 }\r
103 \r
104 void IPCThread::ClearStatus()\r
105 {\r
106         *status = '\0';\r
107 }\r
108 \r
109 int IPCThread::GetResult()\r
110 {\r
111         return result;\r
112 }\r
113 \r
114 void IPCThread::SetResult(int newresult)\r
115 {\r
116         result = newresult;\r
117 }\r
118 \r
119 \r
120 IPC::IPC(InspIRCd* Srv) : ServerInstance(Srv)
121 {
122         /* The IPC pipe is threaded */
123         thread = new IPCThread(Srv);
124         Srv->Threads->Create(thread);
125 }
126
127 void IPC::Check()
128 {
129         switch (thread->GetStatus())
130         {
131                 case 'N':
132                         /* No-Operation */
133                         thread->SetResult(0);
134                         thread->ClearStatus();
135                 break;
136                 case '1':
137                         /* Rehash */
138                         ServerInstance->Rehash("due to rehash command from GUI");
139                         thread->SetResult(0);
140                         thread->ClearStatus();
141                 break;
142                 case '2':
143                         /* Shutdown */
144                         thread->SetResult(0);
145                         thread->ClearStatus();
146                         ServerInstance->Exit(EXIT_STATUS_NOERROR);
147                 break;
148                 case '3':
149                         /* Restart */
150                         thread->SetResult(0);
151                         thread->ClearStatus();
152                         ServerInstance->Restart("Restarting due to command from GUI");
153                 break;
154         }
155 }
156
157 IPC::~IPC()
158 {
159         thread->SetExitFlag();
160         delete thread;
161 }