]> git.netwichtig.de Git - user/henk/code/inspircd.git/blobdiff - src/inspircd_io.cpp
Regressed buffering code
[user/henk/code/inspircd.git] / src / inspircd_io.cpp
index 15b5fb5a29939cd31a654c2b3be07d6f9a28bdda..328d7c67ed25a3ddfde09331c70b744a57b9719d 100644 (file)
@@ -35,7 +35,7 @@ using namespace std;
 
 extern ServerConfig *Config;
 extern InspIRCd* ServerInstance;
-extern int openSockfd[MAXSOCKS];
+extern int openSockfd[MAX_DESCRIPTORS];
 extern time_t TIME;
 
 extern int MODCOUNT;
@@ -262,7 +262,7 @@ bool ValidateServerName(const char* tag, const char* value, void* data)
                log(DEFAULT,"WARNING: <server:name> '%s' is not a fully-qualified domain name. Changed to '%s%c'",x,x,'.');
                charlcat(x,'.',MAXBUF);
        }
-       strlower(x);
+       //strlower(x);
        return true;
 }
 
@@ -344,48 +344,48 @@ bool DoConnect(const char* tag, char** entries, void** values, int* types)
        int* localmax = (int*)values[9];
        int* globalmax = (int*)values[10];
 
-        if (*allow)
-        {
-                c.host = allow;
-                c.type = CC_ALLOW;
-                c.pass = password;
-                c.registration_timeout = *timeout;
-                c.pingtime = *pingfreq;
-                c.flood = *flood;
-                c.threshold = *threshold;
-                c.sendqmax = *sendq;
-                c.recvqmax = *recvq;
-                c.maxlocal = *localmax;
-                c.maxglobal = *globalmax;
-
-
-                if (c.maxlocal == 0)
+       if (*allow)
+       {
+               c.host = allow;
+               c.type = CC_ALLOW;
+               c.pass = password;
+               c.registration_timeout = *timeout;
+               c.pingtime = *pingfreq;
+               c.flood = *flood;
+               c.threshold = *threshold;
+               c.sendqmax = *sendq;
+               c.recvqmax = *recvq;
+               c.maxlocal = *localmax;
+               c.maxglobal = *globalmax;
+
+
+               if (c.maxlocal == 0)
                        c.maxlocal = 3;
-                if (c.maxglobal == 0)
+               if (c.maxglobal == 0)
                        c.maxglobal = 3;
-                if (c.threshold == 0)
-                {
+               if (c.threshold == 0)
+               {
                        c.threshold = 1;
                        c.flood = 999;
                        log(DEFAULT,"Warning: Connect allow line '%s' has no flood/threshold settings. Setting this tag to 999 lines in 1 second.",c.host.c_str());
-                }
-                if (c.sendqmax == 0)
+               }
+               if (c.sendqmax == 0)
                        c.sendqmax = 262114;
-                if (c.recvqmax == 0)
+               if (c.recvqmax == 0)
                        c.recvqmax = 4096;
-                if (c.registration_timeout == 0)
+               if (c.registration_timeout == 0)
                        c.registration_timeout = 90;
-                if (c.pingtime == 0)
+               if (c.pingtime == 0)
                        c.pingtime = 120;
-                Config->Classes.push_back(c);
-        }
-        else
-        {
-                c.host = deny;
-                c.type = CC_DENY;
-                Config->Classes.push_back(c);
-                log(DEBUG,"Read connect class type DENY, host=%s",deny);
-        }
+               Config->Classes.push_back(c);
+       }
+       else
+       {
+               c.host = deny;
+               c.type = CC_DENY;
+               Config->Classes.push_back(c);
+               log(DEBUG,"Read connect class type DENY, host=%s",deny);
+       }
 
        return true;
 }
