1 /* +------------------------------------+
2 * | Inspire Internet Relay Chat Daemon |
3 * +------------------------------------+
5 * InspIRCd: (C) 2002-2008 InspIRCd Development Team
6 * See: http://www.inspircd.org/wiki/index.php/Credits
8 * This program is free but copyrighted software; see
9 * the file COPYING for details.
11 * ---------------------------------------------------
18 #include "socketengine.h"
21 /* Private static member data must be initialized in this manner */
22 unsigned int ListenSocket::socketcount = 0;
23 sockaddr* ListenSocket::sock_us = NULL;
24 sockaddr* ListenSocket::client = NULL;
25 sockaddr* ListenSocket::raddr = NULL;
27 ListenSocket::ListenSocket(InspIRCd* Instance, int port, char* addr) : ServerInstance(Instance), desc("plaintext"), bind_addr(addr), bind_port(port)
29 this->SetFd(irc::sockets::OpenTCPSocket(addr));
30 if (this->GetFd() > -1)
32 if (!Instance->BindSocket(this->fd,port,addr))
35 if ((!*addr) || (strchr(addr,':')))
36 this->family = AF_INET6;
39 this->family = AF_INET;
40 Instance->SE->AddFd(this);
42 /* Saves needless allocations */
45 /* All instances of ListenSocket share these, so reference count it */
46 ServerInstance->Logs->Log("SOCKET", DEBUG,"Allocate sockaddr structures");
47 sock_us = new sockaddr[2];
48 client = new sockaddr[2];
49 raddr = new sockaddr[2];
54 ListenSocket::~ListenSocket()
56 if (this->GetFd() > -1)
58 ServerInstance->SE->DelFd(this);
59 ServerInstance->Logs->Log("SOCKET", DEBUG,"Shut down listener on fd %d", this->fd);
60 if (ServerInstance->SE->Shutdown(this, 2) || ServerInstance->SE->Close(this))
61 ServerInstance->Logs->Log("SOCKET", DEBUG,"Failed to cancel listener: %s", strerror(errno));
73 /* Just seperated into another func for tidiness really.. */
74 void ListenSocket::AcceptInternal()
76 ServerInstance->Logs->Log("SOCKET",DEBUG,"HandleEvent for Listensoket");
77 socklen_t uslen, length; // length of our port number
81 if (this->family == AF_INET6)
83 uslen = sizeof(sockaddr_in6);
84 length = sizeof(sockaddr_in6);
89 uslen = sizeof(sockaddr_in);
90 length = sizeof(sockaddr_in);
93 incomingSockfd = ServerInstance->SE->Accept(this, (sockaddr*)client, &length);
95 if (incomingSockfd < 0 ||
96 ServerInstance->SE->GetSockName(this, sock_us, &uslen) == -1)
98 ServerInstance->SE->Shutdown(incomingSockfd, 2);
99 ServerInstance->SE->Close(incomingSockfd);
100 ServerInstance->stats->statsRefused++;
104 static char buf[MAXBUF];
105 static char target[MAXBUF];
107 *target = *buf = '\0';
110 if (this->family == AF_INET6)
112 inet_ntop(AF_INET6, &((const sockaddr_in6*)client)->sin6_addr, buf, sizeof(buf));
113 socklen_t raddrsz = sizeof(sockaddr_in6);
114 if (getsockname(incomingSockfd, (sockaddr*) raddr, &raddrsz) == 0)
115 inet_ntop(AF_INET6, &((const sockaddr_in6*)raddr)->sin6_addr, target, sizeof(target));
117 ServerInstance->Logs->Log("SOCKET", DEBUG, "Can't get peername: %s", strerror(errno));
122 inet_ntop(AF_INET, &((const sockaddr_in*)client)->sin_addr, buf, sizeof(buf));
123 socklen_t raddrsz = sizeof(sockaddr_in);
124 if (getsockname(incomingSockfd, (sockaddr*) raddr, &raddrsz) == 0)
125 inet_ntop(AF_INET, &((const sockaddr_in*)raddr)->sin_addr, target, sizeof(target));
127 ServerInstance->Logs->Log("SOCKET", DEBUG, "Can't get peername: %s", strerror(errno));
132 * this is done as a safety check to keep the file descriptors within range of fd_ref_table.
133 * its a pretty big but for the moment valid assumption:
134 * file descriptors are handed out starting at 0, and are recycled as theyre freed.
135 * therefore if there is ever an fd over 65535, 65536 clients must be connected to the
136 * irc server at once (or the irc server otherwise initiating this many connections, files etc)
137 * which for the time being is a physical impossibility (even the largest networks dont have more
138 * than about 10,000 users on ONE server!)
140 if (incomingSockfd >= ServerInstance->SE->GetMaxFds())
142 ServerInstance->Logs->Log("SOCKET", DEBUG, "Server is full");
143 ServerInstance->SE->Shutdown(incomingSockfd, 2);
144 ServerInstance->SE->Close(incomingSockfd);
145 ServerInstance->stats->statsRefused++;
149 ServerInstance->SE->NonBlocking(incomingSockfd);
150 ServerInstance->stats->statsAccept++;
151 this->OnAcceptReady(target, incomingSockfd, buf);
154 void ListenSocket::HandleEvent(EventType e, int err)
159 ServerInstance->Logs->Log("SOCKET",DEFAULT,"ListenSocket::HandleEvent() received a socket engine error event! well shit! '%s'", strerror(err));
162 ServerInstance->Logs->Log("SOCKET",DEBUG,"*** BUG *** ListenSocket::HandleEvent() got a WRITE event!!!");
165 this->AcceptInternal();
170 void ListenSocket::OnAcceptReady(const std::string &ipconnectedto, int nfd, const std::string &incomingip)
172 ServerInstance->Users->AddUser(ServerInstance, nfd, bind_port, false, this->family, client, ipconnectedto);