mirror of
https://github.com/libevent/libevent.git
synced 2025-01-31 09:12:55 +08:00
C reserves all identifiers beginning with an underscore for system use. But we had been mangling our autoconf identifiers with the prefix "_EVENT_" to avoid conflict with other programs. Instead, we will now use the prefix "EVENT__". With any luck, the double-underscore will still hint "here be dragons" to anybody tempted to think that event-config.h is a stable api. This is an automatically generated patch. The script that produced it was made by running this script over config.h.in: ===== #!/usr/bin/perl -w # Run this on config.h.in use strict; my %macros = (); while (<>) { if (/^# *undef +([A-Za-z0-9_]+)/) { $macros{$1} = 1; } } print "#!/usr/bin/perl -w -i -p\n\n"; for my $k (sort keys %macros) { print "s/(?<![A-Za-z0-9_])_EVENT_$k(?![A-Za-z0-9_])/EVENT__$k/g;\n"; } == And the script that it generated was then run over all .c and .h files: #!/usr/bin/perl -w -i -p s/(?<![A-Za-z0-9_])_EVENT_DISABLE_DEBUG_MODE(?![A-Za-z0-9_])/EVENT__DISABLE_DEBUG_MODE/g; s/(?<![A-Za-z0-9_])_EVENT_DISABLE_MM_REPLACEMENT(?![A-Za-z0-9_])/EVENT__DISABLE_MM_REPLACEMENT/g; s/(?<![A-Za-z0-9_])_EVENT_DISABLE_THREAD_SUPPORT(?![A-Za-z0-9_])/EVENT__DISABLE_THREAD_SUPPORT/g; s/(?<![A-Za-z0-9_])_EVENT_HAVE_ACCEPT4(?![A-Za-z0-9_])/EVENT__HAVE_ACCEPT4/g; s/(?<![A-Za-z0-9_])_EVENT_HAVE_ARC4RANDOM(?![A-Za-z0-9_])/EVENT__HAVE_ARC4RANDOM/g; s/(?<![A-Za-z0-9_])_EVENT_HAVE_ARC4RANDOM_BUF(?![A-Za-z0-9_])/EVENT__HAVE_ARC4RANDOM_BUF/g; s/(?<![A-Za-z0-9_])_EVENT_HAVE_ARPA_INET_H(?![A-Za-z0-9_])/EVENT__HAVE_ARPA_INET_H/g; s/(?<![A-Za-z0-9_])_EVENT_HAVE_CLOCK_GETTIME(?![A-Za-z0-9_])/EVENT__HAVE_CLOCK_GETTIME/g; s/(?<![A-Za-z0-9_])_EVENT_HAVE_DECL_CTL_KERN(?![A-Za-z0-9_])/EVENT__HAVE_DECL_CTL_KERN/g; s/(?<![A-Za-z0-9_])_EVENT_HAVE_DECL_KERN_ARND(?![A-Za-z0-9_])/EVENT__HAVE_DECL_KERN_ARND/g; s/(?<![A-Za-z0-9_])_EVENT_HAVE_DECL_KERN_RANDOM(?![A-Za-z0-9_])/EVENT__HAVE_DECL_KERN_RANDOM/g; s/(?<![A-Za-z0-9_])_EVENT_HAVE_DECL_RANDOM_UUID(?![A-Za-z0-9_])/EVENT__HAVE_DECL_RANDOM_UUID/g; s/(?<![A-Za-z0-9_])_EVENT_HAVE_DEVPOLL(?![A-Za-z0-9_])/EVENT__HAVE_DEVPOLL/g; s/(?<![A-Za-z0-9_])_EVENT_HAVE_DLFCN_H(?![A-Za-z0-9_])/EVENT__HAVE_DLFCN_H/g; s/(?<![A-Za-z0-9_])_EVENT_HAVE_EPOLL(?![A-Za-z0-9_])/EVENT__HAVE_EPOLL/g; s/(?<![A-Za-z0-9_])_EVENT_HAVE_EPOLL_CREATE1(?![A-Za-z0-9_])/EVENT__HAVE_EPOLL_CREATE1/g; s/(?<![A-Za-z0-9_])_EVENT_HAVE_EPOLL_CTL(?![A-Za-z0-9_])/EVENT__HAVE_EPOLL_CTL/g; s/(?<![A-Za-z0-9_])_EVENT_HAVE_EVENTFD(?![A-Za-z0-9_])/EVENT__HAVE_EVENTFD/g; s/(?<![A-Za-z0-9_])_EVENT_HAVE_EVENT_PORTS(?![A-Za-z0-9_])/EVENT__HAVE_EVENT_PORTS/g; s/(?<![A-Za-z0-9_])_EVENT_HAVE_FCNTL(?![A-Za-z0-9_])/EVENT__HAVE_FCNTL/g; s/(?<![A-Za-z0-9_])_EVENT_HAVE_FCNTL_H(?![A-Za-z0-9_])/EVENT__HAVE_FCNTL_H/g; s/(?<![A-Za-z0-9_])_EVENT_HAVE_FD_MASK(?![A-Za-z0-9_])/EVENT__HAVE_FD_MASK/g; s/(?<![A-Za-z0-9_])_EVENT_HAVE_GETADDRINFO(?![A-Za-z0-9_])/EVENT__HAVE_GETADDRINFO/g; s/(?<![A-Za-z0-9_])_EVENT_HAVE_GETEGID(?![A-Za-z0-9_])/EVENT__HAVE_GETEGID/g; s/(?<![A-Za-z0-9_])_EVENT_HAVE_GETEUID(?![A-Za-z0-9_])/EVENT__HAVE_GETEUID/g; s/(?<![A-Za-z0-9_])_EVENT_HAVE_GETHOSTBYNAME_R(?![A-Za-z0-9_])/EVENT__HAVE_GETHOSTBYNAME_R/g; s/(?<![A-Za-z0-9_])_EVENT_HAVE_GETHOSTBYNAME_R_3_ARG(?![A-Za-z0-9_])/EVENT__HAVE_GETHOSTBYNAME_R_3_ARG/g; s/(?<![A-Za-z0-9_])_EVENT_HAVE_GETHOSTBYNAME_R_5_ARG(?![A-Za-z0-9_])/EVENT__HAVE_GETHOSTBYNAME_R_5_ARG/g; s/(?<![A-Za-z0-9_])_EVENT_HAVE_GETHOSTBYNAME_R_6_ARG(?![A-Za-z0-9_])/EVENT__HAVE_GETHOSTBYNAME_R_6_ARG/g; s/(?<![A-Za-z0-9_])_EVENT_HAVE_GETIFADDRS(?![A-Za-z0-9_])/EVENT__HAVE_GETIFADDRS/g; s/(?<![A-Za-z0-9_])_EVENT_HAVE_GETNAMEINFO(?![A-Za-z0-9_])/EVENT__HAVE_GETNAMEINFO/g; s/(?<![A-Za-z0-9_])_EVENT_HAVE_GETPROTOBYNUMBER(?![A-Za-z0-9_])/EVENT__HAVE_GETPROTOBYNUMBER/g; s/(?<![A-Za-z0-9_])_EVENT_HAVE_GETSERVBYNAME(?![A-Za-z0-9_])/EVENT__HAVE_GETSERVBYNAME/g; s/(?<![A-Za-z0-9_])_EVENT_HAVE_GETTIMEOFDAY(?![A-Za-z0-9_])/EVENT__HAVE_GETTIMEOFDAY/g; s/(?<![A-Za-z0-9_])_EVENT_HAVE_IFADDRS_H(?![A-Za-z0-9_])/EVENT__HAVE_IFADDRS_H/g; s/(?<![A-Za-z0-9_])_EVENT_HAVE_INET_ATON(?![A-Za-z0-9_])/EVENT__HAVE_INET_ATON/g; s/(?<![A-Za-z0-9_])_EVENT_HAVE_INET_NTOP(?![A-Za-z0-9_])/EVENT__HAVE_INET_NTOP/g; s/(?<![A-Za-z0-9_])_EVENT_HAVE_INET_PTON(?![A-Za-z0-9_])/EVENT__HAVE_INET_PTON/g; s/(?<![A-Za-z0-9_])_EVENT_HAVE_INTTYPES_H(?![A-Za-z0-9_])/EVENT__HAVE_INTTYPES_H/g; s/(?<![A-Za-z0-9_])_EVENT_HAVE_ISSETUGID(?![A-Za-z0-9_])/EVENT__HAVE_ISSETUGID/g; s/(?<![A-Za-z0-9_])_EVENT_HAVE_KQUEUE(?![A-Za-z0-9_])/EVENT__HAVE_KQUEUE/g; s/(?<![A-Za-z0-9_])_EVENT_HAVE_LIBZ(?![A-Za-z0-9_])/EVENT__HAVE_LIBZ/g; s/(?<![A-Za-z0-9_])_EVENT_HAVE_MEMORY_H(?![A-Za-z0-9_])/EVENT__HAVE_MEMORY_H/g; s/(?<![A-Za-z0-9_])_EVENT_HAVE_MMAP(?![A-Za-z0-9_])/EVENT__HAVE_MMAP/g; s/(?<![A-Za-z0-9_])_EVENT_HAVE_NANOSLEEP(?![A-Za-z0-9_])/EVENT__HAVE_NANOSLEEP/g; s/(?<![A-Za-z0-9_])_EVENT_HAVE_NETDB_H(?![A-Za-z0-9_])/EVENT__HAVE_NETDB_H/g; s/(?<![A-Za-z0-9_])_EVENT_HAVE_NETINET_IN6_H(?![A-Za-z0-9_])/EVENT__HAVE_NETINET_IN6_H/g; s/(?<![A-Za-z0-9_])_EVENT_HAVE_NETINET_IN_H(?![A-Za-z0-9_])/EVENT__HAVE_NETINET_IN_H/g; s/(?<![A-Za-z0-9_])_EVENT_HAVE_NETINET_TCP_H(?![A-Za-z0-9_])/EVENT__HAVE_NETINET_TCP_H/g; s/(?<![A-Za-z0-9_])_EVENT_HAVE_OPENSSL(?![A-Za-z0-9_])/EVENT__HAVE_OPENSSL/g; s/(?<![A-Za-z0-9_])_EVENT_HAVE_PIPE(?![A-Za-z0-9_])/EVENT__HAVE_PIPE/g; s/(?<![A-Za-z0-9_])_EVENT_HAVE_PIPE2(?![A-Za-z0-9_])/EVENT__HAVE_PIPE2/g; s/(?<![A-Za-z0-9_])_EVENT_HAVE_POLL(?![A-Za-z0-9_])/EVENT__HAVE_POLL/g; s/(?<![A-Za-z0-9_])_EVENT_HAVE_POLL_H(?![A-Za-z0-9_])/EVENT__HAVE_POLL_H/g; s/(?<![A-Za-z0-9_])_EVENT_HAVE_PORT_CREATE(?![A-Za-z0-9_])/EVENT__HAVE_PORT_CREATE/g; s/(?<![A-Za-z0-9_])_EVENT_HAVE_PORT_H(?![A-Za-z0-9_])/EVENT__HAVE_PORT_H/g; s/(?<![A-Za-z0-9_])_EVENT_HAVE_PTHREAD(?![A-Za-z0-9_])/EVENT__HAVE_PTHREAD/g; s/(?<![A-Za-z0-9_])_EVENT_HAVE_PTHREADS(?![A-Za-z0-9_])/EVENT__HAVE_PTHREADS/g; s/(?<![A-Za-z0-9_])_EVENT_HAVE_PUTENV(?![A-Za-z0-9_])/EVENT__HAVE_PUTENV/g; s/(?<![A-Za-z0-9_])_EVENT_HAVE_SA_FAMILY_T(?![A-Za-z0-9_])/EVENT__HAVE_SA_FAMILY_T/g; s/(?<![A-Za-z0-9_])_EVENT_HAVE_SELECT(?![A-Za-z0-9_])/EVENT__HAVE_SELECT/g; s/(?<![A-Za-z0-9_])_EVENT_HAVE_SENDFILE(?![A-Za-z0-9_])/EVENT__HAVE_SENDFILE/g; s/(?<![A-Za-z0-9_])_EVENT_HAVE_SETENV(?![A-Za-z0-9_])/EVENT__HAVE_SETENV/g; s/(?<![A-Za-z0-9_])_EVENT_HAVE_SETFD(?![A-Za-z0-9_])/EVENT__HAVE_SETFD/g; s/(?<![A-Za-z0-9_])_EVENT_HAVE_SETRLIMIT(?![A-Za-z0-9_])/EVENT__HAVE_SETRLIMIT/g; s/(?<![A-Za-z0-9_])_EVENT_HAVE_SIGACTION(?![A-Za-z0-9_])/EVENT__HAVE_SIGACTION/g; s/(?<![A-Za-z0-9_])_EVENT_HAVE_SIGNAL(?![A-Za-z0-9_])/EVENT__HAVE_SIGNAL/g; s/(?<![A-Za-z0-9_])_EVENT_HAVE_SPLICE(?![A-Za-z0-9_])/EVENT__HAVE_SPLICE/g; s/(?<![A-Za-z0-9_])_EVENT_HAVE_STDARG_H(?![A-Za-z0-9_])/EVENT__HAVE_STDARG_H/g; s/(?<![A-Za-z0-9_])_EVENT_HAVE_STDDEF_H(?![A-Za-z0-9_])/EVENT__HAVE_STDDEF_H/g; s/(?<![A-Za-z0-9_])_EVENT_HAVE_STDINT_H(?![A-Za-z0-9_])/EVENT__HAVE_STDINT_H/g; s/(?<![A-Za-z0-9_])_EVENT_HAVE_STDLIB_H(?![A-Za-z0-9_])/EVENT__HAVE_STDLIB_H/g; s/(?<![A-Za-z0-9_])_EVENT_HAVE_STRINGS_H(?![A-Za-z0-9_])/EVENT__HAVE_STRINGS_H/g; s/(?<![A-Za-z0-9_])_EVENT_HAVE_STRING_H(?![A-Za-z0-9_])/EVENT__HAVE_STRING_H/g; s/(?<![A-Za-z0-9_])_EVENT_HAVE_STRLCPY(?![A-Za-z0-9_])/EVENT__HAVE_STRLCPY/g; s/(?<![A-Za-z0-9_])_EVENT_HAVE_STRSEP(?![A-Za-z0-9_])/EVENT__HAVE_STRSEP/g; s/(?<![A-Za-z0-9_])_EVENT_HAVE_STRTOK_R(?![A-Za-z0-9_])/EVENT__HAVE_STRTOK_R/g; s/(?<![A-Za-z0-9_])_EVENT_HAVE_STRTOLL(?![A-Za-z0-9_])/EVENT__HAVE_STRTOLL/g; s/(?<![A-Za-z0-9_])_EVENT_HAVE_STRUCT_ADDRINFO(?![A-Za-z0-9_])/EVENT__HAVE_STRUCT_ADDRINFO/g; s/(?<![A-Za-z0-9_])_EVENT_HAVE_STRUCT_IN6_ADDR(?![A-Za-z0-9_])/EVENT__HAVE_STRUCT_IN6_ADDR/g; s/(?<![A-Za-z0-9_])_EVENT_HAVE_STRUCT_IN6_ADDR_S6_ADDR16(?![A-Za-z0-9_])/EVENT__HAVE_STRUCT_IN6_ADDR_S6_ADDR16/g; s/(?<![A-Za-z0-9_])_EVENT_HAVE_STRUCT_IN6_ADDR_S6_ADDR32(?![A-Za-z0-9_])/EVENT__HAVE_STRUCT_IN6_ADDR_S6_ADDR32/g; s/(?<![A-Za-z0-9_])_EVENT_HAVE_STRUCT_SOCKADDR_IN6(?![A-Za-z0-9_])/EVENT__HAVE_STRUCT_SOCKADDR_IN6/g; s/(?<![A-Za-z0-9_])_EVENT_HAVE_STRUCT_SOCKADDR_IN6_SIN6_LEN(?![A-Za-z0-9_])/EVENT__HAVE_STRUCT_SOCKADDR_IN6_SIN6_LEN/g; s/(?<![A-Za-z0-9_])_EVENT_HAVE_STRUCT_SOCKADDR_IN_SIN_LEN(?![A-Za-z0-9_])/EVENT__HAVE_STRUCT_SOCKADDR_IN_SIN_LEN/g; s/(?<![A-Za-z0-9_])_EVENT_HAVE_STRUCT_SOCKADDR_STORAGE(?![A-Za-z0-9_])/EVENT__HAVE_STRUCT_SOCKADDR_STORAGE/g; s/(?<![A-Za-z0-9_])_EVENT_HAVE_STRUCT_SOCKADDR_STORAGE_SS_FAMILY(?![A-Za-z0-9_])/EVENT__HAVE_STRUCT_SOCKADDR_STORAGE_SS_FAMILY/g; s/(?<![A-Za-z0-9_])_EVENT_HAVE_STRUCT_SOCKADDR_STORAGE___SS_FAMILY(?![A-Za-z0-9_])/EVENT__HAVE_STRUCT_SOCKADDR_STORAGE___SS_FAMILY/g; s/(?<![A-Za-z0-9_])_EVENT_HAVE_SYSCTL(?![A-Za-z0-9_])/EVENT__HAVE_SYSCTL/g; s/(?<![A-Za-z0-9_])_EVENT_HAVE_SYS_DEVPOLL_H(?![A-Za-z0-9_])/EVENT__HAVE_SYS_DEVPOLL_H/g; s/(?<![A-Za-z0-9_])_EVENT_HAVE_SYS_EPOLL_H(?![A-Za-z0-9_])/EVENT__HAVE_SYS_EPOLL_H/g; s/(?<![A-Za-z0-9_])_EVENT_HAVE_SYS_EVENTFD_H(?![A-Za-z0-9_])/EVENT__HAVE_SYS_EVENTFD_H/g; s/(?<![A-Za-z0-9_])_EVENT_HAVE_SYS_EVENT_H(?![A-Za-z0-9_])/EVENT__HAVE_SYS_EVENT_H/g; s/(?<![A-Za-z0-9_])_EVENT_HAVE_SYS_IOCTL_H(?![A-Za-z0-9_])/EVENT__HAVE_SYS_IOCTL_H/g; s/(?<![A-Za-z0-9_])_EVENT_HAVE_SYS_MMAN_H(?![A-Za-z0-9_])/EVENT__HAVE_SYS_MMAN_H/g; s/(?<![A-Za-z0-9_])_EVENT_HAVE_SYS_PARAM_H(?![A-Za-z0-9_])/EVENT__HAVE_SYS_PARAM_H/g; s/(?<![A-Za-z0-9_])_EVENT_HAVE_SYS_QUEUE_H(?![A-Za-z0-9_])/EVENT__HAVE_SYS_QUEUE_H/g; s/(?<![A-Za-z0-9_])_EVENT_HAVE_SYS_RESOURCE_H(?![A-Za-z0-9_])/EVENT__HAVE_SYS_RESOURCE_H/g; s/(?<![A-Za-z0-9_])_EVENT_HAVE_SYS_SELECT_H(?![A-Za-z0-9_])/EVENT__HAVE_SYS_SELECT_H/g; s/(?<![A-Za-z0-9_])_EVENT_HAVE_SYS_SENDFILE_H(?![A-Za-z0-9_])/EVENT__HAVE_SYS_SENDFILE_H/g; s/(?<![A-Za-z0-9_])_EVENT_HAVE_SYS_SOCKET_H(?![A-Za-z0-9_])/EVENT__HAVE_SYS_SOCKET_H/g; s/(?<![A-Za-z0-9_])_EVENT_HAVE_SYS_STAT_H(?![A-Za-z0-9_])/EVENT__HAVE_SYS_STAT_H/g; s/(?<![A-Za-z0-9_])_EVENT_HAVE_SYS_SYSCTL_H(?![A-Za-z0-9_])/EVENT__HAVE_SYS_SYSCTL_H/g; s/(?<![A-Za-z0-9_])_EVENT_HAVE_SYS_TIME_H(?![A-Za-z0-9_])/EVENT__HAVE_SYS_TIME_H/g; s/(?<![A-Za-z0-9_])_EVENT_HAVE_SYS_TYPES_H(?![A-Za-z0-9_])/EVENT__HAVE_SYS_TYPES_H/g; s/(?<![A-Za-z0-9_])_EVENT_HAVE_SYS_UIO_H(?![A-Za-z0-9_])/EVENT__HAVE_SYS_UIO_H/g; s/(?<![A-Za-z0-9_])_EVENT_HAVE_SYS_WAIT_H(?![A-Za-z0-9_])/EVENT__HAVE_SYS_WAIT_H/g; s/(?<![A-Za-z0-9_])_EVENT_HAVE_TAILQFOREACH(?![A-Za-z0-9_])/EVENT__HAVE_TAILQFOREACH/g; s/(?<![A-Za-z0-9_])_EVENT_HAVE_TIMERADD(?![A-Za-z0-9_])/EVENT__HAVE_TIMERADD/g; s/(?<![A-Za-z0-9_])_EVENT_HAVE_TIMERCLEAR(?![A-Za-z0-9_])/EVENT__HAVE_TIMERCLEAR/g; s/(?<![A-Za-z0-9_])_EVENT_HAVE_TIMERCMP(?![A-Za-z0-9_])/EVENT__HAVE_TIMERCMP/g; s/(?<![A-Za-z0-9_])_EVENT_HAVE_TIMERISSET(?![A-Za-z0-9_])/EVENT__HAVE_TIMERISSET/g; s/(?<![A-Za-z0-9_])_EVENT_HAVE_UINT16_T(?![A-Za-z0-9_])/EVENT__HAVE_UINT16_T/g; s/(?<![A-Za-z0-9_])_EVENT_HAVE_UINT32_T(?![A-Za-z0-9_])/EVENT__HAVE_UINT32_T/g; s/(?<![A-Za-z0-9_])_EVENT_HAVE_UINT64_T(?![A-Za-z0-9_])/EVENT__HAVE_UINT64_T/g; s/(?<![A-Za-z0-9_])_EVENT_HAVE_UINT8_T(?![A-Za-z0-9_])/EVENT__HAVE_UINT8_T/g; s/(?<![A-Za-z0-9_])_EVENT_HAVE_UINTPTR_T(?![A-Za-z0-9_])/EVENT__HAVE_UINTPTR_T/g; s/(?<![A-Za-z0-9_])_EVENT_HAVE_UNISTD_H(?![A-Za-z0-9_])/EVENT__HAVE_UNISTD_H/g; s/(?<![A-Za-z0-9_])_EVENT_HAVE_UNSETENV(?![A-Za-z0-9_])/EVENT__HAVE_UNSETENV/g; s/(?<![A-Za-z0-9_])_EVENT_HAVE_USLEEP(?![A-Za-z0-9_])/EVENT__HAVE_USLEEP/g; s/(?<![A-Za-z0-9_])_EVENT_HAVE_VASPRINTF(?![A-Za-z0-9_])/EVENT__HAVE_VASPRINTF/g; s/(?<![A-Za-z0-9_])_EVENT_HAVE_WORKING_KQUEUE(?![A-Za-z0-9_])/EVENT__HAVE_WORKING_KQUEUE/g; s/(?<![A-Za-z0-9_])_EVENT_HAVE_ZLIB_H(?![A-Za-z0-9_])/EVENT__HAVE_ZLIB_H/g; s/(?<![A-Za-z0-9_])_EVENT_LT_OBJDIR(?![A-Za-z0-9_])/EVENT__LT_OBJDIR/g; s/(?<![A-Za-z0-9_])_EVENT_NO_MINUS_C_MINUS_O(?![A-Za-z0-9_])/EVENT__NO_MINUS_C_MINUS_O/g; s/(?<![A-Za-z0-9_])_EVENT_NUMERIC_VERSION(?![A-Za-z0-9_])/EVENT__NUMERIC_VERSION/g; s/(?<![A-Za-z0-9_])_EVENT_PACKAGE(?![A-Za-z0-9_])/EVENT__PACKAGE/g; s/(?<![A-Za-z0-9_])_EVENT_PACKAGE_BUGREPORT(?![A-Za-z0-9_])/EVENT__PACKAGE_BUGREPORT/g; s/(?<![A-Za-z0-9_])_EVENT_PACKAGE_NAME(?![A-Za-z0-9_])/EVENT__PACKAGE_NAME/g; s/(?<![A-Za-z0-9_])_EVENT_PACKAGE_STRING(?![A-Za-z0-9_])/EVENT__PACKAGE_STRING/g; s/(?<![A-Za-z0-9_])_EVENT_PACKAGE_TARNAME(?![A-Za-z0-9_])/EVENT__PACKAGE_TARNAME/g; s/(?<![A-Za-z0-9_])_EVENT_PACKAGE_URL(?![A-Za-z0-9_])/EVENT__PACKAGE_URL/g; s/(?<![A-Za-z0-9_])_EVENT_PACKAGE_VERSION(?![A-Za-z0-9_])/EVENT__PACKAGE_VERSION/g; s/(?<![A-Za-z0-9_])_EVENT_PTHREAD_CREATE_JOINABLE(?![A-Za-z0-9_])/EVENT__PTHREAD_CREATE_JOINABLE/g; s/(?<![A-Za-z0-9_])_EVENT_SIZEOF_INT(?![A-Za-z0-9_])/EVENT__SIZEOF_INT/g; s/(?<![A-Za-z0-9_])_EVENT_SIZEOF_LONG(?![A-Za-z0-9_])/EVENT__SIZEOF_LONG/g; s/(?<![A-Za-z0-9_])_EVENT_SIZEOF_LONG_LONG(?![A-Za-z0-9_])/EVENT__SIZEOF_LONG_LONG/g; s/(?<![A-Za-z0-9_])_EVENT_SIZEOF_OFF_T(?![A-Za-z0-9_])/EVENT__SIZEOF_OFF_T/g; s/(?<![A-Za-z0-9_])_EVENT_SIZEOF_PTHREAD_T(?![A-Za-z0-9_])/EVENT__SIZEOF_PTHREAD_T/g; s/(?<![A-Za-z0-9_])_EVENT_SIZEOF_SHORT(?![A-Za-z0-9_])/EVENT__SIZEOF_SHORT/g; s/(?<![A-Za-z0-9_])_EVENT_SIZEOF_SIZE_T(?![A-Za-z0-9_])/EVENT__SIZEOF_SIZE_T/g; s/(?<![A-Za-z0-9_])_EVENT_SIZEOF_VOID_P(?![A-Za-z0-9_])/EVENT__SIZEOF_VOID_P/g; s/(?<![A-Za-z0-9_])_EVENT_STDC_HEADERS(?![A-Za-z0-9_])/EVENT__STDC_HEADERS/g; s/(?<![A-Za-z0-9_])_EVENT_TIME_WITH_SYS_TIME(?![A-Za-z0-9_])/EVENT__TIME_WITH_SYS_TIME/g; s/(?<![A-Za-z0-9_])_EVENT_VERSION(?![A-Za-z0-9_])/EVENT__VERSION/g; s/(?<![A-Za-z0-9_])_EVENT__ALL_SOURCE(?![A-Za-z0-9_])/EVENT___ALL_SOURCE/g; s/(?<![A-Za-z0-9_])_EVENT__FILE_OFFSET_BITS(?![A-Za-z0-9_])/EVENT___FILE_OFFSET_BITS/g; s/(?<![A-Za-z0-9_])_EVENT__GNU_SOURCE(?![A-Za-z0-9_])/EVENT___GNU_SOURCE/g; s/(?<![A-Za-z0-9_])_EVENT__LARGE_FILES(?![A-Za-z0-9_])/EVENT___LARGE_FILES/g; s/(?<![A-Za-z0-9_])_EVENT__MINIX(?![A-Za-z0-9_])/EVENT___MINIX/g; s/(?<![A-Za-z0-9_])_EVENT__POSIX_1_SOURCE(?![A-Za-z0-9_])/EVENT___POSIX_1_SOURCE/g; s/(?<![A-Za-z0-9_])_EVENT__POSIX_PTHREAD_SEMANTICS(?![A-Za-z0-9_])/EVENT___POSIX_PTHREAD_SEMANTICS/g; s/(?<![A-Za-z0-9_])_EVENT__POSIX_SOURCE(?![A-Za-z0-9_])/EVENT___POSIX_SOURCE/g; s/(?<![A-Za-z0-9_])_EVENT__TANDEM_SOURCE(?![A-Za-z0-9_])/EVENT___TANDEM_SOURCE/g; s/(?<![A-Za-z0-9_])_EVENT___EXTENSIONS__(?![A-Za-z0-9_])/EVENT____EXTENSIONS__/g; s/(?<![A-Za-z0-9_])_EVENT___func__(?![A-Za-z0-9_])/EVENT____func__/g; s/(?<![A-Za-z0-9_])_EVENT_const(?![A-Za-z0-9_])/EVENT__const/g; s/(?<![A-Za-z0-9_])_EVENT_inline(?![A-Za-z0-9_])/EVENT__inline/g; s/(?<![A-Za-z0-9_])_EVENT_pid_t(?![A-Za-z0-9_])/EVENT__pid_t/g; s/(?<![A-Za-z0-9_])_EVENT_size_t(?![A-Za-z0-9_])/EVENT__size_t/g; s/(?<![A-Za-z0-9_])_EVENT_socklen_t(?![A-Za-z0-9_])/EVENT__socklen_t/g; s/(?<![A-Za-z0-9_])_EVENT_ssize_t(?![A-Za-z0-9_])/EVENT__ssize_t/g;
874 lines
20 KiB
C
874 lines
20 KiB
C
/*
|
|
* Copyright (c) 2009-2012 Niels Provos, Nick Mathewson
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions
|
|
* are met:
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
* documentation and/or other materials provided with the distribution.
|
|
* 3. The name of the author may not be used to endorse or promote products
|
|
* derived from this software without specific prior written permission.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
|
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
|
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
|
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
|
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
|
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
*/
|
|
|
|
#include "event2/event-config.h"
|
|
#include "evconfig-private.h"
|
|
|
|
#include <sys/types.h>
|
|
|
|
#ifdef _WIN32
|
|
#ifndef _WIN32_WINNT
|
|
/* Minimum required for InitializeCriticalSectionAndSpinCount */
|
|
#define _WIN32_WINNT 0x0403
|
|
#endif
|
|
#include <winsock2.h>
|
|
#include <ws2tcpip.h>
|
|
#include <mswsock.h>
|
|
#endif
|
|
#include <errno.h>
|
|
#ifdef EVENT__HAVE_SYS_SOCKET_H
|
|
#include <sys/socket.h>
|
|
#endif
|
|
#ifdef EVENT__HAVE_FCNTL_H
|
|
#include <fcntl.h>
|
|
#endif
|
|
#ifdef EVENT__HAVE_UNISTD_H
|
|
#include <unistd.h>
|
|
#endif
|
|
|
|
#include "event2/listener.h"
|
|
#include "event2/util.h"
|
|
#include "event2/event.h"
|
|
#include "event2/event_struct.h"
|
|
#include "mm-internal.h"
|
|
#include "util-internal.h"
|
|
#include "log-internal.h"
|
|
#include "evthread-internal.h"
|
|
#ifdef _WIN32
|
|
#include "iocp-internal.h"
|
|
#include "defer-internal.h"
|
|
#include "event-internal.h"
|
|
#endif
|
|
|
|
struct evconnlistener_ops {
|
|
int (*enable)(struct evconnlistener *);
|
|
int (*disable)(struct evconnlistener *);
|
|
void (*destroy)(struct evconnlistener *);
|
|
void (*shutdown)(struct evconnlistener *);
|
|
evutil_socket_t (*getfd)(struct evconnlistener *);
|
|
struct event_base *(*getbase)(struct evconnlistener *);
|
|
};
|
|
|
|
struct evconnlistener {
|
|
const struct evconnlistener_ops *ops;
|
|
void *lock;
|
|
evconnlistener_cb cb;
|
|
evconnlistener_errorcb errorcb;
|
|
void *user_data;
|
|
unsigned flags;
|
|
short refcnt;
|
|
int accept4_flags;
|
|
unsigned enabled : 1;
|
|
};
|
|
|
|
struct evconnlistener_event {
|
|
struct evconnlistener base;
|
|
struct event listener;
|
|
};
|
|
|
|
#ifdef _WIN32
|
|
struct evconnlistener_iocp {
|
|
struct evconnlistener base;
|
|
evutil_socket_t fd;
|
|
struct event_base *event_base;
|
|
struct event_iocp_port *port;
|
|
short n_accepting;
|
|
unsigned shutting_down : 1;
|
|
unsigned event_added : 1;
|
|
struct accepting_socket **accepting;
|
|
};
|
|
#endif
|
|
|
|
#define LOCK(listener) EVLOCK_LOCK((listener)->lock, 0)
|
|
#define UNLOCK(listener) EVLOCK_UNLOCK((listener)->lock, 0)
|
|
|
|
struct evconnlistener *
|
|
evconnlistener_new_async(struct event_base *base,
|
|
evconnlistener_cb cb, void *ptr, unsigned flags, int backlog,
|
|
evutil_socket_t fd); /* XXXX export this? */
|
|
|
|
static int event_listener_enable(struct evconnlistener *);
|
|
static int event_listener_disable(struct evconnlistener *);
|
|
static void event_listener_destroy(struct evconnlistener *);
|
|
static evutil_socket_t event_listener_getfd(struct evconnlistener *);
|
|
static struct event_base *event_listener_getbase(struct evconnlistener *);
|
|
|
|
#if 0
|
|
static void
|
|
listener_incref_and_lock(struct evconnlistener *listener)
|
|
{
|
|
LOCK(listener);
|
|
++listener->refcnt;
|
|
}
|
|
#endif
|
|
|
|
static int
|
|
listener_decref_and_unlock(struct evconnlistener *listener)
|
|
{
|
|
int refcnt = --listener->refcnt;
|
|
if (refcnt == 0) {
|
|
listener->ops->destroy(listener);
|
|
UNLOCK(listener);
|
|
EVTHREAD_FREE_LOCK(listener->lock, EVTHREAD_LOCKTYPE_RECURSIVE);
|
|
mm_free(listener);
|
|
return 1;
|
|
} else {
|
|
UNLOCK(listener);
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
static const struct evconnlistener_ops evconnlistener_event_ops = {
|
|
event_listener_enable,
|
|
event_listener_disable,
|
|
event_listener_destroy,
|
|
NULL, /* shutdown */
|
|
event_listener_getfd,
|
|
event_listener_getbase
|
|
};
|
|
|
|
static void listener_read_cb(evutil_socket_t, short, void *);
|
|
|
|
struct evconnlistener *
|
|
evconnlistener_new(struct event_base *base,
|
|
evconnlistener_cb cb, void *ptr, unsigned flags, int backlog,
|
|
evutil_socket_t fd)
|
|
{
|
|
struct evconnlistener_event *lev;
|
|
|
|
#ifdef _WIN32
|
|
if (base && event_base_get_iocp(base)) {
|
|
const struct win32_extension_fns *ext =
|
|
event_get_win32_extension_fns();
|
|
if (ext->AcceptEx && ext->GetAcceptExSockaddrs)
|
|
return evconnlistener_new_async(base, cb, ptr, flags,
|
|
backlog, fd);
|
|
}
|
|
#endif
|
|
|
|
if (backlog > 0) {
|
|
if (listen(fd, backlog) < 0)
|
|
return NULL;
|
|
} else if (backlog < 0) {
|
|
if (listen(fd, 128) < 0)
|
|
return NULL;
|
|
}
|
|
|
|
lev = mm_calloc(1, sizeof(struct evconnlistener_event));
|
|
if (!lev)
|
|
return NULL;
|
|
|
|
lev->base.ops = &evconnlistener_event_ops;
|
|
lev->base.cb = cb;
|
|
lev->base.user_data = ptr;
|
|
lev->base.flags = flags;
|
|
lev->base.refcnt = 1;
|
|
|
|
lev->base.accept4_flags = 0;
|
|
if (!(flags & LEV_OPT_LEAVE_SOCKETS_BLOCKING))
|
|
lev->base.accept4_flags |= EVUTIL_SOCK_NONBLOCK;
|
|
if (flags & LEV_OPT_CLOSE_ON_EXEC)
|
|
lev->base.accept4_flags |= EVUTIL_SOCK_CLOEXEC;
|
|
|
|
if (flags & LEV_OPT_THREADSAFE) {
|
|
EVTHREAD_ALLOC_LOCK(lev->base.lock, EVTHREAD_LOCKTYPE_RECURSIVE);
|
|
}
|
|
|
|
event_assign(&lev->listener, base, fd, EV_READ|EV_PERSIST,
|
|
listener_read_cb, lev);
|
|
|
|
if (!(flags & LEV_OPT_DISABLED))
|
|
evconnlistener_enable(&lev->base);
|
|
|
|
return &lev->base;
|
|
}
|
|
|
|
struct evconnlistener *
|
|
evconnlistener_new_bind(struct event_base *base, evconnlistener_cb cb,
|
|
void *ptr, unsigned flags, int backlog, const struct sockaddr *sa,
|
|
int socklen)
|
|
{
|
|
struct evconnlistener *listener;
|
|
evutil_socket_t fd;
|
|
int on = 1;
|
|
int family = sa ? sa->sa_family : AF_UNSPEC;
|
|
int socktype = SOCK_STREAM | EVUTIL_SOCK_NONBLOCK;
|
|
|
|
if (backlog == 0)
|
|
return NULL;
|
|
|
|
if (flags & LEV_OPT_CLOSE_ON_EXEC)
|
|
socktype |= EVUTIL_SOCK_CLOEXEC;
|
|
|
|
fd = evutil_socket(family, socktype, 0);
|
|
if (fd == -1)
|
|
return NULL;
|
|
|
|
setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (void*)&on, sizeof(on));
|
|
if (flags & LEV_OPT_REUSEABLE) {
|
|
evutil_make_listen_socket_reuseable(fd);
|
|
}
|
|
|
|
if (flags & LEV_OPT_DEFERRED_ACCEPT) {
|
|
evutil_make_tcp_listen_socket_deferred(fd);
|
|
}
|
|
|
|
if (sa) {
|
|
if (bind(fd, sa, socklen)<0) {
|
|
evutil_closesocket(fd);
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
listener = evconnlistener_new(base, cb, ptr, flags, backlog, fd);
|
|
if (!listener) {
|
|
evutil_closesocket(fd);
|
|
return NULL;
|
|
}
|
|
|
|
return listener;
|
|
}
|
|
|
|
void
|
|
evconnlistener_free(struct evconnlistener *lev)
|
|
{
|
|
LOCK(lev);
|
|
lev->cb = NULL;
|
|
lev->errorcb = NULL;
|
|
if (lev->ops->shutdown)
|
|
lev->ops->shutdown(lev);
|
|
listener_decref_and_unlock(lev);
|
|
}
|
|
|
|
static void
|
|
event_listener_destroy(struct evconnlistener *lev)
|
|
{
|
|
struct evconnlistener_event *lev_e =
|
|
EVUTIL_UPCAST(lev, struct evconnlistener_event, base);
|
|
|
|
event_del(&lev_e->listener);
|
|
if (lev->flags & LEV_OPT_CLOSE_ON_FREE)
|
|
evutil_closesocket(event_get_fd(&lev_e->listener));
|
|
event_debug_unassign(&lev_e->listener);
|
|
}
|
|
|
|
int
|
|
evconnlistener_enable(struct evconnlistener *lev)
|
|
{
|
|
int r;
|
|
LOCK(lev);
|
|
lev->enabled = 1;
|
|
if (lev->cb)
|
|
r = lev->ops->enable(lev);
|
|
else
|
|
r = 0;
|
|
UNLOCK(lev);
|
|
return r;
|
|
}
|
|
|
|
int
|
|
evconnlistener_disable(struct evconnlistener *lev)
|
|
{
|
|
int r;
|
|
LOCK(lev);
|
|
lev->enabled = 0;
|
|
r = lev->ops->disable(lev);
|
|
UNLOCK(lev);
|
|
return r;
|
|
}
|
|
|
|
static int
|
|
event_listener_enable(struct evconnlistener *lev)
|
|
{
|
|
struct evconnlistener_event *lev_e =
|
|
EVUTIL_UPCAST(lev, struct evconnlistener_event, base);
|
|
return event_add(&lev_e->listener, NULL);
|
|
}
|
|
|
|
static int
|
|
event_listener_disable(struct evconnlistener *lev)
|
|
{
|
|
struct evconnlistener_event *lev_e =
|
|
EVUTIL_UPCAST(lev, struct evconnlistener_event, base);
|
|
return event_del(&lev_e->listener);
|
|
}
|
|
|
|
evutil_socket_t
|
|
evconnlistener_get_fd(struct evconnlistener *lev)
|
|
{
|
|
evutil_socket_t fd;
|
|
LOCK(lev);
|
|
fd = lev->ops->getfd(lev);
|
|
UNLOCK(lev);
|
|
return fd;
|
|
}
|
|
|
|
static evutil_socket_t
|
|
event_listener_getfd(struct evconnlistener *lev)
|
|
{
|
|
struct evconnlistener_event *lev_e =
|
|
EVUTIL_UPCAST(lev, struct evconnlistener_event, base);
|
|
return event_get_fd(&lev_e->listener);
|
|
}
|
|
|
|
struct event_base *
|
|
evconnlistener_get_base(struct evconnlistener *lev)
|
|
{
|
|
struct event_base *base;
|
|
LOCK(lev);
|
|
base = lev->ops->getbase(lev);
|
|
UNLOCK(lev);
|
|
return base;
|
|
}
|
|
|
|
static struct event_base *
|
|
event_listener_getbase(struct evconnlistener *lev)
|
|
{
|
|
struct evconnlistener_event *lev_e =
|
|
EVUTIL_UPCAST(lev, struct evconnlistener_event, base);
|
|
return event_get_base(&lev_e->listener);
|
|
}
|
|
|
|
void
|
|
evconnlistener_set_cb(struct evconnlistener *lev,
|
|
evconnlistener_cb cb, void *arg)
|
|
{
|
|
int enable = 0;
|
|
LOCK(lev);
|
|
if (lev->enabled && !lev->cb)
|
|
enable = 1;
|
|
lev->cb = cb;
|
|
lev->user_data = arg;
|
|
if (enable)
|
|
evconnlistener_enable(lev);
|
|
UNLOCK(lev);
|
|
}
|
|
|
|
void
|
|
evconnlistener_set_error_cb(struct evconnlistener *lev,
|
|
evconnlistener_errorcb errorcb)
|
|
{
|
|
LOCK(lev);
|
|
lev->errorcb = errorcb;
|
|
UNLOCK(lev);
|
|
}
|
|
|
|
static void
|
|
listener_read_cb(evutil_socket_t fd, short what, void *p)
|
|
{
|
|
struct evconnlistener *lev = p;
|
|
int err;
|
|
evconnlistener_cb cb;
|
|
evconnlistener_errorcb errorcb;
|
|
void *user_data;
|
|
LOCK(lev);
|
|
while (1) {
|
|
struct sockaddr_storage ss;
|
|
ev_socklen_t socklen = sizeof(ss);
|
|
evutil_socket_t new_fd = evutil_accept4(fd, (struct sockaddr*)&ss, &socklen, lev->accept4_flags);
|
|
if (new_fd < 0)
|
|
break;
|
|
if (socklen == 0) {
|
|
/* This can happen with some older linux kernels in
|
|
* response to nmap. */
|
|
evutil_closesocket(new_fd);
|
|
continue;
|
|
}
|
|
|
|
if (lev->cb == NULL) {
|
|
UNLOCK(lev);
|
|
return;
|
|
}
|
|
++lev->refcnt;
|
|
cb = lev->cb;
|
|
user_data = lev->user_data;
|
|
UNLOCK(lev);
|
|
cb(lev, new_fd, (struct sockaddr*)&ss, (int)socklen,
|
|
user_data);
|
|
LOCK(lev);
|
|
if (lev->refcnt == 1) {
|
|
int freed = listener_decref_and_unlock(lev);
|
|
EVUTIL_ASSERT(freed);
|
|
return;
|
|
}
|
|
--lev->refcnt;
|
|
}
|
|
err = evutil_socket_geterror(fd);
|
|
if (EVUTIL_ERR_ACCEPT_RETRIABLE(err)) {
|
|
UNLOCK(lev);
|
|
return;
|
|
}
|
|
if (lev->errorcb != NULL) {
|
|
++lev->refcnt;
|
|
errorcb = lev->errorcb;
|
|
user_data = lev->user_data;
|
|
UNLOCK(lev);
|
|
errorcb(lev, user_data);
|
|
LOCK(lev);
|
|
listener_decref_and_unlock(lev);
|
|
} else {
|
|
event_sock_warn(fd, "Error from accept() call");
|
|
}
|
|
}
|
|
|
|
#ifdef _WIN32
|
|
struct accepting_socket {
|
|
CRITICAL_SECTION lock;
|
|
struct event_overlapped overlapped;
|
|
SOCKET s;
|
|
int error;
|
|
struct deferred_cb deferred;
|
|
struct evconnlistener_iocp *lev;
|
|
ev_uint8_t buflen;
|
|
ev_uint8_t family;
|
|
unsigned free_on_cb:1;
|
|
char addrbuf[1];
|
|
};
|
|
|
|
static void accepted_socket_cb(struct event_overlapped *o, ev_uintptr_t key,
|
|
ev_ssize_t n, int ok);
|
|
static void accepted_socket_invoke_user_cb(struct deferred_cb *cb, void *arg);
|
|
|
|
static void
|
|
iocp_listener_event_add(struct evconnlistener_iocp *lev)
|
|
{
|
|
if (lev->event_added)
|
|
return;
|
|
|
|
lev->event_added = 1;
|
|
event_base_add_virtual(lev->event_base);
|
|
}
|
|
|
|
static void
|
|
iocp_listener_event_del(struct evconnlistener_iocp *lev)
|
|
{
|
|
if (!lev->event_added)
|
|
return;
|
|
|
|
lev->event_added = 0;
|
|
event_base_del_virtual(lev->event_base);
|
|
}
|
|
|
|
static struct accepting_socket *
|
|
new_accepting_socket(struct evconnlistener_iocp *lev, int family)
|
|
{
|
|
struct accepting_socket *res;
|
|
int addrlen;
|
|
int buflen;
|
|
|
|
if (family == AF_INET)
|
|
addrlen = sizeof(struct sockaddr_in);
|
|
else if (family == AF_INET6)
|
|
addrlen = sizeof(struct sockaddr_in6);
|
|
else
|
|
return NULL;
|
|
buflen = (addrlen+16)*2;
|
|
|
|
res = mm_calloc(1,sizeof(struct accepting_socket)-1+buflen);
|
|
if (!res)
|
|
return NULL;
|
|
|
|
event_overlapped_init(&res->overlapped, accepted_socket_cb);
|
|
res->s = INVALID_SOCKET;
|
|
res->lev = lev;
|
|
res->buflen = buflen;
|
|
res->family = family;
|
|
|
|
event_deferred_cb_init(&res->deferred,
|
|
accepted_socket_invoke_user_cb, res);
|
|
|
|
InitializeCriticalSectionAndSpinCount(&res->lock, 1000);
|
|
|
|
return res;
|
|
}
|
|
|
|
static void
|
|
free_and_unlock_accepting_socket(struct accepting_socket *as)
|
|
{
|
|
/* requires lock. */
|
|
if (as->s != INVALID_SOCKET)
|
|
closesocket(as->s);
|
|
|
|
LeaveCriticalSection(&as->lock);
|
|
DeleteCriticalSection(&as->lock);
|
|
mm_free(as);
|
|
}
|
|
|
|
static int
|
|
start_accepting(struct accepting_socket *as)
|
|
{
|
|
/* requires lock */
|
|
const struct win32_extension_fns *ext = event_get_win32_extension_fns();
|
|
DWORD pending = 0;
|
|
SOCKET s = socket(as->family, SOCK_STREAM, 0);
|
|
int error = 0;
|
|
|
|
if (!as->lev->base.enabled)
|
|
return 0;
|
|
|
|
if (s == INVALID_SOCKET) {
|
|
error = WSAGetLastError();
|
|
goto report_err;
|
|
}
|
|
|
|
/* XXXX It turns out we need to do this again later. Does this call
|
|
* have any effect? */
|
|
setsockopt(s, SOL_SOCKET, SO_UPDATE_ACCEPT_CONTEXT,
|
|
(char *)&as->lev->fd, sizeof(&as->lev->fd));
|
|
|
|
if (!(as->lev->base.flags & LEV_OPT_LEAVE_SOCKETS_BLOCKING))
|
|
evutil_make_socket_nonblocking(s);
|
|
|
|
if (event_iocp_port_associate(as->lev->port, s, 1) < 0) {
|
|
closesocket(s);
|
|
return -1;
|
|
}
|
|
|
|
as->s = s;
|
|
|
|
if (ext->AcceptEx(as->lev->fd, s, as->addrbuf, 0,
|
|
as->buflen/2, as->buflen/2, &pending, &as->overlapped.overlapped))
|
|
{
|
|
/* Immediate success! */
|
|
accepted_socket_cb(&as->overlapped, 1, 0, 1);
|
|
} else {
|
|
error = WSAGetLastError();
|
|
if (error != ERROR_IO_PENDING) {
|
|
goto report_err;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
|
|
report_err:
|
|
as->error = error;
|
|
event_deferred_cb_schedule(
|
|
event_base_get_deferred_cb_queue(as->lev->event_base),
|
|
&as->deferred);
|
|
return 0;
|
|
}
|
|
|
|
static void
|
|
stop_accepting(struct accepting_socket *as)
|
|
{
|
|
/* requires lock. */
|
|
SOCKET s = as->s;
|
|
as->s = INVALID_SOCKET;
|
|
closesocket(s);
|
|
}
|
|
|
|
static void
|
|
accepted_socket_invoke_user_cb(struct deferred_cb *dcb, void *arg)
|
|
{
|
|
struct accepting_socket *as = arg;
|
|
|
|
struct sockaddr *sa_local=NULL, *sa_remote=NULL;
|
|
int socklen_local=0, socklen_remote=0;
|
|
const struct win32_extension_fns *ext = event_get_win32_extension_fns();
|
|
struct evconnlistener *lev = &as->lev->base;
|
|
evutil_socket_t sock=-1;
|
|
void *data;
|
|
evconnlistener_cb cb=NULL;
|
|
evconnlistener_errorcb errorcb=NULL;
|
|
int error;
|
|
|
|
EVUTIL_ASSERT(ext->GetAcceptExSockaddrs);
|
|
|
|
LOCK(lev);
|
|
EnterCriticalSection(&as->lock);
|
|
if (as->free_on_cb) {
|
|
free_and_unlock_accepting_socket(as);
|
|
listener_decref_and_unlock(lev);
|
|
return;
|
|
}
|
|
|
|
++lev->refcnt;
|
|
|
|
error = as->error;
|
|
if (error) {
|
|
as->error = 0;
|
|
errorcb = lev->errorcb;
|
|
} else {
|
|
ext->GetAcceptExSockaddrs(
|
|
as->addrbuf, 0, as->buflen/2, as->buflen/2,
|
|
&sa_local, &socklen_local, &sa_remote,
|
|
&socklen_remote);
|
|
sock = as->s;
|
|
cb = lev->cb;
|
|
as->s = INVALID_SOCKET;
|
|
|
|
/* We need to call this so getsockname, getpeername, and
|
|
* shutdown work correctly on the accepted socket. */
|
|
/* XXXX handle error? */
|
|
setsockopt(sock, SOL_SOCKET, SO_UPDATE_ACCEPT_CONTEXT,
|
|
(char *)&as->lev->fd, sizeof(&as->lev->fd));
|
|
}
|
|
data = lev->user_data;
|
|
|
|
LeaveCriticalSection(&as->lock);
|
|
UNLOCK(lev);
|
|
|
|
if (errorcb) {
|
|
WSASetLastError(error);
|
|
errorcb(lev, data);
|
|
} else if (cb) {
|
|
cb(lev, sock, sa_remote, socklen_remote, data);
|
|
}
|
|
|
|
LOCK(lev);
|
|
if (listener_decref_and_unlock(lev))
|
|
return;
|
|
|
|
EnterCriticalSection(&as->lock);
|
|
start_accepting(as);
|
|
LeaveCriticalSection(&as->lock);
|
|
}
|
|
|
|
static void
|
|
accepted_socket_cb(struct event_overlapped *o, ev_uintptr_t key, ev_ssize_t n, int ok)
|
|
{
|
|
struct accepting_socket *as =
|
|
EVUTIL_UPCAST(o, struct accepting_socket, overlapped);
|
|
|
|
LOCK(&as->lev->base);
|
|
EnterCriticalSection(&as->lock);
|
|
if (ok) {
|
|
/* XXXX Don't do this if some EV_MT flag is set. */
|
|
event_deferred_cb_schedule(
|
|
event_base_get_deferred_cb_queue(as->lev->event_base),
|
|
&as->deferred);
|
|
LeaveCriticalSection(&as->lock);
|
|
} else if (as->free_on_cb) {
|
|
struct evconnlistener *lev = &as->lev->base;
|
|
free_and_unlock_accepting_socket(as);
|
|
listener_decref_and_unlock(lev);
|
|
return;
|
|
} else if (as->s == INVALID_SOCKET) {
|
|
/* This is okay; we were disabled by iocp_listener_disable. */
|
|
LeaveCriticalSection(&as->lock);
|
|
} else {
|
|
/* Some error on accept that we couldn't actually handle. */
|
|
BOOL ok;
|
|
DWORD transfer = 0, flags=0;
|
|
event_sock_warn(as->s, "Unexpected error on AcceptEx");
|
|
ok = WSAGetOverlappedResult(as->s, &o->overlapped,
|
|
&transfer, FALSE, &flags);
|
|
if (ok) {
|
|
/* well, that was confusing! */
|
|
as->error = 1;
|
|
} else {
|
|
as->error = WSAGetLastError();
|
|
}
|
|
event_deferred_cb_schedule(
|
|
event_base_get_deferred_cb_queue(as->lev->event_base),
|
|
&as->deferred);
|
|
LeaveCriticalSection(&as->lock);
|
|
}
|
|
UNLOCK(&as->lev->base);
|
|
}
|
|
|
|
static int
|
|
iocp_listener_enable(struct evconnlistener *lev)
|
|
{
|
|
int i;
|
|
struct evconnlistener_iocp *lev_iocp =
|
|
EVUTIL_UPCAST(lev, struct evconnlistener_iocp, base);
|
|
|
|
LOCK(lev);
|
|
iocp_listener_event_add(lev_iocp);
|
|
for (i = 0; i < lev_iocp->n_accepting; ++i) {
|
|
struct accepting_socket *as = lev_iocp->accepting[i];
|
|
if (!as)
|
|
continue;
|
|
EnterCriticalSection(&as->lock);
|
|
if (!as->free_on_cb && as->s == INVALID_SOCKET)
|
|
start_accepting(as);
|
|
LeaveCriticalSection(&as->lock);
|
|
}
|
|
UNLOCK(lev);
|
|
return 0;
|
|
}
|
|
|
|
static int
|
|
iocp_listener_disable_impl(struct evconnlistener *lev, int shutdown)
|
|
{
|
|
int i;
|
|
struct evconnlistener_iocp *lev_iocp =
|
|
EVUTIL_UPCAST(lev, struct evconnlistener_iocp, base);
|
|
|
|
LOCK(lev);
|
|
iocp_listener_event_del(lev_iocp);
|
|
for (i = 0; i < lev_iocp->n_accepting; ++i) {
|
|
struct accepting_socket *as = lev_iocp->accepting[i];
|
|
if (!as)
|
|
continue;
|
|
EnterCriticalSection(&as->lock);
|
|
if (!as->free_on_cb && as->s != INVALID_SOCKET) {
|
|
if (shutdown)
|
|
as->free_on_cb = 1;
|
|
stop_accepting(as);
|
|
}
|
|
LeaveCriticalSection(&as->lock);
|
|
}
|
|
UNLOCK(lev);
|
|
return 0;
|
|
}
|
|
|
|
static int
|
|
iocp_listener_disable(struct evconnlistener *lev)
|
|
{
|
|
return iocp_listener_disable_impl(lev,0);
|
|
}
|
|
|
|
static void
|
|
iocp_listener_destroy(struct evconnlistener *lev)
|
|
{
|
|
struct evconnlistener_iocp *lev_iocp =
|
|
EVUTIL_UPCAST(lev, struct evconnlistener_iocp, base);
|
|
|
|
if (! lev_iocp->shutting_down) {
|
|
lev_iocp->shutting_down = 1;
|
|
iocp_listener_disable_impl(lev,1);
|
|
}
|
|
|
|
}
|
|
|
|
static evutil_socket_t
|
|
iocp_listener_getfd(struct evconnlistener *lev)
|
|
{
|
|
struct evconnlistener_iocp *lev_iocp =
|
|
EVUTIL_UPCAST(lev, struct evconnlistener_iocp, base);
|
|
return lev_iocp->fd;
|
|
}
|
|
static struct event_base *
|
|
iocp_listener_getbase(struct evconnlistener *lev)
|
|
{
|
|
struct evconnlistener_iocp *lev_iocp =
|
|
EVUTIL_UPCAST(lev, struct evconnlistener_iocp, base);
|
|
return lev_iocp->event_base;
|
|
}
|
|
|
|
static const struct evconnlistener_ops evconnlistener_iocp_ops = {
|
|
iocp_listener_enable,
|
|
iocp_listener_disable,
|
|
iocp_listener_destroy,
|
|
iocp_listener_destroy, /* shutdown */
|
|
iocp_listener_getfd,
|
|
iocp_listener_getbase
|
|
};
|
|
|
|
/* XXX define some way to override this. */
|
|
#define N_SOCKETS_PER_LISTENER 4
|
|
|
|
struct evconnlistener *
|
|
evconnlistener_new_async(struct event_base *base,
|
|
evconnlistener_cb cb, void *ptr, unsigned flags, int backlog,
|
|
evutil_socket_t fd)
|
|
{
|
|
struct sockaddr_storage ss;
|
|
int socklen = sizeof(ss);
|
|
struct evconnlistener_iocp *lev;
|
|
int i;
|
|
|
|
flags |= LEV_OPT_THREADSAFE;
|
|
|
|
if (!base || !event_base_get_iocp(base))
|
|
goto err;
|
|
|
|
/* XXXX duplicate code */
|
|
if (backlog > 0) {
|
|
if (listen(fd, backlog) < 0)
|
|
goto err;
|
|
} else if (backlog < 0) {
|
|
if (listen(fd, 128) < 0)
|
|
goto err;
|
|
}
|
|
if (getsockname(fd, (struct sockaddr*)&ss, &socklen)) {
|
|
event_sock_warn(fd, "getsockname");
|
|
goto err;
|
|
}
|
|
lev = mm_calloc(1, sizeof(struct evconnlistener_iocp));
|
|
if (!lev) {
|
|
event_warn("calloc");
|
|
goto err;
|
|
}
|
|
lev->base.ops = &evconnlistener_iocp_ops;
|
|
lev->base.cb = cb;
|
|
lev->base.user_data = ptr;
|
|
lev->base.flags = flags;
|
|
lev->base.refcnt = 1;
|
|
lev->base.enabled = 1;
|
|
|
|
lev->port = event_base_get_iocp(base);
|
|
lev->fd = fd;
|
|
lev->event_base = base;
|
|
|
|
|
|
if (event_iocp_port_associate(lev->port, fd, 1) < 0)
|
|
goto err_free_lev;
|
|
|
|
EVTHREAD_ALLOC_LOCK(lev->base.lock, EVTHREAD_LOCKTYPE_RECURSIVE);
|
|
|
|
lev->n_accepting = N_SOCKETS_PER_LISTENER;
|
|
lev->accepting = mm_calloc(lev->n_accepting,
|
|
sizeof(struct accepting_socket *));
|
|
if (!lev->accepting) {
|
|
event_warn("calloc");
|
|
goto err_delete_lock;
|
|
}
|
|
for (i = 0; i < lev->n_accepting; ++i) {
|
|
lev->accepting[i] = new_accepting_socket(lev, ss.ss_family);
|
|
if (!lev->accepting[i]) {
|
|
event_warnx("Couldn't create accepting socket");
|
|
goto err_free_accepting;
|
|
}
|
|
if (cb && start_accepting(lev->accepting[i]) < 0) {
|
|
event_warnx("Couldn't start accepting on socket");
|
|
EnterCriticalSection(&lev->accepting[i]->lock);
|
|
free_and_unlock_accepting_socket(lev->accepting[i]);
|
|
goto err_free_accepting;
|
|
}
|
|
++lev->base.refcnt;
|
|
}
|
|
|
|
iocp_listener_event_add(lev);
|
|
|
|
return &lev->base;
|
|
|
|
err_free_accepting:
|
|
mm_free(lev->accepting);
|
|
/* XXXX free the other elements. */
|
|
err_delete_lock:
|
|
EVTHREAD_FREE_LOCK(lev->base.lock, EVTHREAD_LOCKTYPE_RECURSIVE);
|
|
err_free_lev:
|
|
mm_free(lev);
|
|
err:
|
|
/* Don't close the fd, it is caller's responsibility. */
|
|
return NULL;
|
|
}
|
|
|
|
#endif
|