diff options
-rwxr-xr-x | configure | 54 | ||||
-rw-r--r-- | docs/Doxyfile | 2 | ||||
-rw-r--r-- | docs/conf/modules.conf.example | 1 | ||||
-rw-r--r-- | include/modules/dns.h | 2 | ||||
-rw-r--r-- | include/socketengine.h | 16 | ||||
-rw-r--r-- | make/configure.pm | 38 | ||||
-rw-r--r-- | make/directive.pm | 6 | ||||
-rw-r--r-- | make/test/clock_gettime.cpp | 1 | ||||
-rw-r--r-- | make/test/compiler.cpp | 2 | ||||
-rw-r--r-- | make/test/compiler_info.cpp | 41 | ||||
-rwxr-xr-x | modulemanager | 3 | ||||
-rw-r--r-- | src/coremods/core_dns.cpp | 15 | ||||
-rw-r--r-- | src/modules/m_md5.cpp | 26 | ||||
-rw-r--r-- | src/modules/m_permchannels.cpp | 4 | ||||
-rw-r--r-- | src/socketengine.cpp | 36 | ||||
-rw-r--r-- | src/socketengines/socketengine_epoll.cpp | 2 | ||||
-rw-r--r-- | src/socketengines/socketengine_kqueue.cpp | 2 | ||||
-rw-r--r-- | src/socketengines/socketengine_ports.cpp | 2 | ||||
-rw-r--r-- | src/socketengines/socketengine_select.cpp | 2 |
19 files changed, 152 insertions, 103 deletions
@@ -130,7 +130,7 @@ our $interactive = !( my %version = get_version $opt_distribution_label; print_format "<|BOLD Configuring InspIRCd $version{FULL} on $^O.|>\n"; -our %config; +my %config; if ($interactive) { %config = read_config_file(CONFIGURE_CACHE_FILE); run_test CONFIGURE_CACHE_FILE, %config; @@ -159,41 +159,22 @@ my %compiler = get_compiler_info($config{CXX}); $config{HAS_CLOCK_GETTIME} = run_test 'clock_gettime()', test_file($config{CXX}, 'clock_gettime.cpp', $^O eq 'darwin' ? undef : '-lrt'); $config{HAS_EVENTFD} = run_test 'eventfd()', test_file($config{CXX}, 'eventfd.cpp'); -if ($config{HAS_EPOLL} = run_test 'epoll', test_header($config{CXX}, 'sys/epoll.h')) { - $config{SOCKETENGINE} //= 'epoll'; -} - -if ($config{HAS_KQUEUE} = run_test 'kqueue', test_file($config{CXX}, 'kqueue.cpp')) { - $config{SOCKETENGINE} //= 'kqueue'; -} - -if ($config{HAS_PORTS} = run_test 'Solaris IOCP', test_header($config{CXX}, 'port.h')) { - $config{SOCKETENGINE} //= 'ports'; -} - -if ($config{HAS_POLL} = run_test 'poll', test_header($config{CXX}, 'poll.h')) { - $config{SOCKETENGINE} //= 'poll'; -} - -# Select is available on all platforms -$config{HAS_SELECT} = 1; -$config{SOCKETENGINE} //= 'select'; +my @socketengines; +push @socketengines, 'epoll' if run_test 'epoll', test_header $config{CXX}, 'sys/epoll.h'; +push @socketengines, 'kqueue' if run_test 'kqueue', test_file $config{CXX}, 'kqueue.cpp'; +push @socketengines, 'ports' if run_test 'Solaris IOCP', test_header $config{CXX}, 'port.h'; +push @socketengines, 'poll' if run_test 'poll', test_header $config{CXX}, 'poll.h'; +push @socketengines, 'select'; if (defined $opt_socketengine) { - my $cfgkey = 'HAS_' . uc $opt_socketengine; - if ($config{$cfgkey} && -f "src/socketengines/socketengine_$opt_socketengine.cpp") { - $config{SOCKETENGINE} = $opt_socketengine; - } else { - print "Unable to use a socket engine which is not supported on this platform ($opt_socketengine)!\n"; - print "Available socket engines are:"; - foreach (<src/socketengines/socketengine_*.cpp>) { - s/src\/socketengines\/socketengine_(\w+)\.cpp/$1/; - print " $1" if $config{'HAS_' . uc $1}; - } - print "\n"; - exit 1; + unless (grep { $_ eq $opt_socketengine } @socketengines) { + my $reason = -f "src/socketengines/socketengine_$opt_socketengine.cpp" ? 'is not available on this platform' : 'does not exist'; + print_error "The socket engine you requested ($opt_socketengine) $reason!", + 'Available socket engines are:', + map { " * $_" } @socketengines; } } +$config{SOCKETENGINE} = $opt_socketengine // $socketengines[0]; if (defined $opt_system) { $config{BASE_DIR} = $opt_prefix // '/var/lib/inspircd'; @@ -240,6 +221,15 @@ $config{UID} = $user[2]; # Clear the screen. system 'tput', 'clear' if $interactive; +# Warn the user about clock drifting when running on OpenVZ. +if (-e '/proc/user_beancounters' || -e '/proc/vz/vzaquota') { + print_warning <<'EOW'; +You are building InspIRCd inside of an an OpenVZ container. If you +plan to use InspIRCd in this container then you should make sure that NTP is +configured on the Hardware Node. Failure to do so may result in clock drifting! +EOW +} + # Check that the user actually wants this version. if ($version{LABEL} ne 'release') { print_warning <<'EOW'; diff --git a/docs/Doxyfile b/docs/Doxyfile index 807020af5..f4e526bc7 100644 --- a/docs/Doxyfile +++ b/docs/Doxyfile @@ -1,6 +1,6 @@ DOXYFILE_ENCODING = UTF-8 PROJECT_NAME = InspIRCd -PROJECT_NUMBER = 2.0 +PROJECT_NUMBER = 3.0 PROJECT_BRIEF = PROJECT_LOGO = OUTPUT_DIRECTORY = docs/doxygen diff --git a/docs/conf/modules.conf.example b/docs/conf/modules.conf.example index 835e31795..33da80c56 100644 --- a/docs/conf/modules.conf.example +++ b/docs/conf/modules.conf.example @@ -1434,7 +1434,6 @@ #<include file="permchannels.conf"> # # You may also create channels on startup by using the <permchannels> block. -# Don't forget to set them +P in the modes, or they won't stay permanent. #<permchannels channel="#opers" modes="isP" topic="Opers only."> #-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-# diff --git a/include/modules/dns.h b/include/modules/dns.h index 5f2836761..61abd7144 100644 --- a/include/modules/dns.h +++ b/include/modules/dns.h @@ -33,6 +33,8 @@ namespace DNS QUERY_CNAME = 5, /* Reverse DNS lookup */ QUERY_PTR = 12, + /* TXT */ + QUERY_TXT = 16, /* IPv6 AAAA lookup */ QUERY_AAAA = 28 }; diff --git a/include/socketengine.h b/include/socketengine.h index c0026bfc6..b00643952 100644 --- a/include/socketengine.h +++ b/include/socketengine.h @@ -244,11 +244,19 @@ class CoreExport SocketEngine */ Statistics() : lastempty(0), TotalEvents(0), ReadEvents(0), WriteEvents(0), ErrorEvents(0) { } - /** Increase the counters for bytes sent/received in this second. - * @param len_in Bytes received, 0 if updating number of bytes written. - * @param len_out Bytes sent, 0 if updating number of bytes read. + /** Update counters for network data received. + * This should be called after every read-type syscall. + * @param len_in Number of bytes received, or -1 for error, as typically + * returned by a read-style syscall. */ - void Update(size_t len_in, size_t len_out); + void UpdateReadCounters(int len_in); + + /** Update counters for network data sent. + * This should be called after every write-type syscall. + * @param len_out Number of bytes sent, or -1 for error, as typically + * returned by a read-style syscall. + */ + void UpdateWriteCounters(int len_out); /** Get data transfer statistics. * @param kbitspersec_in Filled with incoming traffic in this second in kbit/s. diff --git a/make/configure.pm b/make/configure.pm index a10493318..dbbbf6509 100644 --- a/make/configure.pm +++ b/make/configure.pm @@ -208,9 +208,9 @@ sub test_file($$;$) { sub test_header($$;$) { my ($compiler, $header, $args) = @_; $args //= ''; - open(COMPILER, "| $compiler -E - $args ${\CONFIGURE_ERROR_PIPE}") or return 0; - print COMPILER "#include <$header>"; - close(COMPILER); + open(my $fh, "| $compiler -E - $args ${\CONFIGURE_ERROR_PIPE}") or return 0; + print $fh "#include <$header>"; + close $fh; return !$?; } @@ -227,19 +227,15 @@ sub write_configure_cache(%) { sub get_compiler_info($) { my $binary = shift; - my $version = `$binary -v 2>&1`; - if ($version =~ /Apple\sLLVM\sversion\s(\d+\.\d+)/i) { - # Apple version their LLVM releases slightly differently to the mainline LLVM. - # See https://trac.macports.org/wiki/XcodeVersionInfo for more information. - return (NAME => 'AppleClang', VERSION => $1); - } elsif ($version =~ /clang\sversion\s(\d+\.\d+)/i) { - return (NAME => 'Clang', VERSION => $1); - } elsif ($version =~ /gcc\sversion\s(\d+\.\d+)/i) { - return (NAME => 'GCC', VERSION => $1); - } elsif ($version =~ /(?:icc|icpc)\sversion\s(\d+\.\d+).\d+\s\(gcc\sversion\s(\d+\.\d+).\d+/i) { - return (NAME => 'ICC', VERSION => $1); + my %info = (NAME => 'Unknown', VERSION => '0.0'); + return %info if system "$binary -o __compiler_info make/test/compiler_info.cpp ${\CONFIGURE_ERROR_PIPE}"; + open(my $fh, '-|', './__compiler_info 2>/dev/null'); + while (my $line = <$fh>) { + $info{$1} = $2 if $line =~ /^([A-Z]+)\s(.+)$/; } - return (NAME => $binary, VERSION => '0.0'); + close $fh; + unlink './__compiler_info'; + return %info; } sub find_compiler { @@ -261,11 +257,11 @@ sub parse_templates($$$) { # Iterate through files in make/template. foreach (<make/template/*>) { print_format "Parsing <|GREEN $_|> ...\n"; - open(TEMPLATE, $_) or print_error "unable to read $_: $!"; + open(my $fh, $_) or print_error "unable to read $_: $!"; my (@lines, $mode, @platforms, %targets); # First pass: parse template variables and directives. - while (my $line = <TEMPLATE>) { + while (my $line = <$fh>) { chomp $line; # Does this line match a variable? @@ -305,7 +301,7 @@ sub parse_templates($$$) { } push @lines, $line; } - close(TEMPLATE); + close $fh; # Only proceed if this file should be templated on this platform. if ($#platforms < 0 || grep { $_ eq $^O } @platforms) { @@ -401,11 +397,11 @@ sub parse_templates($$$) { # Write the template file. print_format "Writing <|GREEN $target|> ...\n"; - open(TARGET, '>', $target) or print_error "unable to write $target: $!"; + open(my $fh, '>', $target) or print_error "unable to write $target: $!"; foreach (@final_lines) { - say TARGET $_; + say $fh $_; } - close(TARGET); + close $fh; # Set file permissions. if (defined $mode) { diff --git a/make/directive.pm b/make/directive.pm index 4501fc5ec..2e9e7ed61 100644 --- a/make/directive.pm +++ b/make/directive.pm @@ -41,16 +41,16 @@ our @EXPORT = qw(get_directive sub get_directive($$;$) { my ($file, $property, $default) = @_; - open(MODULE, $file) or return $default; + open(my $fh, $file) or return $default; my $value = ''; - while (<MODULE>) { + while (<$fh>) { if ($_ =~ /^\/\* \$(\S+): (.+) \*\/$/ || $_ =~ /^\/\/\/ \$(\S+): (.+)/) { next unless $1 eq $property; $value .= ' ' . execute_functions($file, $1, $2); } } - close(MODULE); + close $fh; # Strip all extraneous whitespace. $value =~ s/^\s+|\s+$//g; diff --git a/make/test/clock_gettime.cpp b/make/test/clock_gettime.cpp index 91d8cd412..d111d591f 100644 --- a/make/test/clock_gettime.cpp +++ b/make/test/clock_gettime.cpp @@ -1,6 +1,7 @@ /* * InspIRCd -- Internet Relay Chat Daemon * + * Copyright (C) 2013 Peter Powell <petpow@saberuk.com> * * This file is part of InspIRCd. InspIRCd is free software: you can * redistribute it and/or modify it under the terms of the GNU General Public diff --git a/make/test/compiler.cpp b/make/test/compiler.cpp index e2cbd9f64..f01423325 100644 --- a/make/test/compiler.cpp +++ b/make/test/compiler.cpp @@ -1,6 +1,8 @@ /* * InspIRCd -- Internet Relay Chat Daemon * + * Copyright (C) 2016 Attila Molnar <attilamolnar@hush.com> + * Copyright (C) 2014-2015 Peter Powell <petpow@saberuk.com> * * This file is part of InspIRCd. InspIRCd is free software: you can * redistribute it and/or modify it under the terms of the GNU General Public diff --git a/make/test/compiler_info.cpp b/make/test/compiler_info.cpp new file mode 100644 index 000000000..10b156fc8 --- /dev/null +++ b/make/test/compiler_info.cpp @@ -0,0 +1,41 @@ +/* + * InspIRCd -- Internet Relay Chat Daemon + * + * Copyright (C) 2017 Peter Powell <petpow@saberuk.com> + * + * This file is part of InspIRCd. InspIRCd is free software: you can + * redistribute it and/or modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + + +#include <iostream> + +#if defined __INTEL_COMPILER // Also defines __clang__ and __GNUC__ +# define INSPIRCD_COMPILER_NAME "Intel" +# define INSPIRCD_COMPILER_VERSION (__INTEL_COMPILER / 100) << '.' << (__INTEL_COMPILER % 100) +#elif defined __clang__ // Also defines __GNUC__ +# if defined __apple_build_version__ +# define INSPIRCD_COMPILER_NAME "AppleClang" +# else +# define INSPIRCD_COMPILER_NAME "Clang" +# endif +# define INSPIRCD_COMPILER_VERSION __clang_major__ << '.' << __clang_minor__ +#elif defined __GNUC__ +# define INSPIRCD_COMPILER_NAME "GCC" +# define INSPIRCD_COMPILER_VERSION __GNUC__ << '.' << __GNUC_MINOR__ +#endif + +int main() { + std::cout << "NAME " << INSPIRCD_COMPILER_NAME << std::endl + << "VERSION " << INSPIRCD_COMPILER_VERSION << std::endl; + return 0; +} diff --git a/modulemanager b/modulemanager index d44ccbeb9..7471dcc77 100755 --- a/modulemanager +++ b/modulemanager @@ -254,7 +254,7 @@ sub resolve_deps { } command 'install', 'Install a third-party module', sub { - for my $mod (@ARGV) { + for my $mod (@_) { my $vers = $mod =~ s/=([-0-9.]+)// ? $1 : undef; $mod = lc $mod; unless ($modules{$mod}) { @@ -296,6 +296,7 @@ command 'list', 'List available third-party modules', sub { my $vers = join ' ', map { $_ eq $instver ? "\e[1m$_\e[m" : $_ } @vers; print "$mod ($vers) - $desc\n"; } + exit 0; }; execute_command @ARGV; diff --git a/src/coremods/core_dns.cpp b/src/coremods/core_dns.cpp index 753b41f43..7ee406a24 100644 --- a/src/coremods/core_dns.cpp +++ b/src/coremods/core_dns.cpp @@ -154,7 +154,7 @@ class Packet : public Query record.ttl = (input[pos] << 24) | (input[pos + 1] << 16) | (input[pos + 2] << 8) | input[pos + 3]; pos += 4; - //record.rdlength = input[pos] << 8 | input[pos + 1]; + uint16_t rdlength = input[pos] << 8 | input[pos + 1]; pos += 2; switch (record.type) @@ -200,6 +200,19 @@ class Packet : public Query break; } + case QUERY_TXT: + { + if (pos + rdlength > input_size) + throw Exception("Unable to unpack txt resource record"); + + record.rdata = std::string(reinterpret_cast<const char *>(input + pos), rdlength); + pos += rdlength; + + if (record.rdata.find_first_of("\r\n\0", 0, 3) != std::string::npos) + throw Exception("Invalid character in txt record"); + + break; + } default: break; } diff --git a/src/modules/m_md5.cpp b/src/modules/m_md5.cpp index 6cec05a18..26ff4cffc 100644 --- a/src/modules/m_md5.cpp +++ b/src/modules/m_md5.cpp @@ -61,23 +61,13 @@ class MD5Provider : public HashProvider } while (--words); } - void MD5Init(MD5Context *ctx, unsigned int* ikey = NULL) + void MD5Init(MD5Context *ctx) { /* These are the defaults for md5 */ - if (!ikey) - { - ctx->buf[0] = 0x67452301; - ctx->buf[1] = 0xefcdab89; - ctx->buf[2] = 0x98badcfe; - ctx->buf[3] = 0x10325476; - } - else - { - ctx->buf[0] = ikey[0]; - ctx->buf[1] = ikey[1]; - ctx->buf[2] = ikey[2]; - ctx->buf[3] = ikey[3]; - } + ctx->buf[0] = 0x67452301; + ctx->buf[1] = 0xefcdab89; + ctx->buf[2] = 0x98badcfe; + ctx->buf[3] = 0x10325476; ctx->bytes[0] = 0; ctx->bytes[1] = 0; @@ -236,10 +226,10 @@ class MD5Provider : public HashProvider } - void MyMD5(void *dest, void *orig, int len, unsigned int* ikey) + void MyMD5(void *dest, void *orig, int len) { MD5Context context; - MD5Init(&context, ikey); + MD5Init(&context); MD5Update(&context, (const unsigned char*)orig, len); MD5Final((unsigned char*)dest, &context); } @@ -248,7 +238,7 @@ class MD5Provider : public HashProvider std::string GenerateRaw(const std::string& data) { char res[16]; - MyMD5(res, (void*)data.data(), data.length(), NULL); + MyMD5(res, (void*)data.data(), data.length()); return std::string(res, 16); } diff --git a/src/modules/m_permchannels.cpp b/src/modules/m_permchannels.cpp index 9e77bd60e..d514e62a5 100644 --- a/src/modules/m_permchannels.cpp +++ b/src/modules/m_permchannels.cpp @@ -244,6 +244,10 @@ public: mode->OnModeChange(ServerInstance->FakeClient, ServerInstance->FakeClient, c, par, true); } } + + // We always apply the permchannels mode to permanent channels. + par.clear(); + p.OnModeChange(ServerInstance->FakeClient, ServerInstance->FakeClient, c, par, true); } } } diff --git a/src/socketengine.cpp b/src/socketengine.cpp index 4183488b7..3735e7530 100644 --- a/src/socketengine.cpp +++ b/src/socketengine.cpp @@ -203,40 +203,35 @@ void SocketEngine::SetReuse(int fd) int SocketEngine::RecvFrom(EventHandler* fd, void *buf, size_t len, int flags, sockaddr *from, socklen_t *fromlen) { int nbRecvd = recvfrom(fd->GetFd(), (char*)buf, len, flags, from, fromlen); - if (nbRecvd > 0) - stats.Update(nbRecvd, 0); + stats.UpdateReadCounters(nbRecvd); return nbRecvd; } int SocketEngine::Send(EventHandler* fd, const void *buf, size_t len, int flags) { int nbSent = send(fd->GetFd(), (const char*)buf, len, flags); - if (nbSent > 0) - stats.Update(0, nbSent); + stats.UpdateWriteCounters(nbSent); return nbSent; } int SocketEngine::Recv(EventHandler* fd, void *buf, size_t len, int flags) { int nbRecvd = recv(fd->GetFd(), (char*)buf, len, flags); - if (nbRecvd > 0) - stats.Update(nbRecvd, 0); + stats.UpdateReadCounters(nbRecvd); return nbRecvd; } int SocketEngine::SendTo(EventHandler* fd, const void *buf, size_t len, int flags, const sockaddr *to, socklen_t tolen) { int nbSent = sendto(fd->GetFd(), (const char*)buf, len, flags, to, tolen); - if (nbSent > 0) - stats.Update(0, nbSent); + stats.UpdateWriteCounters(nbSent); return nbSent; } int SocketEngine::WriteV(EventHandler* fd, const IOVector* iovec, int count) { int sent = writev(fd->GetFd(), iovec, count); - if (sent > 0) - stats.Update(0, sent); + stats.UpdateWriteCounters(sent); return sent; } @@ -289,11 +284,26 @@ int SocketEngine::Shutdown(int fd, int how) return shutdown(fd, how); } -void SocketEngine::Statistics::Update(size_t len_in, size_t len_out) +void SocketEngine::Statistics::UpdateReadCounters(int len_in) { CheckFlush(); - indata += len_in; - outdata += len_out; + + ReadEvents++; + if (len_in > 0) + indata += len_in; + else if (len_in < 0) + ErrorEvents++; +} + +void SocketEngine::Statistics::UpdateWriteCounters(int len_out) +{ + CheckFlush(); + + WriteEvents++; + if (len_out > 0) + outdata += len_out; + else if (len_out < 0) + ErrorEvents++; } void SocketEngine::Statistics::CheckFlush() const diff --git a/src/socketengines/socketengine_epoll.cpp b/src/socketengines/socketengine_epoll.cpp index 7602dd201..a935d786b 100644 --- a/src/socketengines/socketengine_epoll.cpp +++ b/src/socketengines/socketengine_epoll.cpp @@ -213,7 +213,6 @@ int SocketEngine::DispatchEvents() eh->SetEventMask(mask); if (ev.events & EPOLLIN) { - stats.ReadEvents++; eh->OnEventHandlerRead(); if (eh != GetRef(fd)) // whoa! we got deleted, better not give out the write event @@ -221,7 +220,6 @@ int SocketEngine::DispatchEvents() } if (ev.events & EPOLLOUT) { - stats.WriteEvents++; eh->OnEventHandlerWrite(); } } diff --git a/src/socketengines/socketengine_kqueue.cpp b/src/socketengines/socketengine_kqueue.cpp index 922cb7f2d..9db902314 100644 --- a/src/socketengines/socketengine_kqueue.cpp +++ b/src/socketengines/socketengine_kqueue.cpp @@ -199,7 +199,6 @@ int SocketEngine::DispatchEvents() } if (filter == EVFILT_WRITE) { - stats.WriteEvents++; /* When mask is FD_WANT_FAST_WRITE or FD_WANT_SINGLE_WRITE, * we set a one-shot write, so we need to clear that bit * to detect when it set again. @@ -210,7 +209,6 @@ int SocketEngine::DispatchEvents() } else if (filter == EVFILT_READ) { - stats.ReadEvents++; eh->SetEventMask(eh->GetEventMask() & ~FD_READ_WILL_BLOCK); eh->OnEventHandlerRead(); } diff --git a/src/socketengines/socketengine_ports.cpp b/src/socketengines/socketengine_ports.cpp index d94d02664..68fa70e3b 100644 --- a/src/socketengines/socketengine_ports.cpp +++ b/src/socketengines/socketengine_ports.cpp @@ -159,14 +159,12 @@ int SocketEngine::DispatchEvents() port_associate(EngineHandle, PORT_SOURCE_FD, fd, mask_to_events(mask), eh); if (portev_events & POLLRDNORM) { - stats.ReadEvents++; eh->OnEventHandlerRead(); if (eh != GetRef(fd)) continue; } if (portev_events & POLLWRNORM) { - stats.WriteEvents++; eh->OnEventHandlerWrite(); } } diff --git a/src/socketengines/socketengine_select.cpp b/src/socketengines/socketengine_select.cpp index 6dfbae88e..42f634db1 100644 --- a/src/socketengines/socketengine_select.cpp +++ b/src/socketengines/socketengine_select.cpp @@ -147,7 +147,6 @@ int SocketEngine::DispatchEvents() if (has_read) { - stats.ReadEvents++; ev->SetEventMask(ev->GetEventMask() & ~FD_READ_WILL_BLOCK); ev->OnEventHandlerRead(); if (ev != GetRef(i)) @@ -156,7 +155,6 @@ int SocketEngine::DispatchEvents() if (has_write) { - stats.WriteEvents++; int newmask = (ev->GetEventMask() & ~(FD_WRITE_WILL_BLOCK | FD_WANT_SINGLE_WRITE)); SocketEngine::OnSetEvent(ev, ev->GetEventMask(), newmask); ev->SetEventMask(newmask); |