int WHOWAS_MAX = 100; // default 100 people maximum in the WHOWAS list
int DieDelay = 5;
time_t startup_time = time(NULL);
-int NetBufferSize = 10240; // NetBufferSize used as the buffer size for all read() ops
+int NetBufferSize = 10240; // NetBufferSize used as the buffer size for all read() ops
+int MaxConn = SOMAXCONN; // size of accept() backlog (128 by default on *BSD)
extern int MaxWhoResults;
time_t nb_start = 0;
int dns_timeout = 5;
void ReadConfig(bool bail, userrec* user)
{
- char dbg[MAXBUF],pauseval[MAXBUF],Value[MAXBUF],timeout[MAXBUF],NB[MAXBUF],flood[MAXBUF],MW[MAXBUF];
+ char dbg[MAXBUF],pauseval[MAXBUF],Value[MAXBUF],timeout[MAXBUF],NB[MAXBUF],flood[MAXBUF],MW[MAXBUF],MCON[MAXBUF];
char AH[MAXBUF],AP[MAXBUF],AF[MAXBUF],DNT[MAXBUF],pfreq[MAXBUF],thold[MAXBUF],sqmax[MAXBUF],rqmax[MAXBUF];
ConnectClass c;
std::stringstream errstr;
ConfValue("dns","timeout",0,DNT,&config_f);
ConfValue("options","moduledir",0,ModPath,&config_f);
ConfValue("disabled","commands",0,DisabledCommands,&config_f);
+ ConfValue("options","somaxconn",0,MCON,&config_f);
+ MaxConn = atoi(MCON);
+ if (MaxConn > SOMAXCONN)
+ log(DEFAULT,"WARNING: <options:somaxconn> value may be higher than the system-defined SOMAXCONN value!");
NetBufferSize = atoi(NB);
MaxWhoResults = atoi(MW);
dns_timeout = atoi(DNT);
if (!dns_timeout)
dns_timeout = 5;
+ if (!MaxConn)
+ MaxConn = SOMAXCONN;
if (!DNSServer[0])
strlcpy(DNSServer,"127.0.0.1",MAXBUF);
if (!ModPath[0])
NetSendToAll(buffer);
}
+ user->FlushWriteBuf();
+
FOREACH_MOD OnUserDisconnect(user);
if (user->fd > -1)
shutdown(user->fd,2);
close(user->fd);
}
-
- if (user->registered == 7) {
- WriteOpers("*** Client exiting: %s!%s@%s [%s]",user->nick,user->ident,user->host,reason);
- AddWhoWas(user);
- }
+ // this must come before the WriteOpers so that it doesnt try to fill their buffer with anything
+ // if they were an oper with +s.
if (user->registered == 7) {
purge_empty_chans(user);
- }
+ WriteOpers("*** Client exiting: %s!%s@%s [%s]",user->nick,user->ident,user->host,reason);
+ AddWhoWas(user);
+ }
if (iter != clientlist.end())
{
Write(user->fd,"ERROR :Closing link (%s@%s) [%s]",user->ident,user->host,reason);
log(DEBUG,"closing fd %lu",(unsigned long)user->fd);
+ user->FlushWriteBuf();
+
if (user->registered == 7) {
FOREACH_MOD OnUserQuit(user);
WriteCommonExcept(user,"QUIT :%s",reason);
bool LoadModule(const char* filename)
{
char modfile[MAXBUF];
+#ifdef STATIC_LINK
+ snprintf(modfile,MAXBUF,"%s",filename);
+#else
snprintf(modfile,MAXBUF,"%s/%s",ModPath,filename);
+#endif
std::string filename_str = filename;
+#ifndef STATIC_LINK
if (!DirValid(modfile))
{
log(DEFAULT,"Module %s is not within the modules directory.",modfile);
snprintf(MODERR,MAXBUF,"Module %s is not within the modules directory.",modfile);
return false;
}
+#endif
log(DEBUG,"Loading module: %s",modfile);
+#ifndef STATIC_LINK
if (FileExists(modfile))
{
+#endif
for (int j = 0; j < module_names.size(); j++)
{
if (module_names[j] == filename_str)
snprintf(MODERR,MAXBUF,"Factory function failed!");
return false;
}
+#ifndef STATIC_LINK
}
else
{
snprintf(MODERR,MAXBUF,"Module file could not be found");
return false;
}
+#endif
MODCOUNT++;
return true;
}
{
struct kevent ke;
log(DEBUG,"kqueue: Add listening socket to events, kq=%d socket=%d",lkq,openSockfd[count]);
- EV_SET(&ke, openSockfd[count], EVFILT_READ, EV_ADD, 0, 32, NULL);
+ EV_SET(&ke, openSockfd[count], EVFILT_READ, EV_ADD, 0, MaxConn, NULL);
int i = kevent(lkq, &ke, 1, 0, 0, NULL);
if (i == -1)
{
if (me[t])
{
log(DEBUG,"kqueue: Add listening SERVER socket to events, kq=%d socket=%d",skq,me[t]->fd);
- EV_SET(&ke, me[t]->fd, EVFILT_READ, EV_ADD, 0, 32, NULL);
+ EV_SET(&ke, me[t]->fd, EVFILT_READ, EV_ADD, 0, MaxConn, NULL);
int i = kevent(skq, &ke, 1, 0, 0, NULL);
if (i == -1)
{
#ifdef USE_EPOLL
i = epoll_wait(sep, event, 1, EP_DELAY);
-#ifdef _POSIX_PRIORITY_SCHEDULING
- sched_yield();
-#endif
if (i > 0)
{
log(DEBUG,"epoll: Listening server socket event, i=%d, event.data.fd=%d",i,event[0].data.fd);
}
tvs.tv_usec = 30000L;
tvs.tv_sec = 0;
- int servresult = select(32767, &serverfds, NULL, NULL, &tvs);
+ int servresult = select(FD_SETSIZE, &serverfds, NULL, NULL, &tvs);
if (servresult > 0)
{
for (int x = 0; x != SERVERportCount; x++)
}
}
+ std::deque<std::string> msgs;
+ std::deque<std::string> sums;
for (int x = 0; x < SERVERportCount; x++)
{
- std::deque<std::string> msgs;
- std::deque<std::string> sums;
- msgs.clear();
sums.clear();
- if (me[x])
+ msgs.clear();
+ while ((me[x]) && (me[x]->RecvPacket(msgs, tcp_host, sums))) // returns 0 or more lines (can be multiple lines!)
{
- sums.clear();
- msgs.clear();
- while (me[x]->RecvPacket(msgs, tcp_host, sums))
+ for (int ctr = 0; ctr < msgs.size(); ctr++)
{
- for (int ctr = 0; ctr < msgs.size(); ctr++)
+ strlcpy(tcp_msg,msgs[ctr].c_str(),MAXBUF);
+ strlcpy(tcp_sum,msgs[ctr].c_str(),MAXBUF);
+ log(DEBUG,"Processing: %s",tcp_msg);
+ if (!tcp_msg[0])
+ {
+ log(DEBUG,"Invalid string from %s [route%lu]",tcp_host,(unsigned long)x);
+ break;
+ }
+ // during a netburst, send all data to all other linked servers
+ if ((((nb_start>0) && (tcp_msg[0] != 'Y') && (tcp_msg[0] != 'X') && (tcp_msg[0] != 'F'))) || (is_uline(tcp_host)))
{
- strlcpy(tcp_msg,msgs[ctr].c_str(),MAXBUF);
- strlcpy(tcp_sum,msgs[ctr].c_str(),MAXBUF);
- log(DEBUG,"Processing: %s",tcp_msg);
- if (!tcp_msg[0])
- {
- log(DEBUG,"Invalid string from %s [route%lu]",tcp_host,(unsigned long)x);
- break;
- }
- // during a netburst, send all data to all other linked servers
- if ((((nb_start>0) && (tcp_msg[0] != 'Y') && (tcp_msg[0] != 'X') && (tcp_msg[0] != 'F'))) || (is_uline(tcp_host)))
+ if (is_uline(tcp_host))
{
- if (is_uline(tcp_host))
+ if ((tcp_msg[0] != 'Y') && (tcp_msg[0] != 'X') && (tcp_msg[0] != 'F'))
{
- if ((tcp_msg[0] != 'Y') && (tcp_msg[0] != 'X') && (tcp_msg[0] != 'F'))
- {
- NetSendToAllExcept_WithSum(tcp_host,tcp_msg,tcp_sum);
- }
- }
- else
NetSendToAllExcept_WithSum(tcp_host,tcp_msg,tcp_sum);
+ }
}
- std::string msg = tcp_msg;
- FOREACH_MOD OnPacketReceive(msg,tcp_host);
- strlcpy(tcp_msg,msg.c_str(),MAXBUF);
- if (me[x])
- handle_link_packet(tcp_msg, tcp_host, me[x], tcp_sum);
+ else
+ NetSendToAllExcept_WithSum(tcp_host,tcp_msg,tcp_sum);
}
- //goto label;
+ std::string msg = tcp_msg;
+ FOREACH_MOD OnPacketReceive(msg,tcp_host);
+ strlcpy(tcp_msg,msg.c_str(),MAXBUF);
+ if (me[x])
+ handle_link_packet(tcp_msg, tcp_host, me[x], tcp_sum);
}
+ sums.clear(); // we're done, clear the list for the next operation
+ msgs.clear();
}
}
statsDnsBad++;
FullConnectUser(curr);
if (fd_ref_table[currfd] != curr) // something changed, bail pronto
- goto label;
+ goto label;
}
if ((curr->dns_done) && (curr->registered == 3) && (AllModulesReportReady(curr))) // both NICK and USER... and DNS
{
userrec* cu = fd_ref_table[ke.ident];
#endif
#ifdef USE_SELECT
+ tval.tv_sec = 0;
tval.tv_usec = 1000L;
- selectResult2 = select(65535, &sfd, NULL, NULL, &tval);
-
+ selectResult2 = select(FD_SETSIZE, &sfd, NULL, NULL, &tval);
// now loop through all of the items in this pool if any are waiting
- if (selectResult2 > 0)
+ if ((selectResult2 > 0) && (xcount != clientlist.end()))
for (user_hash::iterator count2a = xcount; count2a != endingiter; count2a++)
{
// SELECT: we have to iterate...
+ if (count2a == clientlist.end())
+ break;
userrec* cu = count2a->second;
#endif
}
}
- if ((currfd < 0) || (!fd_ref_table[currfd]))
- goto label;
+ goto label;
}
if ((result == -1) && (errno != EAGAIN) && (errno != EINTR))
{
#endif
#ifdef USE_EPOLL
-#ifdef _POSIX_PRIORITY_SCHEDULING
- sched_yield();
-#endif
i = epoll_wait(lep, event, 32, EP_DELAY);
-#ifdef _POSIX_PRIORITY_SCHEDULING
- sched_yield();
-#endif
if (i > 0) for (j = 0; j < i; j++)
{
log(DEBUG,"epoll: Listening socket event, i=%d,events[j].data.fd=%d",i,event[j].data.fd);