@@ -451,34 +451,34 @@ bool DoModule(const char* tag, char** entries, void** values, int* types)
  */
 bool DoneModule(const char* tag)
 {
-        // now create a list of new modules that are due to be loaded
-        // and a seperate list of modules which are due to be unloaded
-        for (std::vector<std::string>::iterator _new = new_module_names.begin(); _new != new_module_names.end(); _new++)
-        {
-                bool added = true;
-
-                for (std::vector<std::string>::iterator old = old_module_names.begin(); old != old_module_names.end(); old++)
-                {
-                        if (*old == *_new)
-                                added = false;
-                }
-
-                if (added)
-                        added_modules.push_back(*_new);
-        }
-
-        for (std::vector<std::string>::iterator oldm = old_module_names.begin(); oldm != old_module_names.end(); oldm++)
-        {
-                bool removed = true;
-                for (std::vector<std::string>::iterator newm = new_module_names.begin(); newm != new_module_names.end(); newm++)
-                {
-                        if (*newm == *oldm)
-                                removed = false;
-                }
-
-                if (removed)
-                        removed_modules.push_back(*oldm);
-        }
+       // now create a list of new modules that are due to be loaded
+       // and a seperate list of modules which are due to be unloaded
+       for (std::vector<std::string>::iterator _new = new_module_names.begin(); _new != new_module_names.end(); _new++)
+       {
+               bool added = true;
+
+               for (std::vector<std::string>::iterator old = old_module_names.begin(); old != old_module_names.end(); old++)
+               {
+                       if (*old == *_new)
+                               added = false;
+               }
+
+               if (added)
+                       added_modules.push_back(*_new);
+       }
+
+       for (std::vector<std::string>::iterator oldm = old_module_names.begin(); oldm != old_module_names.end(); oldm++)
+       {
+               bool removed = true;
+               for (std::vector<std::string>::iterator newm = new_module_names.begin(); newm != new_module_names.end(); newm++)
+               {
+                       if (*newm == *oldm)
+                               removed = false;
+               }
+
+               if (removed)
+                       removed_modules.push_back(*oldm);
+       }
        return true;
 }
 
@@ -519,7 +519,7 @@ void ServerConfig::Read(bool bail, userrec* user)
        std::stringstream errstr;       /* String stream containing the error output */
 
        /* These tags MUST occur and must ONLY occur once in the config file */
-       static char* Once[] = { "server", "admin", "files", "power", "options", "pid" };
+       static char* Once[] = { "server", "admin", "files", "power", "options", "pid", NULL };
 
        /* These tags can occur ONCE or not at all */
        static InitialConfig Values[] = {
@@ -563,7 +563,7 @@ void ServerConfig::Read(bool bail, userrec* user)
 
                {"connect",
                                {"allow",       "deny",         "password",     "timeout",      "pingfreq",     "flood",
-                               "threshold",    "sendq",        "recvq",        "localmax",     "globalmax",    NULL},
+                               "threshold",    "sendq",        "recvq",        "localmax",     "globalmax",    NULL},
                                {DT_CHARPTR,    DT_CHARPTR,     DT_CHARPTR,     DT_INTEGER,     DT_INTEGER,     DT_INTEGER,
                                 DT_INTEGER,    DT_INTEGER,     DT_INTEGER,     DT_INTEGER,     DT_INTEGER},
                                InitConnect, DoConnect, DoneConnect},
@@ -753,6 +753,8 @@ void ServerConfig::Read(bool bail, userrec* user)
         */
        if (!bail)
        {
+               ServerInstance->stats->BoundPortCount = BindPorts(false);
+
                if (!removed_modules.empty())
                        for (std::vector<std::string>::iterator removing = removed_modules.begin(); removing != removed_modules.end(); removing++)
                        {
@@ -795,7 +797,7 @@ void ServerConfig::Read(bool bail, userrec* user)
        }
 }
 
-void Exit (int status)
+void Exit(int status)
 {
        if (Config->log_file)
                fclose(Config->log_file);
@@ -830,7 +832,7 @@ void Rehash(int status)
 
 
 
-void Start (void)
+void Start()
 {
        printf("\033[1;32mInspire Internet Relay Chat Server, compiled %s at %s\n",__DATE__,__TIME__);
        printf("(C) ChatSpike Development team.\033[0m\n\n");
@@ -839,7 +841,7 @@ void Start (void)
        printf("Name concept:\t\t\033[1;32mLord_Zathras\033[0m\n\n");
 }
 
-void WritePID(std::string filename)
+void WritePID(const std::string &filename)
 {
        ofstream outfile(filename.c_str());
        if (outfile.is_open())
@@ -865,7 +867,7 @@ void SetSignals()
 }
 
 
-int DaemonSeed (void)
+bool DaemonSeed()
 {
        int childpid;
        if ((childpid = fork ()) < 0)
@@ -886,7 +888,7 @@ int DaemonSeed (void)
                if (getrlimit(RLIMIT_CORE, &rl) == -1)
                {
                        log(DEFAULT,"Failed to getrlimit()!");
-                       return(FALSE);
+                       return false;
                }
                else
                {
@@ -896,7 +898,7 @@ int DaemonSeed (void)
                }
        }
   
-       return (TRUE);
+       return true;
 }
 
 
