2 * InspIRCd -- Internet Relay Chat Daemon
4 * Copyright (C) 2013-2014 Attila Molnar <attilamolnar@hush.com>
5 * Copyright (C) 2012 Robby <robby@chatbelgie.be>
6 * Copyright (C) 2012 ChrisTX <xpipe@hotmail.de>
7 * Copyright (C) 2009, 2011 Daniel De Graaf <danieldg@inspircd.org>
8 * Copyright (C) 2009 Uli Schlachter <psychon@inspircd.org>
9 * Copyright (C) 2009 Dennis Friis <peavey@inspircd.org>
10 * Copyright (C) 2008-2009 Craig Edwards <brain@inspircd.org>
12 * This file is part of InspIRCd. InspIRCd is free software: you can
13 * redistribute it and/or modify it under the terms of the GNU General Public
14 * License as published by the Free Software Foundation, version 2.
16 * This program is distributed in the hope that it will be useful, but WITHOUT
17 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
18 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
21 * You should have received a copy of the GNU General Public License
22 * along with this program. If not, see <http://www.gnu.org/licenses/>.
27 #include "threadengines/threadengine_win32.h"
29 void ThreadEngine::Start(Thread* thread)
31 thread->state.handle = CreateThread(NULL, 0, ThreadEngine::Entry, thread, 0, NULL);
33 if (thread->state.handle == NULL)
35 DWORD lasterr = GetLastError();
36 std::string err = "Unable to create new thread: " + ConvToStr(lasterr);
37 SetLastError(ERROR_SUCCESS);
38 throw CoreException(err);
42 DWORD WINAPI ThreadEngine::Entry(void* parameter)
44 Thread* pt = static_cast<Thread*>(parameter);
49 void ThreadEngine::Stop(Thread* thread)
51 thread->SetExitFlag();
52 HANDLE handle = thread->state.handle;
53 WaitForSingleObject(handle,INFINITE);
57 class ThreadSignalSocket : public BufferedSocket
61 ThreadSignalSocket(SocketThread* t, int newfd)
62 : BufferedSocket(newfd), parent(t)
72 void OnError(BufferedSocketError)
74 ServerInstance->GlobalCulls.AddItem(this);
78 static bool BindAndListen(int sockfd, int port, const char* addr)
80 irc::sockets::sockaddrs servaddr;
81 if (!irc::sockets::aptosa(addr, port, servaddr))
84 if (SocketEngine::Bind(sockfd, servaddr) != 0)
87 if (SocketEngine::Listen(sockfd, ServerInstance->Config->MaxConn) != 0)
89 ServerInstance->Logs->Log("SOCKET", LOG_DEFAULT, "ERROR in listen(): %s", strerror(errno));
96 SocketThread::SocketThread()
98 int listenFD = socket(AF_INET, SOCK_STREAM, 0);
100 throw CoreException("Could not create ITC pipe");
101 int connFD = socket(AF_INET, SOCK_STREAM, 0);
103 throw CoreException("Could not create ITC pipe");
105 if (!BindAndListen(listenFD, 0, "127.0.0.1"))
106 throw CoreException("Could not create ITC pipe");
107 SocketEngine::NonBlocking(connFD);
109 struct sockaddr_in addr;
110 socklen_t sz = sizeof(addr);
111 getsockname(listenFD, reinterpret_cast<struct sockaddr*>(&addr), &sz);
112 connect(connFD, reinterpret_cast<struct sockaddr*>(&addr), sz);
113 SocketEngine::Blocking(listenFD);
114 int nfd = accept(listenFD, reinterpret_cast<struct sockaddr*>(&addr), &sz);
116 throw CoreException("Could not create ITC pipe");
117 new ThreadSignalSocket(this, nfd);
118 closesocket(listenFD);
120 SocketEngine::Blocking(connFD);
121 this->signal.connFD = connFD;
124 void SocketThread::NotifyParent()
127 send(signal.connFD, &dummy, 1, 0);
130 SocketThread::~SocketThread()
132 if (signal.connFD >= 0)
134 shutdown(signal.connFD, 2);
135 closesocket(signal.connFD);