|
|||
|
|||
|
#include <inspsocket.h>
Inheritance diagram for InspSocket:


Public Member Functions | |
| bool | FlushWriteBuffer () |
| Flushes the write buffer. | |
| void | SetQueues (int nfd) |
| Set the queue sizes This private method sets the operating system queue sizes for this socket to 65535 so that it can queue more information without application-level queueing which was required in older software. | |
| bool | BindAddr (const std::string &ip) |
| Bind to an address. | |
| InspSocket (InspIRCd *SI) | |
| The default constructor does nothing and should not be used. | |
| InspSocket (InspIRCd *SI, int newfd, const char *ip) | |
| This constructor is used to associate an existing connecting with an InspSocket class. | |
| InspSocket (InspIRCd *SI, const std::string &ipaddr, int port, bool listening, unsigned long maxtime, const std::string &connectbindip="") | |
| This constructor is used to create a new socket, either listening for connections, or an outbound connection to another host. | |
| virtual bool | OnConnected () |
| This method is called when an outbound connection on your socket is completed. | |
| virtual void | OnError (InspSocketError e) |
| This method is called when an error occurs. | |
| virtual int | OnDisconnect () |
| When an established connection is terminated, the OnDisconnect method is triggered. | |
| virtual bool | OnDataReady () |
| When there is data waiting to be read on a socket, the OnDataReady() method is called. | |
| virtual bool | OnWriteReady () |
| When it is ok to write to the socket, and a write event was requested, this method is triggered. | |
| virtual void | OnTimeout () |
| When an outbound connection fails, and the attempt times out, you will receive this event. | |
| virtual void | OnClose () |
| Whenever close() is called, OnClose() will be called first. | |
| virtual char * | Read () |
| Reads all pending bytes from the socket into a char* array which can be up to 16 kilobytes in length. | |
| std::string | GetIP () |
| Returns the IP address associated with this connection, or an empty string if no IP address exists. | |
| virtual void | Write (const std::string &data) |
| Writes a std::string to the socket. | |
| virtual int | OnIncomingConnection (int newfd, char *ip) |
| If your socket is a listening socket, when a new connection comes in on the socket this method will be called. | |
| void | SetState (InspSocketState s) |
| Changes the socket's state. | |
| void | WantWrite () |
| Call this to receive the next write event that comes along for this fd to the OnWriteReady method. | |
| InspSocketState | GetState () |
| Returns the current socket state. | |
| bool | Poll () |
| Only the core should call this function. | |
| int | GetFd () |
| This method returns the socket's file descriptor as assigned by the operating system, or -1 if no descriptor has been assigned. | |
| virtual void | Close () |
| This method causes the socket to close, and may also be triggered by other methods such as OnTimeout and OnError. | |
| virtual | ~InspSocket () |
| The destructor may implicitly call OnClose(), and will close() and shutdown() the file descriptor used for this socket. | |
| virtual bool | DoConnect () |
| This method attempts to connect to a hostname. | |
| void | MarkAsClosed () |
| This method marks the socket closed. | |
| void | HandleEvent (EventType et, int errornum=0) |
| Handle event from EventHandler parent class. | |
| bool | Readable () |
| Returns true if this socket is readable. | |
Public Attributes | |
| std::string | cbindip |
| Bind IP. | |
| bool | IsIOHooked |
| Is hooked by a module for low level IO. | |
| InspIRCd * | Instance |
| Instance we were created by. | |
| SocketTimeout * | Timeout |
| Timeout class or NULL. | |
| unsigned long | timeout_val |
| Timeout length. | |
| std::deque< std::string > | outbuffer |
| Socket output buffer (binary safe). | |
| char | host [MAXBUF] |
| The hostname connected to. | |
| int | port |
| The port connected to, or the port this socket is listening on. | |
| InspSocketState | state |
| The state for this socket, either listening, connecting, connected or error. | |
| bool | timeout |
| This value is true if the socket has timed out. | |
| char | ibuf [65535] |
| Socket input buffer, used by read(). | |
| char | IP [MAXBUF] |
| The IP address being connected to stored in string form for easy retrieval by accessors. | |
| socklen_t | length |
| Used by accept() to indicate the sizes of the sockaddr_in structures. | |
| bool | ClosePending |
| When the socket has been marked as closing, this flag will be set to true, then the next time the socket is examined, the socket is deleted and closed. | |
| bool | WaitingForWriteEvent |
| Set to true when we're waiting for a write event. | |
It is fully integrated into InspIRCds socket loop and attaches its sockets to the core's instance of the SocketEngine class, meaning that any sockets you create have the same power and abilities as a socket created by the core itself. To use InspSocket, you must inherit a class from it, and use the InspSocket constructors to establish connections and bindings.
Definition at line 112 of file inspsocket.h.
|
|
The default constructor does nothing and should not be used.
Definition at line 28 of file inspsocket.cpp. References EventHandler::fd, I_DISCONNECTED, Instance, IsIOHooked, state, Timeout, and WaitingForWriteEvent. 00029 { 00030 this->Timeout = NULL; 00031 this->state = I_DISCONNECTED; 00032 this->fd = -1; 00033 this->WaitingForWriteEvent = false; 00034 this->Instance = SI; 00035 this->IsIOHooked = false; 00036 }
|
|
||||||||||||||||
|
This constructor is used to associate an existing connecting with an InspSocket class. The given file descriptor must be valid, and when initialized, the InspSocket will be set with the given IP address and placed in CONNECTED state. Definition at line 38 of file inspsocket.cpp. References SocketEngine::AddFd(), EventHandler::fd, I_CONNECTED, Instance, IsIOHooked, MAXBUF, InspIRCd::SE, state, strlcpy(), Timeout, and WaitingForWriteEvent. 00039 { 00040 this->Timeout = NULL; 00041 this->fd = newfd; 00042 this->state = I_CONNECTED; 00043 strlcpy(this->IP,ip,MAXBUF); 00044 this->WaitingForWriteEvent = false; 00045 this->Instance = SI; 00046 this->IsIOHooked = false; 00047 if (this->fd > -1) 00048 this->Instance->SE->AddFd(this); 00049 }
|
|
||||||||||||||||||||||||||||
|
This constructor is used to create a new socket, either listening for connections, or an outbound connection to another host. Note that if you specify a hostname in the 'ipaddr' parameter, this class will not connect. You must resolve your hostnames before passing them to InspSocket. To do so, you should use the nonblocking class 'Resolver'.
Definition at line 51 of file inspsocket.cpp. References InspIRCd::BindSocket(), cbindip, Close(), ClosePending, DEBUG, ERROR, EventHandler::fd, host, I_ERR_BIND, I_ERR_CONNECT, I_ERR_NOMOREFDS, I_ERR_SOCKET, I_ERROR, I_LISTENING, Instance, IsIOHooked, InspIRCd::Log(), MAXBUF, OnError(), irc::sockets::OpenTCPSocket(), port, state, strlcpy(), Timeout, timeout_val, and WaitingForWriteEvent. 00052 { 00053 this->cbindip = connectbindip; 00054 this->fd = -1; 00055 this->Instance = SI; 00056 strlcpy(host,ipaddr.c_str(),MAXBUF); 00057 this->WaitingForWriteEvent = false; 00058 this->IsIOHooked = false; 00059 this->Timeout = NULL; 00060 if (listening) 00061 { 00062 if ((this->fd = OpenTCPSocket(host)) == ERROR) 00063 { 00064 this->fd = -1; 00065 this->state = I_ERROR; 00066 this->OnError(I_ERR_SOCKET); 00067 return; 00068 } 00069 else 00070 { 00071 if (!SI->BindSocket(this->fd,aport,(char*)ipaddr.c_str())) 00072 { 00073 this->Close(); 00074 this->fd = -1; 00075 this->state = I_ERROR; 00076 this->OnError(I_ERR_BIND); 00077 this->ClosePending = true; 00078 return; 00079 } 00080 else 00081 { 00082 this->state = I_LISTENING; 00083 this->port = aport; 00084 if (this->fd > -1) 00085 { 00086 if (!this->Instance->SE->AddFd(this)) 00087 { 00088 this->Close(); 00089 this->state = I_ERROR; 00090 this->OnError(I_ERR_NOMOREFDS); 00091 } 00092 } 00093 return; 00094 } 00095 } 00096 } 00097 else 00098 { 00099 strlcpy(this->host,ipaddr.c_str(),MAXBUF); 00100 this->port = aport; 00101 00102 bool ipvalid = true; 00103 #ifdef IPV6 00104 if (strchr(host,':')) 00105 { 00106 in6_addr n; 00107 if (inet_pton(AF_INET6, host, &n) < 1) 00108 ipvalid = false; 00109 } 00110 else 00111 #endif 00112 { 00113 in_addr n; 00114 if (inet_aton(host,&n) < 1) 00115 ipvalid = false; 00116 } 00117 if (!ipvalid) 00118 { 00119 this->Instance->Log(DEBUG,"BUG: Hostname passed to InspSocket, rather than an IP address!"); 00120 this->OnError(I_ERR_CONNECT); 00121 this->Close(); 00122 this->fd = -1; 00123 this->state = I_ERROR; 00124 return; 00125 } 00126 else 00127 { 00128 strlcpy(this->IP,host,MAXBUF); 00129 timeout_val = maxtime; 00130 if (!this->DoConnect()) 00131 { 00132 this->OnError(I_ERR_CONNECT); 00133 this->Close(); 00134 this->fd = -1; 00135 this->state = I_ERROR; 00136 return; 00137 } 00138 } 00139 } 00140 }
|
|
|
The destructor may implicitly call OnClose(), and will close() and shutdown() the file descriptor used for this socket.
Definition at line 708 of file inspsocket.cpp. References Close(), TimerManager::DelTimer(), Instance, Timeout, and InspIRCd::Timers. 00709 { 00710 this->Close(); 00711 if (Timeout) 00712 { 00713 Instance->Timers->DelTimer(Timeout); 00714 Timeout = NULL; 00715 } 00716 }
|
|
|
Bind to an address.
Definition at line 168 of file inspsocket.cpp. References Conf, ConfigReader::Enumerate(), EventHandler::fd, I_ERR_BIND, I_ERROR, IP, OnError(), ConfigReader::ReadValue(), and state. 00169 { 00170 ConfigReader Conf(this->Instance); 00171 socklen_t size = sizeof(sockaddr_in); 00172 #ifdef IPV6 00173 bool v6 = false; 00174 /* Are we looking for a binding to fit an ipv6 host? */ 00175 if ((ip.empty()) || (ip.find(':') != std::string::npos)) 00176 v6 = true; 00177 #endif 00178 int j = 0; 00179 while (j < Conf.Enumerate("bind") || (!ip.empty())) 00180 { 00181 std::string IP = ip.empty() ? Conf.ReadValue("bind","address",j) : ip; 00182 if (!ip.empty() || Conf.ReadValue("bind","type",j) == "servers") 00183 { 00184 if (!ip.empty() || ((IP != "*") && (IP != "127.0.0.1") && (!IP.empty()) && (IP != "::1"))) 00185 { 00186 /* The [2] is required because we may write a sockaddr_in6 here, and sockaddr_in6 is larger than sockaddr, where sockaddr_in4 is not. */ 00187 sockaddr* s = new sockaddr[2]; 00188 #ifdef IPV6 00189 if (v6) 00190 { 00191 in6_addr n; 00192 if (inet_pton(AF_INET6, IP.c_str(), &n) > 0) 00193 { 00194 memcpy(&((sockaddr_in6*)s)->sin6_addr, &n, sizeof(sockaddr_in6)); 00195 ((sockaddr_in6*)s)->sin6_port = 0; 00196 ((sockaddr_in6*)s)->sin6_family = AF_INET6; 00197 size = sizeof(sockaddr_in6); 00198 } 00199 else 00200 { 00201 delete[] s; 00202 j++; 00203 continue; 00204 } 00205 } 00206 else 00207 #endif 00208 { 00209 in_addr n; 00210 if (inet_aton(IP.c_str(), &n) > 0) 00211 { 00212 ((sockaddr_in*)s)->sin_addr = n; 00213 ((sockaddr_in*)s)->sin_port = 0; 00214 ((sockaddr_in*)s)->sin_family = AF_INET; 00215 } 00216 else 00217 { 00218 delete[] s; 00219 j++; 00220 continue; 00221 } 00222 } 00223 00224 if (bind(this->fd, s, size) < 0) 00225 { 00226 this->state = I_ERROR; 00227 this->OnError(I_ERR_BIND); 00228 this->fd = -1; 00229 delete[] s; 00230 return false; 00231 } 00232 00233 delete[] s; 00234 return true; 00235 } 00236 } 00237 j++; 00238 } 00239 return true; 00240 }
|
|
|
This method causes the socket to close, and may also be triggered by other methods such as OnTimeout and OnError.
Definition at line 352 of file inspsocket.cpp. References InspIRCd::Config, DEFAULT, ServerConfig::GetIOHook(), CoreException::GetReason(), CoreException::GetSource(), I_LISTENING, Instance, InspIRCd::Log(), OnClose(), Module::OnRawSocketClose(), and InspIRCd::SocketCull. Referenced by DoConnect(), ModuleSpanningTree::DoPingChecks(), FlushWriteBuffer(), cmd_rsquit::Handle(), ModuleSpanningTree::HandleSquit(), TreeSocket::Inbound_Server(), InspSocket(), SpanningTreeUtilities::ReadConfiguration(), ~InspSocket(), and SpanningTreeUtilities::~SpanningTreeUtilities(). 00353 { 00354 /* Save this, so we dont lose it, 00355 * otherise on failure, error messages 00356 * might be inaccurate. 00357 */ 00358 int save = errno; 00359 if (this->fd > -1) 00360 { 00361 if (this->IsIOHooked && Instance->Config->GetIOHook(this)) 00362 { 00363 try 00364 { 00365 if (this->state != I_LISTENING) 00366 Instance->Config->GetIOHook(this)->OnRawSocketClose(this->fd); 00367 } 00368 catch (CoreException& modexcept) 00369 { 00370 Instance->Log(DEFAULT,"%s threw an exception: %s", modexcept.GetSource(), modexcept.GetReason()); 00371 } 00372 } 00373 shutdown(this->fd,2); 00374 if (close(this->fd) != -1) 00375 this->OnClose(); 00376 00377 if (Instance->SocketCull.find(this) == Instance->SocketCull.end()) 00378 Instance->SocketCull[this] = this; 00379 } 00380 errno = save; 00381 }
|
|
|
This method attempts to connect to a hostname. This only occurs on a non-listening socket. This method is asyncronous. Definition at line 242 of file inspsocket.cpp. References TimerManager::AddTimer(), Close(), EventHandler::fd, I_CONNECTING, I_ERR_CONNECT, I_ERR_NOMOREFDS, I_ERR_SOCKET, I_ERROR, Instance, OnError(), SetQueues(), state, InspIRCd::Time(), Timeout, timeout_val, and InspIRCd::Timers. 00243 { 00244 /* The [2] is required because we may write a sockaddr_in6 here, and sockaddr_in6 is larger than sockaddr, where sockaddr_in4 is not. */ 00245 sockaddr* addr = new sockaddr[2]; 00246 socklen_t size = sizeof(sockaddr_in); 00247 #ifdef IPV6 00248 bool v6 = false; 00249 if ((!*this->host) || strchr(this->host, ':')) 00250 v6 = true; 00251 00252 if (v6) 00253 { 00254 this->fd = socket(AF_INET6, SOCK_STREAM, 0); 00255 if ((this->fd > -1) && ((strstr(this->IP,"::ffff:") != (char*)&this->IP) && (strstr(this->IP,"::FFFF:") != (char*)&this->IP))) 00256 { 00257 if (!this->BindAddr(this->cbindip)) 00258 { 00259 delete[] addr; 00260 return false; 00261 } 00262 } 00263 } 00264 else 00265 #endif 00266 { 00267 this->fd = socket(AF_INET, SOCK_STREAM, 0); 00268 if (this->fd > -1) 00269 { 00270 if (!this->BindAddr(this->cbindip)) 00271 { 00272 delete[] addr; 00273 return false; 00274 } 00275 } 00276 } 00277 00278 if (this->fd == -1) 00279 { 00280 this->state = I_ERROR; 00281 this->OnError(I_ERR_SOCKET); 00282 delete[] addr; 00283 return false; 00284 } 00285 00286 #ifdef IPV6 00287 if (v6) 00288 { 00289 in6_addr addy; 00290 if (inet_pton(AF_INET6, this->host, &addy) > 0) 00291 { 00292 ((sockaddr_in6*)addr)->sin6_family = AF_INET6; 00293 memcpy(&((sockaddr_in6*)addr)->sin6_addr, &addy, sizeof(addy)); 00294 ((sockaddr_in6*)addr)->sin6_port = htons(this->port); 00295 size = sizeof(sockaddr_in6); 00296 } 00297 } 00298 else 00299 #endif 00300 { 00301 in_addr addy; 00302 if (inet_aton(this->host, &addy) > 0) 00303 { 00304 ((sockaddr_in*)addr)->sin_family = AF_INET; 00305 ((sockaddr_in*)addr)->sin_addr = addy; 00306 ((sockaddr_in*)addr)->sin_port = htons(this->port); 00307 } 00308 } 00309 #ifndef WIN32 00310 int flags = fcntl(this->fd, F_GETFL, 0); 00311 fcntl(this->fd, F_SETFL, flags | O_NONBLOCK); 00312 #else 00313 unsigned long flags = 0; 00314 ioctlsocket(this->fd, FIONBIO, &flags); 00315 #endif 00316 if (connect(this->fd, (sockaddr*)addr, size) == -1) 00317 { 00318 if (errno != EINPROGRESS) 00319 { 00320 this->OnError(I_ERR_CONNECT); 00321 this->Close(); 00322 this->state = I_ERROR; 00323 delete[] addr; 00324 return false; 00325 } 00326 00327 this->Timeout = new SocketTimeout(this->GetFd(), this->Instance, this, timeout_val, this->Instance->Time()); 00328 this->Instance->Timers->AddTimer(this->Timeout); 00329 } 00330 #ifdef WIN32 00331 /* Set nonblocking mode after the connect() call */ 00332 flags = 0; 00333 ioctlsocket(this->fd, FIONBIO, &flags); 00334 #endif 00335 this->state = I_CONNECTING; 00336 delete[] addr; 00337 if (this->fd > -1) 00338 { 00339 if (!this->Instance->SE->AddFd(this)) 00340 { 00341 this->OnError(I_ERR_NOMOREFDS); 00342 this->Close(); 00343 this->state = I_ERROR; 00344 return false; 00345 } 00346 this->SetQueues(this->fd); 00347 } 00348 return true; 00349 }
|
|
|
Flushes the write buffer.
Definition at line 471 of file inspsocket.cpp. References Close(), InspIRCd::Config, DEBUG, SocketEngine::DelFd(), EventHandler::fd, ServerConfig::GetIOHook(), CoreException::GetReason(), CoreException::GetSource(), I_CONNECTED, I_ERR_WRITE, I_ERROR, Instance, length, InspIRCd::Log(), OnError(), Module::OnRawSocketWrite(), outbuffer, InspIRCd::SE, state, and SocketEngine::WantWrite(). Referenced by HttpServerSocket::Page(), TreeSocket::SendError(), HttpServerSocket::SendHeaders(), and HttpServerSocket::ServeData(). 00472 { 00473 errno = 0; 00474 if ((this->fd > -1) && (this->state == I_CONNECTED)) 00475 { 00476 if (this->IsIOHooked) 00477 { 00478 while (outbuffer.size() && (errno != EAGAIN)) 00479 { 00480 try 00481 { 00482 /* XXX: The lack of buffering here is NOT a bug, modules implementing this interface have to 00483 * implement their own buffering mechanisms 00484 */ 00485 Instance->Config->GetIOHook(this)->OnRawSocketWrite(this->fd, outbuffer[0].c_str(), outbuffer[0].length()); 00486 outbuffer.pop_front(); 00487 } 00488 catch (CoreException& modexcept) 00489 { 00490 Instance->Log(DEBUG,"%s threw an exception: %s", modexcept.GetSource(), modexcept.GetReason()); 00491 return true; 00492 } 00493 } 00494 } 00495 else 00496 { 00497 /* If we have multiple lines, try to send them all, 00498 * not just the first one -- Brain 00499 */ 00500 while (outbuffer.size() && (errno != EAGAIN)) 00501 { 00502 /* Send a line */ 00503 #ifndef WIN32 00504 int result = write(this->fd,outbuffer[0].c_str(),outbuffer[0].length()); 00505 #else 00506 int result = send(this->fd,outbuffer[0].c_str(),outbuffer[0].length(), 0); 00507 #endif 00508 if (result > 0) 00509 { 00510 if ((unsigned int)result >= outbuffer[0].length()) 00511 { 00512 /* The whole block was written (usually a line) 00513 * Pop the block off the front of the queue, 00514 * dont set errno, because we are clear of errors 00515 * and want to try and write the next block too. 00516 */ 00517 outbuffer.pop_front(); 00518 } 00519 else 00520 { 00521 std::string temp = outbuffer[0].substr(result); 00522 outbuffer[0] = temp; 00523 /* We didnt get the whole line out. arses. 00524 * Try again next time, i guess. Set errno, 00525 * because we shouldnt be writing any more now, 00526 * until the socketengine says its safe to do so. 00527 */ 00528 errno = EAGAIN; 00529 } 00530 } 00531 else if (result == 0) 00532 { 00533 this->Instance->SE->DelFd(this); 00534 this->Close(); 00535 return true; 00536 } 00537 else if ((result == -1) && (errno != EAGAIN)) 00538 { 00539 this->OnError(I_ERR_WRITE); 00540 this->state = I_ERROR; 00541 this->Instance->SE->DelFd(this); 00542 this->Close(); 00543 return true; 00544 } 00545 } 00546 } 00547 } 00548 00549 if ((errno == EAGAIN) && (fd > -1)) 00550 { 00551 this->Instance->SE->WantWrite(this); 00552 } 00553 00554 return (fd < 0); 00555 }
|
|
|
This method returns the socket's file descriptor as assigned by the operating system, or -1 if no descriptor has been assigned.
Reimplemented from EventHandler. Definition at line 694 of file inspsocket.cpp. References EventHandler::fd. Referenced by ModuleSpanningTree::ConnectServer(), HandshakeTimer::HandshakeTimer(), ServernameResolver::OnLookupComplete(), ModuleSSLOpenSSL::OnRequest(), and ModuleSSLGnuTLS::OnRequest(). 00695 { 00696 return this->fd; 00697 }
|
|
|
Returns the IP address associated with this connection, or an empty string if no IP address exists.
Definition at line 383 of file inspsocket.cpp. References IP. Referenced by TreeSocket::OnConnected(), and TreeSocket::SendError(). 00384 { 00385 return this->IP; 00386 }
|
|
|
Returns the current socket state.
Definition at line 689 of file inspsocket.cpp. References state. Referenced by SpanningTreeUtilities::ReadConfiguration(). 00690 { 00691 return this->state; 00692 }
|
|
||||||||||||
|
Handle event from EventHandler parent class.
Implements EventHandler. Definition at line 718 of file inspsocket.cpp. References EVENT_ERROR, EVENT_READ, EVENT_WRITE, I_CONNECTING, I_ERR_BIND, I_ERR_CONNECT, I_ERR_TIMEOUT, I_ERR_WRITE, Instance, OnError(), InspIRCd::SocketCull, and WaitingForWriteEvent. 00719 { 00720 switch (et) 00721 { 00722 case EVENT_ERROR: 00723 switch (errornum) 00724 { 00725 case ETIMEDOUT: 00726 this->OnError(I_ERR_TIMEOUT); 00727 break; 00728 case ECONNREFUSED: 00729 case 0: 00730 this->OnError(this->state == I_CONNECTING ? I_ERR_CONNECT : I_ERR_WRITE); 00731 break; 00732 case EADDRINUSE: 00733 this->OnError(I_ERR_BIND); 00734 break; 00735 case EPIPE: 00736 case EIO: 00737 this->OnError(I_ERR_WRITE); 00738 break; 00739 } 00740 if (this->Instance->SocketCull.find(this) == this->Instance->SocketCull.end()) 00741 this->Instance->SocketCull[this] = this; 00742 return; 00743 break; 00744 case EVENT_READ: 00745 if (!this->Poll()) 00746 { 00747 if (this->Instance->SocketCull.find(this) == this->Instance->SocketCull.end()) 00748 this->Instance->SocketCull[this] = this; 00749 return; 00750 } 00751 break; 00752 case EVENT_WRITE: 00753 if (this->WaitingForWriteEvent) 00754 { 00755 this->WaitingForWriteEvent = false; 00756 if (!this->OnWriteReady()) 00757 { 00758 if (this->Instance->SocketCull.find(this) == this->Instance->SocketCull.end()) 00759 this->Instance->SocketCull[this] = this; 00760 return; 00761 } 00762 } 00763 if (this->state == I_CONNECTING) 00764 { 00765 /* This might look wrong as if we should be actually calling 00766 * with EVENT_WRITE, but trust me it is correct. There are some 00767 * writeability-state things in the read code, because of how 00768 * InspSocket used to work regarding write buffering in previous 00769 * versions of InspIRCd. - Brain 00770 */ 00771 this->HandleEvent(EVENT_READ); 00772 return; 00773 } 00774 else 00775 { 00776 if (this->FlushWriteBuffer()) 00777 { 00778 if (this->Instance->SocketCull.find(this) == this->Instance->SocketCull.end()) 00779 this->Instance->SocketCull[this] = this; 00780 return; 00781 } 00782 } 00783 break; 00784 } 00785 }
|
|
|
This method marks the socket closed. The next time the core examines a socket marked as closed, the socket will be closed and the memory reclaimed. NOTE: This method is DEPRECIATED and will be ignored if called! Definition at line 447 of file inspsocket.cpp.
|
|
|
Whenever close() is called, OnClose() will be called first. Please note that this means OnClose will be called alongside OnError(), OnTimeout(), and Close(), and also when cancelling a listening socket by calling the destructor indirectly. Reimplemented in HttpServerSocket, and TreeSocket. Definition at line 706 of file inspsocket.cpp. Referenced by Close().
|
|
|
This method is called when an outbound connection on your socket is completed.
Reimplemented in TreeSocket. Definition at line 699 of file inspsocket.cpp. Referenced by Poll().
|
|
|
When there is data waiting to be read on a socket, the OnDataReady() method is called. Within this method, you *MUST* call the Read() method to read any pending data. At its lowest level, this event is signalled by the core via the socket engine. If you return false from this function, the core removes your socket from its list and erases it from the socket engine, then calls InspSocket::Close() and deletes it.
Reimplemented in HttpServerSocket, Notifier, and TreeSocket. Definition at line 703 of file inspsocket.cpp. Referenced by Poll().
|
|
|
When an established connection is terminated, the OnDisconnect method is triggered.
Reimplemented in TreeSocket. Definition at line 701 of file inspsocket.cpp.
|
|
|
This method is called when an error occurs. A closed socket in itself is not an error, however errors also generate close events.
Reimplemented in TreeSocket. Definition at line 700 of file inspsocket.cpp. Referenced by BindAddr(), DoConnect(), FlushWriteBuffer(), HandleEvent(), InspSocket(), SocketTimeout::Tick(), and ModuleSQLite3::~ModuleSQLite3().
|
|
||||||||||||
|
If your socket is a listening socket, when a new connection comes in on the socket this method will be called. Given the new file descriptor in the parameters, and the IP, it is recommended you copy them to a new instance of your socket class, e.g.: MySocket* newsocket = new MySocket(newfd,ip); Once you have done this, you can then associate the new socket with the core using Server::AddSocket(). Reimplemented in HttpServerSocket, Notifier, ResultNotifier, and TreeSocket. Definition at line 702 of file inspsocket.cpp. Referenced by Poll().
|
|
|
When an outbound connection fails, and the attempt times out, you will receive this event. The method will trigger once maxtime seconds are reached (as given in the constructor) just before the socket's descriptor is closed. A failed DNS lookup may cause this event if the DNS server is not responding, as well as a failed connect() call, because DNS lookups are nonblocking as implemented by this class. Reimplemented in TreeSocket. Definition at line 705 of file inspsocket.cpp. Referenced by SocketTimeout::Tick().
|
|
|
When it is ok to write to the socket, and a write event was requested, this method is triggered. Within this method you should call write() or send() etc, to send data to the other end of the socket. Further write events will not be triggered unless you call WantWrite().
Reimplemented in HttpServerSocket. Definition at line 704 of file inspsocket.cpp.
|
|
|
Only the core should call this function. When called, it is assumed the socket is ready to read data, and the method call routes the event to the various methods of InspSocket for you to handle. This can also cause the socket's state to change. Definition at line 585 of file inspsocket.cpp. References _accept, InspIRCd::Config, DEBUG, SocketEngine::DelFd(), EventHandler::fd, ServerConfig::GetIOHook(), CoreException::GetReason(), SocketEngine::GetRef(), CoreException::GetSource(), I_CONNECTED, I_CONNECTING, I_LISTENING, Instance, length, InspIRCd::Log(), MAX_DESCRIPTORS, irc::sockets::NonBlocking(), OnConnected(), OnDataReady(), OnIncomingConnection(), Module::OnRawSocketAccept(), Module::OnRawSocketConnect(), port, InspIRCd::SE, SetQueues(), and SetState(). 00586 { 00587 #ifdef WINDOWS 00588 if(Instance->SE->GetRef(this->fd) != this) 00589 return false; 00590 int incoming = -1; 00591 #else 00592 if (this->Instance->SE->GetRef(this->fd) != this) 00593 return false; 00594 00595 int incoming = -1; 00596 00597 if ((fd < 0) || (fd > MAX_DESCRIPTORS)) 00598 return false; 00599 #endif 00600 switch (this->state) 00601 { 00602 case I_CONNECTING: 00603 /* Our socket was in write-state, so delete it and re-add it 00604 * in read-state. 00605 */ 00606 #ifndef WINDOWS 00607 if (this->fd > -1) 00608 { 00609 this->Instance->SE->DelFd(this); 00610 this->SetState(I_CONNECTED); 00611 if (!this->Instance->SE->AddFd(this)) 00612 return false; 00613 } 00614 #else 00615 this->SetState(I_CONNECTED); 00616 #endif 00617 Instance->Log(DEBUG,"Inspsocket I_CONNECTING state"); 00618 if (Instance->Config->GetIOHook(this)) 00619 { 00620 Instance->Log(DEBUG,"Hook for raw connect"); 00621 try 00622 { 00623 Instance->Config->GetIOHook(this)->OnRawSocketConnect(this->fd); 00624 } 00625 catch (CoreException& modexcept) 00626 { 00627 Instance->Log(DEBUG,"%s threw an exception: %s", modexcept.GetSource(), modexcept.GetReason()); 00628 } 00629 } 00630 return this->OnConnected(); 00631 break; 00632 case I_LISTENING: 00633 { 00634 /* The [2] is required because we may write a sockaddr_in6 here, and sockaddr_in6 is larger than sockaddr, where sockaddr_in4 is not. */ 00635 sockaddr* client = new sockaddr[2]; 00636 length = sizeof (sockaddr_in); 00637 std::string recvip; 00638 #ifdef IPV6 00639 if ((!*this->host) || strchr(this->host, ':')) 00640 length = sizeof(sockaddr_in6); 00641 #endif 00642 incoming = _accept (this->fd, client, &length); 00643 #ifdef IPV6 00644 if ((!*this->host) || strchr(this->host, ':')) 00645 { 00646 char buf[1024]; 00647 recvip = inet_ntop(AF_INET6, &((sockaddr_in6*)client)->sin6_addr, buf, sizeof(buf)); 00648 } 00649 else 00650 #endif 00651 recvip = inet_ntoa(((sockaddr_in*)client)->sin_addr); 00652 this->OnIncomingConnection(incoming, (char*)recvip.c_str()); 00653 00654 NonBlocking(incoming); 00655 00656 if (this->IsIOHooked) 00657 { 00658 try 00659 { 00660 Instance->Config->GetIOHook(this)->OnRawSocketAccept(incoming, recvip.c_str(), this->port); 00661 } 00662 catch (CoreException& modexcept) 00663 { 00664 Instance->Log(DEBUG,"%s threw an exception: %s", modexcept.GetSource(), modexcept.GetReason()); 00665 } 00666 } 00667 00668 this->SetQueues(incoming); 00669 00670 delete[] client; 00671 return true; 00672 } 00673 break; 00674 case I_CONNECTED: 00675 /* Process the read event */ 00676 return this->OnDataReady(); 00677 break; 00678 default: 00679 break; 00680 } 00681 return true; 00682 }
|
|
|
Reads all pending bytes from the socket into a char* array which can be up to 16 kilobytes in length.
Definition at line 388 of file inspsocket.cpp. References InspIRCd::Config, DEFAULT, EventHandler::fd, ServerConfig::GetIOHook(), CoreException::GetReason(), CoreException::GetSource(), ibuf, Instance, InspIRCd::Log(), MAX_DESCRIPTORS, and Module::OnRawSocketRead(). Referenced by TreeSocket::OnDataReady(), and HttpServerSocket::OnDataReady(). 00389 { 00390 #ifdef WINDOWS 00391 if ((fd < 0) || (m_internalFd > MAX_DESCRIPTORS)) 00392 #else 00393 if ((fd < 0) || (fd > MAX_DESCRIPTORS)) 00394 #endif 00395 return NULL; 00396 00397 int n = 0; 00398 00399 if (this->IsIOHooked) 00400 { 00401 int result2 = 0; 00402 int MOD_RESULT = 0; 00403 try 00404 { 00405 MOD_RESULT = Instance->Config->GetIOHook(this)->OnRawSocketRead(this->fd,this->ibuf,sizeof(this->ibuf) - 1,result2); 00406 } 00407 catch (CoreException& modexcept) 00408 { 00409 Instance->Log(DEFAULT,"%s threw an exception: %s", modexcept.GetSource(), modexcept.GetReason()); 00410 } 00411 if (MOD_RESULT < 0) 00412 { 00413 n = -1; 00414 errno = EAGAIN; 00415 } 00416 else 00417 { 00418 n = result2; 00419 } 00420 } 00421 else 00422 { 00423 n = recv(this->fd,this->ibuf,sizeof(this->ibuf) - 1,0); 00424 } 00425 00426 /* 00427 * This used to do some silly bounds checking instead of just passing bufsize - 1 to recv. 00428 * Not only does that make absolutely no sense, but it could potentially result in a read buffer's worth 00429 * of data being thrown into the bit bucket for no good reason, which is just *stupid*.. do things correctly now. 00430 * --w00t (july 2, 2008) 00431 */ 00432 if (n > 0) 00433 { 00434 ibuf[n] = 0; 00435 return ibuf; 00436 } 00437 else 00438 { 00439 int err = errno; 00440 if (err == EAGAIN) 00441 return ""; 00442 else 00443 return NULL; 00444 } 00445 }
|
|
|
Returns true if this socket is readable.
Reimplemented from EventHandler. Definition at line 23 of file inspsocket.cpp. References I_CONNECTING. 00024 { 00025 return ((this->state != I_CONNECTING) && (this->WaitingForWriteEvent == false)); 00026 }
|
|
|
Set the queue sizes This private method sets the operating system queue sizes for this socket to 65535 so that it can queue more information without application-level queueing which was required in older software.
Definition at line 148 of file inspsocket.cpp. Referenced by DoConnect(), and Poll(). 00149 { 00150 // attempt to increase socket sendq and recvq as high as its possible 00151 int sendbuf = 32768; 00152 int recvbuf = 32768; 00153 if(setsockopt(nfd,SOL_SOCKET,SO_SNDBUF,(const char *)&sendbuf,sizeof(sendbuf)) || setsockopt(nfd,SOL_SOCKET,SO_RCVBUF,(const char *)&recvbuf,sizeof(sendbuf))) 00154 { 00155 //this->Instance->Log(DEFAULT, "Could not increase SO_SNDBUF/SO_RCVBUF for socket %u", GetFd()); 00156 // per 1.2 change, commenting this out .. sick of people trying to interpret this 00157 } 00158 }
|
|
|
Changes the socket's state. The core uses this to change socket states, and you should not call it directly. Definition at line 684 of file inspsocket.cpp. References state. Referenced by Poll(). 00685 { 00686 this->state = s; 00687 }
|
|
|
Call this to receive the next write event that comes along for this fd to the OnWriteReady method.
Definition at line 142 of file inspsocket.cpp. References Instance, InspIRCd::SE, WaitingForWriteEvent, and SocketEngine::WantWrite(). 00143 { 00144 this->Instance->SE->WantWrite(this); 00145 this->WaitingForWriteEvent = true; 00146 }
|
|
|
Writes a std::string to the socket. No carriage returns or linefeeds are appended to the string.
Definition at line 463 of file inspsocket.cpp. References Instance, outbuffer, InspIRCd::SE, and SocketEngine::WantWrite(). Referenced by HttpServerSocket::Page(), HttpServerSocket::SendHeaders(), HttpServerSocket::ServeData(), and TreeSocket::WriteLine(). 00464 { 00465 /* Try and append the data to the back of the queue, and send it on its way 00466 */ 00467 outbuffer.push_back(data); 00468 this->Instance->SE->WantWrite(this); 00469 }
|
|
|
Bind IP.
Definition at line 119 of file inspsocket.h. Referenced by InspSocket(). |
|
|
When the socket has been marked as closing, this flag will be set to true, then the next time the socket is examined, the socket is deleted and closed.
Definition at line 208 of file inspsocket.h. Referenced by InspSocket(), and ModuleSQLite3::~ModuleSQLite3(). |
|
|
The hostname connected to.
Definition at line 149 of file inspsocket.h. Referenced by InspSocket(). |
|
|
Socket input buffer, used by read(). The class which extends InspSocket is expected to implement an extendable buffer which can grow much larger than 64k, this buffer is just designed to be temporary storage. space. Definition at line 177 of file inspsocket.h. Referenced by Read(). |
|
|
|
The IP address being connected to stored in string form for easy retrieval by accessors.
Definition at line 184 of file inspsocket.h. Referenced by BindAddr(), and GetIP(). |
|
|
Is hooked by a module for low level IO.
Definition at line 124 of file inspsocket.h. Referenced by ServerConfig::AddIOHook(), and InspSocket(). |
|
|
Used by accept() to indicate the sizes of the sockaddr_in structures.
Definition at line 190 of file inspsocket.h. Referenced by FlushWriteBuffer(), TreeSocket::IntroduceClient(), and Poll(). |
|
|
Socket output buffer (binary safe).
Definition at line 144 of file inspsocket.h. Referenced by FlushWriteBuffer(), and Write(). |
|
|
The port connected to, or the port this socket is listening on.
Definition at line 155 of file inspsocket.h. Referenced by InspSocket(), and Poll(). |
|
|
The state for this socket, either listening, connecting, connected or error.
Definition at line 162 of file inspsocket.h. Referenced by BindAddr(), DoConnect(), FlushWriteBuffer(), GetState(), InspSocket(), SetState(), SocketTimeout::Tick(), and ModuleSQLite3::~ModuleSQLite3(). |
|
|
This value is true if the socket has timed out.
Definition at line 168 of file inspsocket.h. Referenced by SocketTimeout::Tick(). |
|
|
Timeout class or NULL.
Definition at line 134 of file inspsocket.h. Referenced by DoConnect(), InspSocket(), SocketTimeout::Tick(), and ~InspSocket(). |
|
|
Timeout length.
Definition at line 139 of file inspsocket.h. Referenced by DoConnect(), and InspSocket(). |
|
|
Set to true when we're waiting for a write event. If this is true and a write event comes in, we call the write instead of the read method. Definition at line 214 of file inspsocket.h. Referenced by HandleEvent(), InspSocket(), HttpServerSocket::SetWrite(), and WantWrite(). |