]> git.netwichtig.de Git - user/henk/code/inspircd.git/commitdiff
Not yet tested -- allow iohooking of inspsockets
authorbrain <brain@e03df62e-2008-0410-955e-edbf42e46eb7>
Sat, 9 Dec 2006 18:36:24 +0000 (18:36 +0000)
committerbrain <brain@e03df62e-2008-0410-955e-edbf42e46eb7>
Sat, 9 Dec 2006 18:36:24 +0000 (18:36 +0000)
git-svn-id: http://svn.inspircd.org/repository/trunk/inspircd@5886 e03df62e-2008-0410-955e-edbf42e46eb7

include/configreader.h
include/inspsocket.h
src/configreader.cpp
src/inspsocket.cpp

index 1790bd8470c85e5875a8d9158a553c474530db92..2c048c849ba2598c4de2fb99e667a591db20d854 100644 (file)
@@ -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);
index 71f16951ec4ed02a59ded8c79f530dcc14977250..52de46c2da8a38309950a37fcd085c1c013e304a 100644 (file)
@@ -71,6 +71,9 @@ class SocketTimeout : public InspTimer
 class InspSocket : public EventHandler
 {
  public:
+
+       bool IsIOHooked;
+
        InspIRCd* Instance;
 
        SocketTimeout* Timeout;
index 73a0e25b1cc0fcb643368f8ed1eeb5ac93e94c0d..f7c867544c47c7606e8a783ec102a6bf4664f85c 100644 (file)
@@ -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);
index 5f5c2d6ec2d3701f6e2cf6244b6f99b97055d8da..9d2745a2df46496a1097d3fc4dd7cb74c7263ed3 100644 (file)
@@ -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;