summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/configreader.h6
-rw-r--r--include/inspsocket.h3
-rw-r--r--src/configreader.cpp35
-rw-r--r--src/inspsocket.cpp144
4 files changed, 153 insertions, 35 deletions
diff --git a/include/configreader.h b/include/configreader.h
index 1790bd847..2c048c849 100644
--- a/include/configreader.h
+++ b/include/configreader.h
@@ -30,6 +30,7 @@
class ServerConfig;
class InspIRCd;
+class InspSocket;
/** Types of data in the core config
*/
@@ -445,6 +446,8 @@ class ServerConfig : public Extensible
*/
std::map<int,Module*> IOHookModule;
+ std::map<InspSocket*, Module*> SocketIOHookModule;
+
/** The 005 tokens of this server (ISUPPORT)
* populated/repopulated upon loading or unloading
* modules.
@@ -560,6 +563,9 @@ class ServerConfig : public Extensible
Module* GetIOHook(int port);
bool AddIOHook(int port, Module* iomod);
bool DelIOHook(int port);
+ Module* GetIOHook(InspSocket* is);
+ bool AddIOHook(InspSocket* is, Module* iomod);
+ bool DelIOHook(InspSocket* is);
static std::string GetFullProgDir(char** argv, int argc);
static bool DirValid(const char* dirandfile);
diff --git a/include/inspsocket.h b/include/inspsocket.h
index 71f16951e..52de46c2d 100644
--- a/include/inspsocket.h
+++ b/include/inspsocket.h
@@ -71,6 +71,9 @@ class SocketTimeout : public InspTimer
class InspSocket : public EventHandler
{
public:
+
+ bool IsIOHooked;
+
InspIRCd* Instance;
SocketTimeout* Timeout;
diff --git a/src/configreader.cpp b/src/configreader.cpp
index 73a0e25b1..f7c867544 100644
--- a/src/configreader.cpp
+++ b/src/configreader.cpp
@@ -57,6 +57,12 @@ Module* ServerConfig::GetIOHook(int port)
return (x != IOHookModule.end() ? x->second : NULL);
}
+Module* ServerConfig::GetIOHook(InspSocket* is)
+{
+ std::map<InspSocket*,Module*>::iterator x = SocketIOHookModule.find(is);
+ return (x != SocketIOHookModule.end() ? x->second : NULL);
+}
+
bool ServerConfig::AddIOHook(int port, Module* iomod)
{
if (!GetIOHook(port))
@@ -66,8 +72,22 @@ bool ServerConfig::AddIOHook(int port, Module* iomod)
}
else
{
- ModuleException err("Port already hooked by another module");
- throw(err);
+ throw ModuleException("Port already hooked by another module");
+ return false;
+ }
+}
+
+bool ServerConfig::AddIOHook(InspSocket* is, Module* iomod)
+{
+ if (!GetIOHook(is))
+ {
+ SocketIOHookModule[is] = iomod;
+ is->IsIOHooked = true;
+ return true;
+ }
+ else
+ {
+ throw ModuleException("InspSocket derived class already hooked by another module");
return false;
}
}
@@ -83,6 +103,17 @@ bool ServerConfig::DelIOHook(int port)
return false;
}
+bool ServerConfig::DelIOHook(InspSocket* is)
+{
+ std::map<InspSocket*,Module*>::iterator x = SocketIOHookModule.find(is);
+ if (x != SocketIOHookModule.end())
+ {
+ SocketIOHookModule.erase(x);
+ return true;
+ }
+ return false;
+}
+
bool ServerConfig::CheckOnce(char* tag, bool bail, userrec* user)
{
int count = ConfValueEnum(this->config_data, tag);
diff --git a/src/inspsocket.cpp b/src/inspsocket.cpp
index 5f5c2d6ec..9d2745a2d 100644
--- a/src/inspsocket.cpp
+++ b/src/inspsocket.cpp
@@ -35,6 +35,7 @@ InspSocket::InspSocket(InspIRCd* SI)
this->fd = -1;
this->WaitingForWriteEvent = false;
this->Instance = SI;
+ this->IsIOHooked = false;
}
InspSocket::InspSocket(InspIRCd* SI, int newfd, const char* ip)
@@ -44,6 +45,7 @@ InspSocket::InspSocket(InspIRCd* SI, int newfd, const char* ip)
strlcpy(this->IP,ip,MAXBUF);
this->WaitingForWriteEvent = false;
this->Instance = SI;
+ this->IsIOHooked = false;
if (this->fd > -1)
this->Instance->SE->AddFd(this);
}
@@ -54,6 +56,7 @@ InspSocket::InspSocket(InspIRCd* SI, const std::string &ipaddr, int aport, bool
this->Instance = SI;
strlcpy(host,ipaddr.c_str(),MAXBUF);
this->WaitingForWriteEvent = false;
+ this->IsIOHooked = false;
if (listening)
{
if ((this->fd = OpenTCPSocket()) == ERROR)
@@ -256,6 +259,17 @@ void InspSocket::Close()
{
if (this->fd > -1)
{
+ if (this->IsIOHooked)
+ {
+ try
+ {
+ Instance->Config->GetIOHook(this)->OnRawSocketClose(this->fd);
+ }
+ catch (ModuleException& modexcept)
+ {
+ Instance->Log(DEBUG,"Module exception cought: %s",modexcept.GetReason());
+ }
+ }
this->OnClose();
shutdown(this->fd,2);
close(this->fd);
@@ -271,7 +285,36 @@ char* InspSocket::Read()
{
if ((fd < 0) || (fd > MAX_DESCRIPTORS))
return NULL;
- int n = recv(this->fd,this->ibuf,sizeof(this->ibuf),0);
+
+ int n = 0;
+
+ if (this->IsIOHooked)
+ {
+ int result2 = 0;
+ int MOD_RESULT = 0;
+ try
+ {
+ MOD_RESULT = Instance->Config->GetIOHook(this)->OnRawSocketRead(this->fd,this->ibuf,sizeof(this->ibuf),result2);
+ }
+ catch (ModuleException& modexcept)
+ {
+ Instance->Log(DEBUG,"Module exception caught: %s",modexcept.GetReason());
+ }
+ if (MOD_RESULT < 0)
+ {
+ n = -1;
+ errno = EAGAIN;
+ }
+ else
+ {
+ n = result2;
+ }
+ }
+ else
+ {
+ n = recv(this->fd,this->ibuf,sizeof(this->ibuf),0);
+ }
+
if ((n > 0) && (n <= (int)sizeof(this->ibuf)))
{
ibuf[n] = 0;
@@ -318,44 +361,62 @@ bool InspSocket::FlushWriteBuffer()
errno = 0;
if ((this->fd > -1) && (this->state == I_CONNECTED))
{
- /* If we have multiple lines, try to send them all,
- * not just the first one -- Brain
- */
- while (outbuffer.size() && (errno != EAGAIN))
+ if (this->IsIOHooked)
{
- /* Send a line */
- int result = write(this->fd,outbuffer[0].c_str(),outbuffer[0].length());
- if (result > 0)
+ while (outbuffer.size() && (errno != EAGAIN))
{
- if ((unsigned int)result == outbuffer[0].length())
+ try
{
- /* The whole block was written (usually a line)
- * Pop the block off the front of the queue,
- * dont set errno, because we are clear of errors
- * and want to try and write the next block too.
- */
- outbuffer.pop_front();
+ Instance->Config->GetIOHook(this)->OnRawSocketWrite(this->fd, outbuffer[0].c_str(), outbuffer[0].length());
}
- else
+ catch (ModuleException& modexcept)
{
- std::string temp = outbuffer[0].substr(result);
- outbuffer[0] = temp;
- /* We didnt get the whole line out. arses.
- * Try again next time, i guess. Set errno,
- * because we shouldnt be writing any more now,
- * until the socketengine says its safe to do so.
- */
- errno = EAGAIN;
+ Instance->Log(DEBUG,"Module exception caught: %s",modexcept.GetReason());
+ return true;
}
}
- else if ((result == -1) && (errno != EAGAIN))
+ }
+ else
+ {
+ /* If we have multiple lines, try to send them all,
+ * not just the first one -- Brain
+ */
+ while (outbuffer.size() && (errno != EAGAIN))
{
- this->Instance->Log(DEBUG,"Write error on socket: %s",strerror(errno));
- this->OnError(I_ERR_WRITE);
- this->state = I_ERROR;
- this->Instance->SE->DelFd(this);
- this->Close();
- return true;
+ /* Send a line */
+ int result = write(this->fd,outbuffer[0].c_str(),outbuffer[0].length());
+ if (result > 0)
+ {
+ if ((unsigned int)result == outbuffer[0].length())
+ {
+ /* The whole block was written (usually a line)
+ * Pop the block off the front of the queue,
+ * dont set errno, because we are clear of errors
+ * and want to try and write the next block too.
+ */
+ outbuffer.pop_front();
+ }
+ else
+ {
+ std::string temp = outbuffer[0].substr(result);
+ outbuffer[0] = temp;
+ /* We didnt get the whole line out. arses.
+ * Try again next time, i guess. Set errno,
+ * because we shouldnt be writing any more now,
+ * until the socketengine says its safe to do so.
+ */
+ errno = EAGAIN;
+ }
+ }
+ else if ((result == -1) && (errno != EAGAIN))
+ {
+ this->Instance->Log(DEBUG,"Write error on socket: %s",strerror(errno));
+ this->OnError(I_ERR_WRITE);
+ this->state = I_ERROR;
+ this->Instance->SE->DelFd(this);
+ this->Close();
+ return true;
+ }
}
}
}
@@ -427,11 +488,28 @@ bool InspSocket::Poll()
case I_LISTENING:
length = sizeof (client);
incoming = accept (this->fd, (sockaddr*)&client,&length);
+
+ if (this->IsIOHooked)
+ {
+ try
+ {
+#ifdef IPV6
+ Instance->Config->GetIOHook(this)->OnRawSocketAccept(incoming, insp_ntoa(client.sin6_addr), this->port);
+#else
+ Instance->Config->GetIOHook(this)->OnRawSocketAccept(incoming, insp_ntoa(client.sin_addr), this->port);
+#endif
+ }
+ catch (ModuleException& modexcept)
+ {
+ Instance->Log(DEBUG,"Module exception cought: %s",modexcept.GetReason());
+ }
+ }
+
this->SetQueues(incoming);
#ifdef IPV6
- this->OnIncomingConnection(incoming,(char*)insp_ntoa(client.sin6_addr));
+ this->OnIncomingConnection(incoming, (char*)insp_ntoa(client.sin6_addr));
#else
- this->OnIncomingConnection(incoming,(char*)insp_ntoa(client.sin_addr));
+ this->OnIncomingConnection(incoming, (char*)insp_ntoa(client.sin_addr));
#endif
return true;
break;