]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - src/threadengines/threadengine_win32.cpp
33eb707e4fcc886c595b71fc1c8d9a93b7763a4b
[user/henk/code/inspircd.git] / src / threadengines / threadengine_win32.cpp
1 /*
2  * InspIRCd -- Internet Relay Chat Daemon
3  *
4  *   Copyright (C) 2009 Daniel De Graaf <danieldg@inspircd.org>
5  *   Copyright (C) 2008 Craig Edwards <craigedwards@brainbox.cc>
6  *
7  * This file is part of InspIRCd.  InspIRCd is free software: you can
8  * redistribute it and/or modify it under the terms of the GNU General Public
9  * License as published by the Free Software Foundation, version 2.
10  *
11  * This program is distributed in the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13  * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
14  * details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
18  */
19
20
21 #include "inspircd.h"
22 #include "threadengines/threadengine_win32.h"
23
24 void ThreadEngine::Start(Thread* thread)
25 {
26         DWORD ThreadId = 0;
27         thread->state.handle = CreateThread(NULL, 0, ThreadEngine::Entry, thread, 0, &ThreadId);
28
29         if (thread->state.handle == NULL)
30         {
31                 DWORD lasterr = GetLastError();
32                 std::string err = "Unable to create new thread: " + ConvToStr(lasterr);
33                 SetLastError(ERROR_SUCCESS);
34                 throw CoreException(err);
35         }
36 }
37
38 DWORD WINAPI ThreadEngine::Entry(void* parameter)
39 {
40         Thread* pt = static_cast<Thread*>(parameter);
41         pt->Run();
42         return 0;
43 }
44
45 void ThreadEngine::Stop(Thread* thread)
46 {
47         thread->SetExitFlag();
48         HANDLE handle = thread->state.handle;
49         WaitForSingleObject(handle,INFINITE);
50         CloseHandle(handle);
51 }
52
53 class ThreadSignalSocket : public BufferedSocket
54 {
55         SocketThread* parent;
56  public:
57         ThreadSignalSocket(SocketThread* t, int newfd)
58                 : BufferedSocket(newfd), parent(t)
59         {
60         }
61
62         void OnDataReady()
63         {
64                 recvq.clear();
65                 parent->OnNotify();
66         }
67
68         void OnError(BufferedSocketError)
69         {
70                 ServerInstance->GlobalCulls.AddItem(this);
71         }
72 };
73
74 SocketThread::SocketThread()
75 {
76         int listenFD = socket(AF_INET, SOCK_STREAM, 0);
77         if (listenFD == -1)
78                 throw CoreException("Could not create ITC pipe");
79         int connFD = socket(AF_INET, SOCK_STREAM, 0);
80         if (connFD == -1)
81                 throw CoreException("Could not create ITC pipe");
82
83         if (!ServerInstance->BindSocket(listenFD, 0, "127.0.0.1", true))
84                 throw CoreException("Could not create ITC pipe");
85         SocketEngine::NonBlocking(connFD);
86
87         struct sockaddr_in addr;
88         socklen_t sz = sizeof(addr);
89         getsockname(listenFD, reinterpret_cast<struct sockaddr*>(&addr), &sz);
90         connect(connFD, reinterpret_cast<struct sockaddr*>(&addr), sz);
91         SocketEngine::Blocking(listenFD);
92         int nfd = accept(listenFD, reinterpret_cast<struct sockaddr*>(&addr), &sz);
93         if (nfd < 0)
94                 throw CoreException("Could not create ITC pipe");
95         new ThreadSignalSocket(this, nfd);
96         closesocket(listenFD);
97
98         SocketEngine::Blocking(connFD);
99         this->signal.connFD = connFD;
100 }
101
102 void SocketThread::NotifyParent()
103 {
104         char dummy = '*';
105         send(signal.connFD, &dummy, 1, 0);
106 }
107
108 SocketThread::~SocketThread()
109 {
110         if (signal.connFD >= 0)
111         {
112                 shutdown(signal.connFD, 2);
113                 closesocket(signal.connFD);
114         }
115 }