@@ -1459,8 +1461,14 @@ int ServerConfig::ConfValueInteger(char* tag, char* var, int index, std::strings
        return atoi(result);
 }
 
-// This will bind a socket to a port. It works for UDP/TCP
-int BindSocket (int sockfd, struct sockaddr_in client, struct sockaddr_in server, int port, char* addr)
+/** This will bind a socket to a port. It works for UDP/TCP.
+ * If a hostname is given to bind to, the function will first
+ * attempt to resolve the hostname, then bind to the IP the 
+ * hostname resolves to. This is a blocking lookup blocking for
+ * a maximum of one second before it times out, using the DNS
+ * server specified in the configuration file.
+ */ 
+bool BindSocket(int sockfd, struct sockaddr_in client, struct sockaddr_in server, int port, char* addr)
 {
        memset((char *)&server,0,sizeof(server));
        struct in_addr addy;
@@ -1483,7 +1491,7 @@ int BindSocket (int sockfd, struct sockaddr_in client, struct sockaddr_in server
                else
                {
                        log(DEFAULT,"WARNING: Could not resolve '%s' to an IP for binding to on port %d",addr,port);
-                       return(FALSE);
+                       return false;
                }
        }
        server.sin_family = AF_INET;
@@ -1501,7 +1509,7 @@ int BindSocket (int sockfd, struct sockaddr_in client, struct sockaddr_in server
        server.sin_port = htons(port);
        if (bind(sockfd,(struct sockaddr*)&server,sizeof(server)) < 0)
        {
-               return(ERROR);
+               return false;
        }
        else
        {
@@ -1509,25 +1517,29 @@ int BindSocket (int sockfd, struct sockaddr_in client, struct sockaddr_in server
                if (listen(sockfd, Config->MaxConn) == -1)
                {
                        log(DEFAULT,"ERROR in listen(): %s",strerror(errno));
-                       return(FALSE);
+                       return false;
                }
                else
                {
-                       return(TRUE);
+                       NonBlocking(sockfd);
+                       return true;
                }
        }
 }
 
 
 // Open a TCP Socket
-int OpenTCPSocket (void)
+int OpenTCPSocket()
 {
        int sockfd;
        int on = 1;
        struct linger linger = { 0 };
   
        if ((sockfd = socket (AF_INET, SOCK_STREAM, 0)) < 0)
+       {
+               log(DEFAULT,"Error creating TCP socket: %s",strerror(errno));
                return (ERROR);
+       }
        else
        {
                setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (const char*)&on, sizeof(on));
@@ -1539,13 +1551,77 @@ int OpenTCPSocket (void)
        }
 }
 
-int BindPorts()
+bool HasPort(int port, char* addr)
+{
+       for (int count = 0; count < ServerInstance->stats->BoundPortCount; count++)
+       {
+               if ((port == Config->ports[count]) && (!strcasecmp(Config->addrs[count],addr)))
+               {
+                       return true;
+               }
+       }
+       return false;
+}
+
+int BindPorts(bool bail)
 {
        char configToken[MAXBUF], Addr[MAXBUF], Type[MAXBUF];
        sockaddr_in client,server;
        int clientportcount = 0;
        int BoundPortCount = 0;
 
+       if (!bail)
+       {
+               int InitialPortCount = ServerInstance->stats->BoundPortCount;
+               log(DEBUG,"Initial port count: %d",InitialPortCount);
+
+               for (int count = 0; count < Config->ConfValueEnum("bind",&Config->config_f); count++)
+               {
+                       Config->ConfValue("bind","port",count,configToken,&Config->config_f);
+                       Config->ConfValue("bind","address",count,Addr,&Config->config_f);
+                       Config->ConfValue("bind","type",count,Type,&Config->config_f);
+                       if (((!*Type) || (!strcmp(Type,"clients"))) && (!HasPort(atoi(configToken),Addr)))
+                       {
+                               // modules handle server bind types now
+                               Config->ports[clientportcount+InitialPortCount] = atoi(configToken);
+                               if (*Addr == '*')
+                                       *Addr = 0;
+
+                               strlcpy(Config->addrs[clientportcount+InitialPortCount],Addr,256);
+                               clientportcount++;
+                               log(DEBUG,"NEW binding %s:%s [%s] from config",Addr,configToken, Type);
+                       }
+               }
+               int PortCount = clientportcount;
+               if (PortCount)
+               {
+                       for (int count = InitialPortCount; count < InitialPortCount + PortCount; count++)
+                       {
+                               if ((openSockfd[count] = OpenTCPSocket()) == ERROR)
+                               {
+                                       log(DEBUG,"Bad fd %d binding port [%s:%d]",openSockfd[count],Config->addrs[count],Config->ports[count]);
+                                       return ERROR;
+                               }
+                               if (!BindSocket(openSockfd[count],client,server,Config->ports[count],Config->addrs[count]))
+                               {
+                                       log(DEFAULT,"Failed to bind port [%s:%d]: %s",Config->addrs[count],Config->ports[count],strerror(errno));
+                               }
+                               else
+                               {
+                                       /* Associate the new open port with a slot in the socket engine */
+                                       ServerInstance->SE->AddFd(openSockfd[count],true,X_LISTEN);
+                                       BoundPortCount++;
+                               }
+                       }
+                       return InitialPortCount + BoundPortCount;
+               }
+               else
+               {
+                       log(DEBUG,"There is nothing new to bind!");
+               }
+               return InitialPortCount;
+       }
+
        for (int count = 0; count < Config->ConfValueEnum("bind",&Config->config_f); count++)
        {
                Config->ConfValue("bind","port",count,configToken,&Config->config_f);
@@ -1566,7 +1642,7 @@ int BindPorts()
 
                        strlcpy(Config->addrs[clientportcount],Addr,256);
                        clientportcount++;
-                       log(DEBUG,"InspIRCd: startup: read binding %s:%s [%s] from config",Addr,configToken, Type);
+                       log(DEBUG,"Binding %s:%s [%s] from config",Addr,configToken, Type);
                }
        }
 
@@ -1576,13 +1652,13 @@ int BindPorts()
        {
                if ((openSockfd[BoundPortCount] = OpenTCPSocket()) == ERROR)
                {
-                       log(DEBUG,"InspIRCd: startup: bad fd %lu binding port [%s:%d]",(unsigned long)openSockfd[BoundPortCount],Config->addrs[count],(unsigned long)Config->ports[count]);
-                       return(ERROR);
+                       log(DEBUG,"Bad fd %d binding port [%s:%d]",openSockfd[BoundPortCount],Config->addrs[count],Config->ports[count]);
+                       return ERROR;
                }
 
-               if (BindSocket(openSockfd[BoundPortCount],client,server,Config->ports[count],Config->addrs[count]) == ERROR)
+               if (!BindSocket(openSockfd[BoundPortCount],client,server,Config->ports[count],Config->addrs[count]))
                {
-                       log(DEFAULT,"InspIRCd: startup: failed to bind port [%s:%lu]: %s",Config->addrs[count],(unsigned long)Config->ports[count],strerror(errno));
+                       log(DEFAULT,"Failed to bind port [%s:%d]: %s",Config->addrs[count],Config->ports[count],strerror(errno));
                }
                else
                {
@@ -1594,9 +1670,9 @@ int BindPorts()
        /* if we didn't bind to anything then abort */
        if (!BoundPortCount)
        {
-               log(DEFAULT,"InspIRCd: startup: no ports bound, bailing!");
-               printf("\nERROR: Was not able to bind any of %lu ports! Please check your configuration.\n\n", (unsigned long)PortCount);
-               return (ERROR);
+               log(DEFAULT,"No ports bound, bailing!");
+               printf("\nERROR: Could not bind any of %d ports! Please check your configuration.\n\n", PortCount);
+               return ERROR;
        }
 
        return BoundPortCount;