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 void ListenSocket::HandleEvent(EventType e, int err)
78 ServerInstance->Logs->Log("SOCKET",DEFAULT,"ListenSocket::HandleEvent() received a socket engine error event! well shit! '%s'", strerror(err));
81 ServerInstance->Logs->Log("SOCKET",DEBUG,"*** BUG *** ListenSocket::HandleEvent() got a WRITE event!!!");
85 ServerInstance->Logs->Log("SOCKET",DEBUG,"HandleEvent for Listensoket");
86 socklen_t uslen, length; // length of our port number
87 int incomingSockfd, in_port;
90 if (this->family == AF_INET6)
92 uslen = sizeof(sockaddr_in6);
93 length = sizeof(sockaddr_in6);
98 uslen = sizeof(sockaddr_in);
99 length = sizeof(sockaddr_in);
102 incomingSockfd = ServerInstance->SE->Accept(this, (sockaddr*)client, &length);
104 if ((incomingSockfd > -1) && (!ServerInstance->SE->GetSockName(this, sock_us, &uslen)))
109 *target = *buf = '\0';
112 if (this->family == AF_INET6)
114 in_port = ntohs(((sockaddr_in6*)sock_us)->sin6_port);
115 inet_ntop(AF_INET6, &((const sockaddr_in6*)client)->sin6_addr, buf, sizeof(buf));
116 socklen_t raddrsz = sizeof(sockaddr_in6);
117 if (getsockname(incomingSockfd, (sockaddr*) raddr, &raddrsz) == 0)
118 inet_ntop(AF_INET6, &((const sockaddr_in6*)raddr)->sin6_addr, target, sizeof(target));
120 ServerInstance->Logs->Log("SOCKET", DEBUG, "Can't get peername: %s", strerror(errno));
125 inet_ntop(AF_INET, &((const sockaddr_in*)client)->sin_addr, buf, sizeof(buf));
126 in_port = ntohs(((sockaddr_in*)sock_us)->sin_port);
127 socklen_t raddrsz = sizeof(sockaddr_in);
128 if (getsockname(incomingSockfd, (sockaddr*) raddr, &raddrsz) == 0)
129 inet_ntop(AF_INET, &((const sockaddr_in*)raddr)->sin_addr, target, sizeof(target));
131 ServerInstance->Logs->Log("SOCKET", DEBUG, "Can't get peername: %s", strerror(errno));
133 ServerInstance->SE->NonBlocking(incomingSockfd);
134 ServerInstance->stats->statsAccept++;
135 ServerInstance->Users->AddUser(ServerInstance, incomingSockfd, in_port, false, this->family, client, target);
139 ServerInstance->SE->Shutdown(incomingSockfd, 2);
140 ServerInstance->SE->Close(incomingSockfd);
141 ServerInstance->stats->statsRefused++;