├── src ├── var.cpp ├── struct.cpp ├── udp_raw.h ├── dns │ ├── dns_parser.h │ └── dns_parser.c ├── netif │ ├── socket_util.h │ ├── socket_util.c │ ├── tapif.h │ ├── tunif.h │ ├── tapif.c │ └── tunif.c ├── util.h ├── var.h ├── struct.h ├── tcp_raw.h ├── socks5.h ├── util.cpp ├── socks5.cpp ├── main.cpp └── tcp_raw.cpp ├── libev ├── autogen.sh ├── Symbols.event ├── configure.ac ├── Makefile.am ├── TODO ├── Symbols.ev ├── libev.m4 ├── LICENSE ├── README ├── config.h.in ├── mkinstalldirs ├── ev_poll.c ├── ev_win32.c ├── ev_wrap.h ├── event.h ├── ev_vars.h ├── ev_port.c ├── ev_kqueue.c ├── missing ├── compile ├── ev_select.c ├── ev_epoll.c └── event.c ├── scripts ├── route ├── linux_down_tuntap.sh ├── config.darwin.example.yml ├── config.linux.example.yml ├── linux_setup_tuntap.sh ├── darwin_setup_utun.sh ├── darwin_down_utun.sh ├── block.conf └── custom_domain_server.conf ├── Rakefile ├── cmake ├── libyaml.cmake ├── libev.cmake ├── config.h.cmake └── liblwip.cmake ├── .gitmodules ├── .editorconfig ├── .gitignore ├── CMakeLists.txt ├── README.md └── Vagrantfile /src/var.cpp: -------------------------------------------------------------------------------- 1 | #include "var.h" 2 | -------------------------------------------------------------------------------- /libev/autogen.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | autoreconf --install --symlink --force 4 | -------------------------------------------------------------------------------- /scripts/route: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FlowerWrong/ip2socks/HEAD/scripts/route -------------------------------------------------------------------------------- /src/struct.cpp: -------------------------------------------------------------------------------- 1 | #include "struct.h" 2 | 3 | struct Conf *conf = static_cast(malloc(sizeof(Conf))); 4 | -------------------------------------------------------------------------------- /src/udp_raw.h: -------------------------------------------------------------------------------- 1 | /** 2 | * based on lwip-contrib 3 | */ 4 | #ifndef LWIP_UDP_RAW_H 5 | #define LWIP_UDP_RAW_H 6 | 7 | void udp_raw_init(void); 8 | 9 | #endif /* LWIP_UDP_RAW_H */ 10 | -------------------------------------------------------------------------------- /src/dns/dns_parser.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | char *get_query_domain(const u_char *payload, int paylen, FILE *trace); 9 | 10 | #ifdef __cplusplus 11 | } 12 | #endif 13 | -------------------------------------------------------------------------------- /src/netif/socket_util.h: -------------------------------------------------------------------------------- 1 | #ifndef LWIP_SOCKET_UTIL_H 2 | #define LWIP_SOCKET_UTIL_H 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | int setnonblocking(int fd); 9 | 10 | #ifdef __cplusplus 11 | } 12 | #endif 13 | 14 | #endif //LWIP_SOCKET_UTIL_H 15 | -------------------------------------------------------------------------------- /src/netif/socket_util.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "socket_util.h" 3 | 4 | int setnonblocking(int fd) { 5 | int flags; 6 | if (-1 == (flags = fcntl(fd, F_GETFL, 0))) { 7 | flags = 0; 8 | } 9 | return fcntl(fd, F_SETFL, flags | O_NONBLOCK); 10 | } 11 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | task default: %w[clean] 2 | 3 | desc "clean ignore file" 4 | task :clean do 5 | sh "rm -rf Makefile CMakeCache.txt cmake_install.cmake CTestTestfile.cmake CMakeFiles cmake-build-debug" 6 | sh "rm -rf *.a *.dylib *.so *.cbp *.log vgcore.*" 7 | sh "rm -rf libyaml/include/config.h libev/config.h ip2socks ip2socks.dSYM" 8 | end 9 | -------------------------------------------------------------------------------- /src/util.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | void split(std::string &s, std::string &delim, std::vector *ret); 6 | 7 | bool end_with(const std::string &str, const std::string &suffix); 8 | 9 | void match_dns_rule(std::vector> &domains, std::string &domain, bool *matched, 10 | std::string *dns_server, bool *blocked); 11 | -------------------------------------------------------------------------------- /src/netif/tapif.h: -------------------------------------------------------------------------------- 1 | /** 2 | * based on lwip-contrib 3 | */ 4 | #ifndef LWIP_TAPIF_H 5 | #define LWIP_TAPIF_H 6 | 7 | #ifdef __cplusplus 8 | extern "C" { 9 | #endif 10 | 11 | #include "lwip/netif.h" 12 | 13 | err_t tapif_init(struct netif *netif); 14 | 15 | #if NO_SYS 16 | void tapif_input(struct netif *netif); 17 | #endif /* NO_SYS */ 18 | 19 | #ifdef __cplusplus 20 | } 21 | #endif 22 | 23 | #endif /* LWIP_TAPIF_H */ 24 | -------------------------------------------------------------------------------- /src/netif/tunif.h: -------------------------------------------------------------------------------- 1 | /** 2 | * based on lwip-contrib 3 | */ 4 | #ifndef LWIP_TUNIF_H 5 | #define LWIP_TUNIF_H 6 | 7 | #ifdef __cplusplus 8 | extern "C" { 9 | #endif 10 | 11 | #include "lwip/netif.h" 12 | #include "lwip/pbuf.h" 13 | 14 | err_t tunif_init(struct netif *netif); 15 | 16 | #if NO_SYS 17 | void tunif_input(struct netif *netif); 18 | #endif /* NO_SYS */ 19 | 20 | #ifdef __cplusplus 21 | } 22 | #endif 23 | 24 | #endif /* LWIP_TUNIF_H */ 25 | -------------------------------------------------------------------------------- /libev/Symbols.event: -------------------------------------------------------------------------------- 1 | event_active 2 | event_add 3 | event_base_dispatch 4 | event_base_free 5 | event_base_get_method 6 | event_base_loop 7 | event_base_loopexit 8 | event_base_new 9 | event_base_once 10 | event_base_priority_init 11 | event_base_set 12 | event_del 13 | event_dispatch 14 | event_get_callback 15 | event_get_method 16 | event_get_version 17 | event_init 18 | event_loop 19 | event_loopexit 20 | event_once 21 | event_pending 22 | event_priority_init 23 | event_priority_set 24 | event_set 25 | -------------------------------------------------------------------------------- /cmake/libyaml.cmake: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8) 2 | project(yaml C) 3 | 4 | set(YAML_VERSION_MAJOR 0) 5 | set(YAML_VERSION_MINOR 1) 6 | set(YAML_VERSION_PATCH 7) 7 | set(YAML_VERSION_STRING "${YAML_VERSION_MAJOR}.${YAML_VERSION_MINOR}.${YAML_VERSION_PATCH}") 8 | 9 | set(LIBYAMLDIR libyaml) 10 | 11 | add_definitions(-DHAVE_CONFIG_H) 12 | 13 | file(GLOB YAML_SOURCE_FILES ${LIBYAMLDIR}/src/*.c ${LIBYAMLDIR}/src/yaml_private.h) 14 | 15 | configure_file(cmake/config.h.cmake ${LIBYAMLDIR}/include/config.h) 16 | -------------------------------------------------------------------------------- /libev/configure.ac: -------------------------------------------------------------------------------- 1 | AC_INIT 2 | 3 | orig_CFLAGS="$CFLAGS" 4 | 5 | AC_CONFIG_SRCDIR([ev_epoll.c]) 6 | 7 | dnl also update ev.h! 8 | AM_INIT_AUTOMAKE(libev,4.24) 9 | AC_CONFIG_HEADERS([config.h]) 10 | AM_MAINTAINER_MODE 11 | 12 | AC_PROG_CC 13 | 14 | dnl Supply default CFLAGS, if not specified 15 | if test -z "$orig_CFLAGS"; then 16 | if test x$GCC = xyes; then 17 | CFLAGS="-g -O3" 18 | fi 19 | fi 20 | 21 | AC_PROG_INSTALL 22 | AC_PROG_LIBTOOL 23 | 24 | m4_include([libev.m4]) 25 | 26 | AC_CONFIG_FILES([Makefile]) 27 | AC_OUTPUT 28 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "lwip"] 2 | path = lwip 3 | url = git@github.com:FlowerWrong/lwip.git 4 | [submodule "scripts/china_ip_list"] 5 | path = scripts/china_ip_list 6 | url = git@github.com:17mon/china_ip_list.git 7 | [submodule "libyaml"] 8 | path = libyaml 9 | url = git@github.com:yaml/libyaml.git 10 | [submodule "scripts/dnsmasq-china-list"] 11 | path = scripts/dnsmasq-china-list 12 | url = git@github.com:felixonmars/dnsmasq-china-list.git 13 | [submodule "lwip-contrib"] 14 | path = lwip-contrib 15 | url = git@github.com:FlowerWrong/lwip-contrib.git 16 | -------------------------------------------------------------------------------- /libev/Makefile.am: -------------------------------------------------------------------------------- 1 | AUTOMAKE_OPTIONS = foreign 2 | 3 | VERSION_INFO = 4:0:0 4 | 5 | EXTRA_DIST = LICENSE Changes libev.m4 autogen.sh \ 6 | ev_vars.h ev_wrap.h \ 7 | ev_epoll.c ev_select.c ev_poll.c ev_kqueue.c ev_port.c ev_win32.c \ 8 | ev.3 ev.pod Symbols.ev Symbols.event 9 | 10 | man_MANS = ev.3 11 | 12 | include_HEADERS = ev.h ev++.h event.h 13 | 14 | lib_LTLIBRARIES = libev.la 15 | 16 | libev_la_SOURCES = ev.c event.c 17 | libev_la_LDFLAGS = -version-info $(VERSION_INFO) 18 | 19 | ev.3: ev.pod 20 | pod2man -n LIBEV -r "libev-$(VERSION)" -c "libev - high performance full featured event loop" -s3 <$< >$@ 21 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig is awesome: http://EditorConfig.org 2 | root = true 3 | 4 | # Unix-style newlines with a newline ending every file 5 | [*] 6 | end_of_line = lf 7 | insert_final_newline = true 8 | charset = utf-8 9 | 10 | # Tab indentation (no size specified) 11 | [Makefile] 12 | indent_style = tab 13 | 14 | [CMakeLists.txt] 15 | trim_trailing_whitespace = false 16 | indent_style = space 17 | indent_size = 4 18 | 19 | [*.cmake] 20 | trim_trailing_whitespace = false 21 | indent_style = space 22 | indent_size = 4 23 | 24 | # Matches the exact files either package.json or .travis.yml 25 | [{package.json,.travis.yml}] 26 | indent_style = space 27 | indent_size = 2 28 | -------------------------------------------------------------------------------- /src/var.h: -------------------------------------------------------------------------------- 1 | #define SLASH "/" 2 | #define BUFFER_SIZE 1514 3 | #define UDP_BUFFER_SIZE 1460 4 | #define NUM_OPTS ((sizeof(longopts) / sizeof(struct option)) - 1) 5 | #define container_of(ptr, type, member) ({ \ 6 | const typeof( ((type *)0)->member ) *__mptr = (ptr); \ 7 | (type *)( (char *)__mptr - offsetof(type,member) );}) 8 | 9 | 10 | // ==========socks 5========== 11 | // socks5 version 12 | #define SOCKS5_VERSION 0x05 13 | // socks5 command 14 | #define SOCKS5_CMD_CONNECT 0x01 15 | #define SOCKS5_CMD_BIND 0x02 16 | #define SOCKS5_CMD_UDPASSOCIATE 0x03 17 | 18 | // socks5 address type 19 | #define SOSKC5_ADDRTYPE_IPV4 0x01 20 | #define SOSKC5_ADDRTYPE_DOMAIN 0x03 21 | #define SOSKC5_ADDRTYPE_IPV6 0x04 22 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /.vagrant/ 2 | 3 | build/ 4 | 5 | .DS_Store 6 | .depend 7 | 8 | .idea/ 9 | *.iml 10 | 11 | *.log 12 | 13 | # debug 14 | vgcore* 15 | ip2socks.dSYM/ 16 | 17 | # main app 18 | ip2socks 19 | 20 | # cmake 21 | CMakeCache.txt 22 | CMakeFiles 23 | CMakeScripts 24 | Testing 25 | Makefile 26 | cmake_install.cmake 27 | install_manifest.txt 28 | compile_commands.json 29 | CTestTestfile.cmake 30 | /cmake-build-debug/ 31 | 32 | # libev 33 | /libev/.deps/ 34 | /libev/.libs/ 35 | /libev/config.h 36 | /libev/*.log 37 | /libev/*.status 38 | /libev/libtool 39 | /libev/stamp-h1 40 | /libev/*.la 41 | /libev/*.lo 42 | 43 | # config file 44 | config.yml 45 | 46 | # library 47 | *.a 48 | *.so 49 | *.dylib 50 | *.o 51 | *.out 52 | *.cbp 53 | -------------------------------------------------------------------------------- /libev/TODO: -------------------------------------------------------------------------------- 1 | TODO: ev_loop_wakeup 2 | TODO: EV_STANDALONE == NO_HASSLE (do not use clock_gettime in ev_standalone) 3 | TODO: faq, process a thing in each iteration 4 | TODO: dbeugging tips, ev_verify, ev_init twice 5 | TODO: ev_break for immediate exit (EVBREAK_NOW?) 6 | TODO: ev_feed_child_event 7 | TODO: document the special problem of signals around fork. 8 | TODO: store pid for each signal 9 | TODO: document file descriptor usage per loop 10 | TODO: store loop pid_t and compare isndie signal handler,store 1 for same, 2 for differign pid, clean up in loop_fork 11 | TODO: embed watchers need updating when fd changes 12 | TODO: document portability requirements for atomic pointer access 13 | TODO: document requirements for function pointers and calling conventions. 14 | 15 | -------------------------------------------------------------------------------- /src/struct.h: -------------------------------------------------------------------------------- 1 | #ifndef EV_STRUCT_H_H 2 | #define EV_STRUCT_H_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | struct Conf { 9 | char *ip_mode; 10 | char *dns_mode; 11 | char *socks_server; 12 | char *socks_port; 13 | char *remote_dns_server; 14 | char *remote_dns_port; 15 | char *local_dns_port; 16 | char *relay_none_dns_packet_with_udp; 17 | char *custom_domian_server_file; 18 | char *gw; 19 | char *addr; 20 | char *netmask; 21 | char *after_start_shell; 22 | char *before_shutdown_shell; 23 | std::vector > domains; 24 | }; 25 | 26 | struct tuntapif { 27 | /* Add whatever per-interface state that is needed here. */ 28 | int fd; 29 | }; 30 | 31 | extern struct Conf *conf; 32 | 33 | #endif //EV_STRUCT_H_H 34 | -------------------------------------------------------------------------------- /scripts/linux_down_tuntap.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | TUN_IP=$1 4 | DIRECT_IP_LIST=./scripts/china_ip_list/china_ip_list.txt 5 | 6 | # get current gateway 7 | GATEWAY_IP=$(ip route | awk '/default/ { print $3 }') 8 | echo "origin gateway is '$GATEWAY_IP'" 9 | 10 | # direct route 11 | chnroutes=$(grep -E "^([0-9]{1,3}\.){3}[0-9]{1,3}" $DIRECT_IP_LIST |\ 12 | sed -e "s/^/route del /" -e "s/$/ via $GATEWAY_IP/") 13 | 14 | ip -batch - <> /dev/null 11 | 12 | # direct route 13 | chnroutes=$(grep -E "^([0-9]{1,3}\.){3}[0-9]{1,3}" $DIRECT_IP_LIST |\ 14 | sed -e "s/^/route add /" -e "s/$/ via $GATEWAY_IP/") 15 | 16 | ip -batch - < 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #include "var.h" 15 | 16 | typedef struct { 17 | uint8_t ver; 18 | uint8_t nmethods; 19 | uint8_t methods[0]; 20 | } socks5_method_req_t; 21 | 22 | typedef struct { 23 | uint8_t ver; 24 | uint8_t method; 25 | } socks5_method_res_t; 26 | 27 | typedef struct { 28 | uint8_t ver; 29 | uint8_t cmd; 30 | uint8_t rsv; 31 | uint8_t addrtype; 32 | } socks5_request_t; 33 | typedef socks5_request_t socks5_response_t; 34 | 35 | int32_t socks5_sockset(int sockfd); 36 | 37 | int socks5_connect(const char *proxy_host, const char *proxy_port); 38 | 39 | int socks5_auth(int sockfd, const char *server_host, const char *server_port, u_char cmd, int atype); 40 | 41 | 42 | #endif //LWIP_SOCKS5_H 43 | -------------------------------------------------------------------------------- /scripts/block.conf: -------------------------------------------------------------------------------- 1 | block=/mmstat.com/domain_suffix 2 | block=/doubleclick.net/domain_suffix 3 | block=/monitor.uu.qq.com/domain_suffix 4 | block=/127.net/domain_suffix 5 | block=/amazon-adsystem.com/domain_suffix 6 | block=/applovin.com/domain_suffix 7 | block=/beacon.qq.com/domain_suffix 8 | block=/duomeng.cn/domain_suffix 9 | block=/mob.com/domain_suffix 10 | block=/sponsorpay.com/domain_suffix 11 | block=/youmi.net/domain_suffix 12 | 13 | block=/ads.mopub.com/domain 14 | block=/cpro.baidu.com/domain 15 | block=/hm.baidu.com/domain 16 | block=/hmma.baidu.com/domain 17 | block=/monitor.uu.qq.com/domain 18 | block=/graph.facebook.com/domain 19 | block=/pagead2.googlesyndication.com/domain 20 | block=/pgdt.gtimg.cn/domain 21 | block=/pingma.qq.com/domain 22 | block=/stat.m.jd.com/domain 23 | block=/ad.api.3g.youku.com/domain 24 | block=/agn.aty.sohu.com/domain 25 | block=/agn.aty.sohu.com/domain 26 | block=/ark.letv.com/domain 27 | block=/asimgs.pplive.cn/domain 28 | block=/atm.youku.com/domain 29 | block=/lives.l.qq.com/domain 30 | block=/mob/domain 31 | block=/init.icloud-analysis.com/domain 32 | block=/fonts.googleapis.com/domain 33 | block=/61.160.200/domain 34 | 35 | block=/analytics/domain_keyword 36 | block=/cnzz/domain_keyword 37 | block=/domob/domain_keyword 38 | block=/flurry.co/domain_keyword 39 | block=/umeng.co/domain_keyword 40 | -------------------------------------------------------------------------------- /src/dns/dns_parser.c: -------------------------------------------------------------------------------- 1 | #include "dns_parser.h" 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | char * 8 | hostname_from_question(ns_msg msg) { 9 | static char hostname[256] = {0}; 10 | ns_rr rr; 11 | int rrnum, rrmax; 12 | const char *result; 13 | int result_len; 14 | rrmax = ns_msg_count(msg, ns_s_qd); 15 | if (rrmax == 0) 16 | return NULL; 17 | for (rrnum = 0; rrnum < rrmax; rrnum++) { 18 | if (ns_parserr(&msg, ns_s_qd, rrnum, &rr)) { 19 | printf("ns_parserr\n"); 20 | return NULL; 21 | } 22 | result = ns_rr_name(rr); 23 | result_len = (int) strlen(result) + 1; 24 | if (result_len > sizeof(hostname)) { 25 | printf("hostname too long: %s\n", result); 26 | } 27 | memset(hostname, 0, sizeof(hostname)); 28 | memcpy(hostname, result, result_len); 29 | return hostname; 30 | } 31 | return NULL; 32 | } 33 | 34 | 35 | char *get_query_domain(const u_char *payload, int paylen, FILE *trace) { 36 | ns_msg msg; 37 | 38 | // Message too long 39 | if (ns_initparse(payload, paylen, &msg) < 0) { 40 | fputs(strerror(errno), trace); 41 | printf("\n"); 42 | return NULL; 43 | } 44 | 45 | return hostname_from_question(msg); 46 | } 47 | -------------------------------------------------------------------------------- /libev/Symbols.ev: -------------------------------------------------------------------------------- 1 | ev_async_send 2 | ev_async_start 3 | ev_async_stop 4 | ev_backend 5 | ev_break 6 | ev_check_start 7 | ev_check_stop 8 | ev_child_start 9 | ev_child_stop 10 | ev_cleanup_start 11 | ev_cleanup_stop 12 | ev_clear_pending 13 | ev_default_loop 14 | ev_default_loop_ptr 15 | ev_depth 16 | ev_embed_start 17 | ev_embed_stop 18 | ev_embed_sweep 19 | ev_embeddable_backends 20 | ev_feed_event 21 | ev_feed_fd_event 22 | ev_feed_signal 23 | ev_feed_signal_event 24 | ev_fork_start 25 | ev_fork_stop 26 | ev_idle_start 27 | ev_idle_stop 28 | ev_invoke 29 | ev_invoke_pending 30 | ev_io_start 31 | ev_io_stop 32 | ev_iteration 33 | ev_loop_destroy 34 | ev_loop_fork 35 | ev_loop_new 36 | ev_now 37 | ev_now_update 38 | ev_once 39 | ev_pending_count 40 | ev_periodic_again 41 | ev_periodic_start 42 | ev_periodic_stop 43 | ev_prepare_start 44 | ev_prepare_stop 45 | ev_recommended_backends 46 | ev_ref 47 | ev_resume 48 | ev_run 49 | ev_set_allocator 50 | ev_set_invoke_pending_cb 51 | ev_set_io_collect_interval 52 | ev_set_loop_release_cb 53 | ev_set_syserr_cb 54 | ev_set_timeout_collect_interval 55 | ev_set_userdata 56 | ev_signal_start 57 | ev_signal_stop 58 | ev_sleep 59 | ev_stat_start 60 | ev_stat_stat 61 | ev_stat_stop 62 | ev_supported_backends 63 | ev_suspend 64 | ev_time 65 | ev_timer_again 66 | ev_timer_remaining 67 | ev_timer_start 68 | ev_timer_stop 69 | ev_unref 70 | ev_userdata 71 | ev_verify 72 | ev_version_major 73 | ev_version_minor 74 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8) 2 | list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake_module") 3 | 4 | project(ip2socks) 5 | 6 | set(CMAKE_CXX_STANDARD 11) 7 | 8 | set(LIBEVDIR libev) 9 | set(LIBYAML libyaml) 10 | set(LWIPDIR lwip/src) 11 | set(LWIPARCH lwip-contrib/ports/unix/port) 12 | 13 | include(cmake/liblwip.cmake) 14 | include(cmake/libyaml.cmake) 15 | include(cmake/libev.cmake) 16 | 17 | include_directories( 18 | # lwip and patch 19 | ${LWIPDIR}/include 20 | ${LWIPARCH}/include 21 | 22 | # libev 23 | ${LIBEVDIR} 24 | 25 | # libyaml 26 | ${LIBYAML}/include 27 | ${LIBYAML}/win32 28 | ${LIBYAML}/src 29 | 30 | # source code 31 | src/netif 32 | src/dns 33 | src 34 | ) 35 | 36 | set(MAIN_SOURCE_FILES 37 | # lwip and patch 38 | ${LWIP_SOURCE_FILES} 39 | 40 | # libev 41 | ${LIBEVDIR}/ev.c 42 | 43 | # libyaml 44 | ${YAML_SOURCE_FILES} 45 | 46 | # patch files 47 | src/netif/tunif.c 48 | src/netif/socket_util.c 49 | 50 | src/dns/dns_parser.c 51 | 52 | src/struct.cpp 53 | src/socks5.cpp 54 | src/util.cpp 55 | src/tcp_raw.cpp 56 | src/udp_raw.cpp 57 | src/main.cpp 58 | ) 59 | 60 | # linux 61 | if (UNIX AND NOT APPLE) 62 | set(MAIN_SOURCE_FILES 63 | ${MAIN_SOURCE_FILES} 64 | # patch files 65 | src/netif/tapif.c 66 | ) 67 | endif () 68 | 69 | add_executable(ip2socks ${MAIN_SOURCE_FILES}) 70 | target_link_libraries(ip2socks resolv) 71 | -------------------------------------------------------------------------------- /libev/libev.m4: -------------------------------------------------------------------------------- 1 | dnl this file is part of libev, do not make local modifications 2 | dnl http://software.schmorp.de/pkg/libev 3 | 4 | dnl libev support 5 | AC_CHECK_HEADERS(sys/inotify.h sys/epoll.h sys/event.h port.h poll.h sys/select.h sys/eventfd.h sys/signalfd.h) 6 | 7 | AC_CHECK_FUNCS(inotify_init epoll_ctl kqueue port_create poll select eventfd signalfd) 8 | 9 | AC_CHECK_FUNCS(clock_gettime, [], [ 10 | dnl on linux, try syscall wrapper first 11 | if test $(uname) = Linux; then 12 | AC_MSG_CHECKING(for clock_gettime syscall) 13 | AC_LINK_IFELSE([AC_LANG_PROGRAM( 14 | [#include 15 | #include 16 | #include ], 17 | [struct timespec ts; int status = syscall (SYS_clock_gettime, CLOCK_REALTIME, &ts)])], 18 | [ac_have_clock_syscall=1 19 | AC_DEFINE(HAVE_CLOCK_SYSCALL, 1, Define to 1 to use the syscall interface for clock_gettime) 20 | AC_MSG_RESULT(yes)], 21 | [AC_MSG_RESULT(no)]) 22 | fi 23 | if test -z "$LIBEV_M4_AVOID_LIBRT" && test -z "$ac_have_clock_syscall"; then 24 | AC_CHECK_LIB(rt, clock_gettime) 25 | unset ac_cv_func_clock_gettime 26 | AC_CHECK_FUNCS(clock_gettime) 27 | fi 28 | ]) 29 | 30 | AC_CHECK_FUNCS(nanosleep, [], [ 31 | if test -z "$LIBEV_M4_AVOID_LIBRT"; then 32 | AC_CHECK_LIB(rt, nanosleep) 33 | unset ac_cv_func_nanosleep 34 | AC_CHECK_FUNCS(nanosleep) 35 | fi 36 | ]) 37 | 38 | if test -z "$LIBEV_M4_AVOID_LIBM"; then 39 | LIBM=m 40 | fi 41 | AC_SEARCH_LIBS(floor, $LIBM, [AC_DEFINE(HAVE_FLOOR, 1, Define to 1 if the floor function is available)]) 42 | 43 | -------------------------------------------------------------------------------- /libev/LICENSE: -------------------------------------------------------------------------------- 1 | All files in libev are 2 | Copyright (c)2007,2008,2009,2010,2011,2012,2013 Marc Alexander Lehmann. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are 6 | met: 7 | 8 | * Redistributions of source code must retain the above copyright 9 | notice, this list of conditions and the following disclaimer. 10 | 11 | * Redistributions in binary form must reproduce the above 12 | copyright notice, this list of conditions and the following 13 | disclaimer in the documentation and/or other materials provided 14 | with the distribution. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 | 28 | Alternatively, the contents of this package may be used under the terms 29 | of the GNU General Public License ("GPL") version 2 or any later version, 30 | in which case the provisions of the GPL are applicable instead of the 31 | above. If you wish to allow the use of your version of this package only 32 | under the terms of the GPL and not to allow others to use your version of 33 | this file under the BSD license, indicate your decision by deleting the 34 | provisions above and replace them with the notice and other provisions 35 | required by the GPL in this and the other files of this package. If you do 36 | not delete the provisions above, a recipient may use your version of this 37 | file under either the BSD or the GPL. 38 | -------------------------------------------------------------------------------- /cmake/libev.cmake: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8) 2 | 3 | project(ev C) 4 | 5 | include(CheckIncludeFiles) 6 | include(CheckFunctionExists) 7 | include(CheckLibraryExists) 8 | 9 | set(package_name "libev") 10 | set(package_bugreport "") 11 | set(package_bugreport "") 12 | set(libtool_objdir ".libs") 13 | 14 | set(libname "libev") 15 | set(version_major "4") 16 | set(version_minor "24") 17 | 18 | set(LIBEVDIR libev) 19 | 20 | include_directories(${LIBEVDIR}) 21 | 22 | # check headers 23 | check_include_files(inttypeas.h HAVE_INTTYPES_H) 24 | check_include_files(dlfcn.h HAVE_DLFCN_H) 25 | check_include_files(memory.h HAVE_MEMORY_H) 26 | check_include_files(poll.h HAVE_POLL_H) 27 | check_include_files(port.h HAVE_PORT_H) 28 | check_include_files(stdint.h HAVE_STDINT_H) 29 | check_include_files(stdlib.h HAVE_STDLIB_H) 30 | check_include_files(strings.h HAVE_STRINGS_H) 31 | check_include_files(string.h HAVE_STRING_H) 32 | check_include_files(sys/epoll.h HAVE_SYS_EPOLL_H) 33 | check_include_files(sys/eventfd.h HAVE_SYS_EVENTFD_H) 34 | check_include_files(sys/event.h HAVE_SYS_EVENT_H) 35 | check_include_files(sys/inotify.h HAVE_SYS_INOTIFY_H) 36 | check_include_files(sys/select.h HAVE_SYS_SELECT_H) 37 | check_include_files(sys/signalfd.h HAVE_SYS_SIGNALFD_H) 38 | check_include_files(sys/stat.h HAVE_SYS_STAT_H) 39 | check_include_files(sys/types.h HAVE_SYS_TYPES_H) 40 | check_include_files(unistd.h HAVE_UNISTD_H) 41 | check_include_files("assert.h;ctype.h;errno.h;float.h;limits.h;locale.h;math.h;setjmp.h;signal.h;stdarg.h;stddef.h;stdio.h;stdlib.h;string.h;time.h;" STDC_HEADERS) 42 | check_include_files("winsock.h" HAVE_WINSOCK_H) 43 | 44 | # check functions 45 | check_function_exists(clock_gettime HAVE_CLOCK_GETTIME) 46 | check_function_exists(epoll_ctl HAVE_EPOLL_CTL) 47 | check_function_exists(eventfd HAVE_EVENTFD) 48 | check_function_exists(floor HAVE_FLOOR) 49 | check_function_exists(inotify_init HAVE_INOTIFY_INIT) 50 | check_function_exists(kqueue HAVE_KQUEUE) 51 | check_function_exists(nanosleep HAVE_NANOSLEEP) 52 | check_function_exists(poll HAVE_POLL) 53 | check_function_exists(port_create HAVE_PORT_CREATE) 54 | check_function_exists(select HAVE_SELECT) 55 | check_function_exists(signalfd HAVE_SIGNALFD) 56 | 57 | # check system library 58 | check_library_exists(rt pthread_create "" HAVE_LIBRT) 59 | 60 | 61 | configure_file(cmake/config.h.cmake ${LIBEVDIR}/config.h) 62 | -------------------------------------------------------------------------------- /src/util.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | // 注意:当字符串为空时,也会返回一个空字符串 5 | void split(std::string &s, std::string &delim, std::vector *ret) { 6 | size_t last = 0; 7 | size_t index = s.find_first_of(delim, last); 8 | while (index != std::string::npos) { 9 | ret->push_back(s.substr(last, index - last)); 10 | last = index + 1; 11 | index = s.find_first_of(delim, last); 12 | } 13 | if (index - last > 0) { 14 | ret->push_back(s.substr(last, index - last)); 15 | } 16 | } 17 | 18 | bool end_with(const std::string &str, const std::string &suffix) { 19 | return str.size() >= suffix.size() && str.compare(str.size() - suffix.size(), suffix.size(), suffix) == 0; 20 | } 21 | 22 | void match_dns_rule(std::vector > &domains, std::string &domain, bool *matched, 23 | std::string *dns_server, bool *blocked) { 24 | for (int i = 0; i < domains.size(); ++i) { 25 | std::string rule(domains.at(i).at(0).c_str()); 26 | if (rule == "server=" || rule == "domain=") { 27 | if (domain == domains.at(i).at(1)) { 28 | *matched = true; 29 | *dns_server = domains.at(i).at(2); 30 | break; 31 | } 32 | } else if (rule == "domain_keyword=") { 33 | if (domain.find(domains.at(i).at(1), 0) != std::string::npos) { 34 | *matched = true; 35 | *dns_server = domains.at(i).at(2); 36 | break; 37 | } 38 | } else if (rule == "domain_suffix=") { 39 | if (end_with(domain, domains.at(i).at(1))) { 40 | *matched = true; 41 | *dns_server = domains.at(i).at(2); 42 | break; 43 | } 44 | } else if (rule == "block=") { 45 | std::string block_rule(domains.at(i).at(2).c_str()); 46 | 47 | if (block_rule == "domain") { 48 | if (domain == domains.at(i).at(1)) { 49 | *blocked = true; 50 | break; 51 | } 52 | } else if (block_rule == "domain_keyword") { 53 | if (domain.find(domains.at(i).at(1), 0) != std::string::npos) { 54 | *blocked = true; 55 | break; 56 | } 57 | } else if (block_rule == "domain_suffix") { 58 | if (end_with(domain, domains.at(i).at(1))) { 59 | *blocked = true; 60 | break; 61 | } 62 | } 63 | } 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /libev/README: -------------------------------------------------------------------------------- 1 | libev is a high-performance event loop/event model with lots of features. 2 | (see benchmark at http://libev.schmorp.de/bench.html) 3 | 4 | 5 | ABOUT 6 | 7 | Homepage: http://software.schmorp.de/pkg/libev 8 | Mailinglist: libev@lists.schmorp.de 9 | http://lists.schmorp.de/cgi-bin/mailman/listinfo/libev 10 | Library Documentation: http://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod 11 | 12 | Libev is modelled (very losely) after libevent and the Event perl 13 | module, but is faster, scales better and is more correct, and also more 14 | featureful. And also smaller. Yay. 15 | 16 | Some of the specialties of libev not commonly found elsewhere are: 17 | 18 | - extensive and detailed, readable documentation (not doxygen garbage). 19 | - fully supports fork, can detect fork in various ways and automatically 20 | re-arms kernel mechanisms that do not support fork. 21 | - highly optimised select, poll, epoll, kqueue and event ports backends. 22 | - filesystem object (path) watching (with optional linux inotify support). 23 | - wallclock-based times (using absolute time, cron-like). 24 | - relative timers/timeouts (handle time jumps). 25 | - fast intra-thread communication between multiple 26 | event loops (with optional fast linux eventfd backend). 27 | - extremely easy to embed (fully documented, no dependencies, 28 | autoconf supported but optional). 29 | - very small codebase, no bloated library, simple code. 30 | - fully extensible by being able to plug into the event loop, 31 | integrate other event loops, integrate other event loop users. 32 | - very little memory use (small watchers, small event loop data). 33 | - optional C++ interface allowing method and function callbacks 34 | at no extra memory or runtime overhead. 35 | - optional Perl interface with similar characteristics (capable 36 | of running Glib/Gtk2 on libev). 37 | - support for other languages (multiple C++ interfaces, D, Ruby, 38 | Python) available from third-parties. 39 | 40 | Examples of programs that embed libev: the EV perl module, node.js, 41 | auditd, rxvt-unicode, gvpe (GNU Virtual Private Ethernet), the 42 | Deliantra MMORPG server (http://www.deliantra.net/), Rubinius (a 43 | next-generation Ruby VM), the Ebb web server, the Rev event toolkit. 44 | 45 | 46 | CONTRIBUTORS 47 | 48 | libev was written and designed by Marc Lehmann and Emanuele Giaquinta. 49 | 50 | The following people sent in patches or made other noteworthy 51 | contributions to the design (for minor patches, see the Changes 52 | file. If I forgot to include you, please shout at me, it was an 53 | accident): 54 | 55 | W.C.A. Wijngaards 56 | Christopher Layne 57 | Chris Brody 58 | 59 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ip2socks 2 | 3 | ## Support operating system 4 | 5 | * [x] OSX 6 | * [x] Linux 7 | 8 | ## Get start 9 | 10 | ```bash 11 | git clone https://github.com/FlowerWrong/ip2socks.git --recursive 12 | 13 | # ubuntu vm 14 | vagrant up --provider virtualbox 15 | vagrant ssh 16 | ``` 17 | 18 | #### Compile with C++ 11 and cmake 19 | 20 | ```bash 21 | # build ip2socks 22 | cmake . 23 | make 24 | 25 | 26 | ## start ip2socks 27 | # OSX 28 | sudo ./ip2socks --config=./scripts/config.darwin.example.yml 29 | 30 | # linux 31 | sudo ./ip2socks --config=./scripts/config.linux.example.yml 32 | ``` 33 | 34 | #### ip mode 35 | 36 | * tun 37 | * tap 38 | 39 | #### dns mode 40 | 41 | * tcp: just dns with port you set `local_dns_port` redirect to tcp, other flow will be try to send to remote via socks 5 udp tunnel 42 | * udp: just dns with port you set `local_dns_port` redirect to udp, other flow will be send to remote via socks 5 udp tunnel 43 | 44 | #### There are 5 ways to setup DNS query to remote 45 | 46 | * `use-vc` in `/etc/resolv.conf`: Sets RES_USEVC in _res.options. This option forces the use of TCP for DNS resolutions. 47 | * pdnsd 48 | * lwip udp hooked, redirect to upstream tcp dns server via socks 5, config with `remote_dns_server`, you can just route your dns servers to tun or tap with `route` on OSX or `ip route` on Linux 49 | * lwip udp hooked, redirect to upstream tcp dns server via socks 5, config with `remote_dns_server`, setup your dns to `addr`, eg `10.0.0.2` 50 | * lwip udp hooked, set you dns to remote, eg: `8.8.8.8` 51 | 52 | ## Library 53 | 54 | * C++ 11 55 | * [lwip](https://github.com/FlowerWrong/lwip) 56 | * [lwip-contrib](https://github.com/FlowerWrong/lwip-contrib) 57 | * [libev](http://software.schmorp.de/pkg/libev.html) 58 | * [libyaml](https://github.com/yaml/libyaml) 59 | 60 | ## Know bugs 61 | 62 | * [x] too many `CLOSE_WAIT` to socks server, see `netstat -an | grep CLOSE_WAIT | wc -l` 63 | * [x] OSX receive data too often, eg: `brew update`, `brew upgrade` 64 | * [x] if `ERR_QUIC_PROTOCOL_ERROR`, go to `chrome://flags/` disable quic 65 | * [x] ns_initparse `Message too long` bug 66 | * [ ] (libev) select: Invalid argument 67 | * [ ] tcp_raw_error is -14(ERR_RST): Connection reset. 68 | 69 | ## TODO 70 | 71 | * [ ] speed statistics 72 | * [ ] DNS cache 73 | * [x] `block` rule support, just close it 74 | * [ ] dnsmasq `address=/test.com/127.0.0.1` support 75 | * [x] `domain`, `domain_keyword`, `domain_suffix` (ip_cidr, geoip) rule support 76 | * [x] timeout 77 | * [ ] log 78 | * [x] OSX route batch insert 79 | * [x] lwip `keep-alive` support 80 | * [x] lwip `SO_REUSEADDR` support 81 | * [ ] TCP fast open with Linux kernel > 3.7.0 82 | * [x] socks 5 client UDP relay 83 | * [ ] FreeBSD support 84 | * [ ] Android support 85 | * [ ] iOS support 86 | * [ ] ipv6 support 87 | -------------------------------------------------------------------------------- /Vagrantfile: -------------------------------------------------------------------------------- 1 | # -*- mode: ruby -*- 2 | # vi: set ft=ruby : 3 | 4 | # All Vagrant configuration is done below. The "2" in Vagrant.configure 5 | # configures the configuration version (we support older styles for 6 | # backwards compatibility). Please don't change it unless you know what 7 | # you're doing. 8 | Vagrant.configure("2") do |config| 9 | # The most common configuration options are documented and commented below. 10 | # For a complete reference, please see the online documentation at 11 | # https://docs.vagrantup.com. 12 | 13 | # Every Vagrant development environment requires a box. You can search for 14 | # boxes at https://atlas.hashicorp.com/search. 15 | config.vm.box = "ubuntu/trusty64" 16 | 17 | # Disable automatic box update checking. If you disable this, then 18 | # boxes will only be checked for updates when the user runs 19 | # `vagrant box outdated`. This is not recommended. 20 | # config.vm.box_check_update = false 21 | 22 | # Create a forwarded port mapping which allows access to a specific port 23 | # within the machine from a port on the host machine. In the example below, 24 | # accessing "localhost:8080" will access port 80 on the guest machine. 25 | # NOTE: This will enable public access to the opened port 26 | # config.vm.network "forwarded_port", guest: 80, host: 8080 27 | 28 | # Create a forwarded port mapping which allows access to a specific port 29 | # within the machine from a port on the host machine and only allow access 30 | # via 127.0.0.1 to disable public access 31 | # config.vm.network "forwarded_port", guest: 80, host: 8080, host_ip: "127.0.0.1" 32 | 33 | # Create a private network, which allows host-only access to the machine 34 | # using a specific IP. 35 | # config.vm.network "private_network", ip: "192.168.33.10" 36 | 37 | # Create a public network, which generally matched to bridged network. 38 | # Bridged networks make the machine appear as another physical device on 39 | # your network. 40 | # config.vm.network "public_network" 41 | 42 | # Share an additional folder to the guest VM. The first argument is 43 | # the path on the host to the actual folder. The second argument is 44 | # the path on the guest to mount the folder. And the optional third 45 | # argument is a set of non-required options. 46 | # config.vm.synced_folder "../data", "/vagrant_data" 47 | 48 | # Provider-specific configuration so you can fine-tune various 49 | # backing providers for Vagrant. These expose provider-specific options. 50 | # Example for VirtualBox: 51 | # 52 | # config.vm.provider "virtualbox" do |vb| 53 | # # Display the VirtualBox GUI when booting the machine 54 | # vb.gui = true 55 | # 56 | # # Customize the amount of memory on the VM: 57 | # vb.memory = "1024" 58 | # end 59 | # 60 | # View the documentation for the provider you are using for more 61 | # information on available options. 62 | 63 | # Define a Vagrant Push strategy for pushing to Atlas. Other push strategies 64 | # such as FTP and Heroku are also available. See the documentation at 65 | # https://docs.vagrantup.com/v2/push/atlas.html for more information. 66 | # config.push.define "atlas" do |push| 67 | # push.app = "YOUR_ATLAS_USERNAME/YOUR_APPLICATION_NAME" 68 | # end 69 | 70 | # Enable provisioning with a shell script. Additional provisioners such as 71 | # Puppet, Chef, Ansible, Salt, and Docker are also available. Please see the 72 | # documentation for more information about their specific syntax and use. 73 | # config.vm.provision "shell", inline: <<-SHELL 74 | # apt-get update 75 | # apt-get install -y apache2 76 | # SHELL 77 | end 78 | -------------------------------------------------------------------------------- /libev/config.h.in: -------------------------------------------------------------------------------- 1 | /* config.h.in. Generated from configure.ac by autoheader. */ 2 | 3 | /* Define to 1 if you have the `clock_gettime' function. */ 4 | #undef HAVE_CLOCK_GETTIME 5 | 6 | /* Define to 1 to use the syscall interface for clock_gettime */ 7 | #undef HAVE_CLOCK_SYSCALL 8 | 9 | /* Define to 1 if you have the header file. */ 10 | #undef HAVE_DLFCN_H 11 | 12 | /* Define to 1 if you have the `epoll_ctl' function. */ 13 | #undef HAVE_EPOLL_CTL 14 | 15 | /* Define to 1 if you have the `eventfd' function. */ 16 | #undef HAVE_EVENTFD 17 | 18 | /* Define to 1 if the floor function is available */ 19 | #undef HAVE_FLOOR 20 | 21 | /* Define to 1 if you have the `inotify_init' function. */ 22 | #undef HAVE_INOTIFY_INIT 23 | 24 | /* Define to 1 if you have the header file. */ 25 | #undef HAVE_INTTYPES_H 26 | 27 | /* Define to 1 if you have the `kqueue' function. */ 28 | #undef HAVE_KQUEUE 29 | 30 | /* Define to 1 if you have the `rt' library (-lrt). */ 31 | #undef HAVE_LIBRT 32 | 33 | /* Define to 1 if you have the header file. */ 34 | #undef HAVE_MEMORY_H 35 | 36 | /* Define to 1 if you have the `nanosleep' function. */ 37 | #undef HAVE_NANOSLEEP 38 | 39 | /* Define to 1 if you have the `poll' function. */ 40 | #undef HAVE_POLL 41 | 42 | /* Define to 1 if you have the header file. */ 43 | #undef HAVE_POLL_H 44 | 45 | /* Define to 1 if you have the `port_create' function. */ 46 | #undef HAVE_PORT_CREATE 47 | 48 | /* Define to 1 if you have the header file. */ 49 | #undef HAVE_PORT_H 50 | 51 | /* Define to 1 if you have the `select' function. */ 52 | #undef HAVE_SELECT 53 | 54 | /* Define to 1 if you have the `signalfd' function. */ 55 | #undef HAVE_SIGNALFD 56 | 57 | /* Define to 1 if you have the header file. */ 58 | #undef HAVE_STDINT_H 59 | 60 | /* Define to 1 if you have the header file. */ 61 | #undef HAVE_STDLIB_H 62 | 63 | /* Define to 1 if you have the header file. */ 64 | #undef HAVE_STRINGS_H 65 | 66 | /* Define to 1 if you have the header file. */ 67 | #undef HAVE_STRING_H 68 | 69 | /* Define to 1 if you have the header file. */ 70 | #undef HAVE_SYS_EPOLL_H 71 | 72 | /* Define to 1 if you have the header file. */ 73 | #undef HAVE_SYS_EVENTFD_H 74 | 75 | /* Define to 1 if you have the header file. */ 76 | #undef HAVE_SYS_EVENT_H 77 | 78 | /* Define to 1 if you have the header file. */ 79 | #undef HAVE_SYS_INOTIFY_H 80 | 81 | /* Define to 1 if you have the header file. */ 82 | #undef HAVE_SYS_SELECT_H 83 | 84 | /* Define to 1 if you have the header file. */ 85 | #undef HAVE_SYS_SIGNALFD_H 86 | 87 | /* Define to 1 if you have the header file. */ 88 | #undef HAVE_SYS_STAT_H 89 | 90 | /* Define to 1 if you have the header file. */ 91 | #undef HAVE_SYS_TYPES_H 92 | 93 | /* Define to 1 if you have the header file. */ 94 | #undef HAVE_UNISTD_H 95 | 96 | /* Define to the sub-directory in which libtool stores uninstalled libraries. 97 | */ 98 | #undef LT_OBJDIR 99 | 100 | /* Name of package */ 101 | #undef PACKAGE 102 | 103 | /* Define to the address where bug reports for this package should be sent. */ 104 | #undef PACKAGE_BUGREPORT 105 | 106 | /* Define to the full name of this package. */ 107 | #undef PACKAGE_NAME 108 | 109 | /* Define to the full name and version of this package. */ 110 | #undef PACKAGE_STRING 111 | 112 | /* Define to the one symbol short name of this package. */ 113 | #undef PACKAGE_TARNAME 114 | 115 | /* Define to the home page for this package. */ 116 | #undef PACKAGE_URL 117 | 118 | /* Define to the version of this package. */ 119 | #undef PACKAGE_VERSION 120 | 121 | /* Define to 1 if you have the ANSI C header files. */ 122 | #undef STDC_HEADERS 123 | 124 | /* Version number of package */ 125 | #undef VERSION 126 | -------------------------------------------------------------------------------- /libev/mkinstalldirs: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | # mkinstalldirs --- make directory hierarchy 3 | 4 | scriptversion=2009-04-28.21; # UTC 5 | 6 | # Original author: Noah Friedman 7 | # Created: 1993-05-16 8 | # Public domain. 9 | # 10 | # This file is maintained in Automake, please report 11 | # bugs to or send patches to 12 | # . 13 | 14 | nl=' 15 | ' 16 | IFS=" "" $nl" 17 | errstatus=0 18 | dirmode= 19 | 20 | usage="\ 21 | Usage: mkinstalldirs [-h] [--help] [--version] [-m MODE] DIR ... 22 | 23 | Create each directory DIR (with mode MODE, if specified), including all 24 | leading file name components. 25 | 26 | Report bugs to ." 27 | 28 | # process command line arguments 29 | while test $# -gt 0 ; do 30 | case $1 in 31 | -h | --help | --h*) # -h for help 32 | echo "$usage" 33 | exit $? 34 | ;; 35 | -m) # -m PERM arg 36 | shift 37 | test $# -eq 0 && { echo "$usage" 1>&2; exit 1; } 38 | dirmode=$1 39 | shift 40 | ;; 41 | --version) 42 | echo "$0 $scriptversion" 43 | exit $? 44 | ;; 45 | --) # stop option processing 46 | shift 47 | break 48 | ;; 49 | -*) # unknown option 50 | echo "$usage" 1>&2 51 | exit 1 52 | ;; 53 | *) # first non-opt arg 54 | break 55 | ;; 56 | esac 57 | done 58 | 59 | for file 60 | do 61 | if test -d "$file"; then 62 | shift 63 | else 64 | break 65 | fi 66 | done 67 | 68 | case $# in 69 | 0) exit 0 ;; 70 | esac 71 | 72 | # Solaris 8's mkdir -p isn't thread-safe. If you mkdir -p a/b and 73 | # mkdir -p a/c at the same time, both will detect that a is missing, 74 | # one will create a, then the other will try to create a and die with 75 | # a "File exists" error. This is a problem when calling mkinstalldirs 76 | # from a parallel make. We use --version in the probe to restrict 77 | # ourselves to GNU mkdir, which is thread-safe. 78 | case $dirmode in 79 | '') 80 | if mkdir -p --version . >/dev/null 2>&1 && test ! -d ./--version; then 81 | echo "mkdir -p -- $*" 82 | exec mkdir -p -- "$@" 83 | else 84 | # On NextStep and OpenStep, the 'mkdir' command does not 85 | # recognize any option. It will interpret all options as 86 | # directories to create, and then abort because '.' already 87 | # exists. 88 | test -d ./-p && rmdir ./-p 89 | test -d ./--version && rmdir ./--version 90 | fi 91 | ;; 92 | *) 93 | if mkdir -m "$dirmode" -p --version . >/dev/null 2>&1 && 94 | test ! -d ./--version; then 95 | echo "mkdir -m $dirmode -p -- $*" 96 | exec mkdir -m "$dirmode" -p -- "$@" 97 | else 98 | # Clean up after NextStep and OpenStep mkdir. 99 | for d in ./-m ./-p ./--version "./$dirmode"; 100 | do 101 | test -d $d && rmdir $d 102 | done 103 | fi 104 | ;; 105 | esac 106 | 107 | for file 108 | do 109 | case $file in 110 | /*) pathcomp=/ ;; 111 | *) pathcomp= ;; 112 | esac 113 | oIFS=$IFS 114 | IFS=/ 115 | set fnord $file 116 | shift 117 | IFS=$oIFS 118 | 119 | for d 120 | do 121 | test "x$d" = x && continue 122 | 123 | pathcomp=$pathcomp$d 124 | case $pathcomp in 125 | -*) pathcomp=./$pathcomp ;; 126 | esac 127 | 128 | if test ! -d "$pathcomp"; then 129 | echo "mkdir $pathcomp" 130 | 131 | mkdir "$pathcomp" || lasterr=$? 132 | 133 | if test ! -d "$pathcomp"; then 134 | errstatus=$lasterr 135 | else 136 | if test ! -z "$dirmode"; then 137 | echo "chmod $dirmode $pathcomp" 138 | lasterr= 139 | chmod "$dirmode" "$pathcomp" || lasterr=$? 140 | 141 | if test ! -z "$lasterr"; then 142 | errstatus=$lasterr 143 | fi 144 | fi 145 | fi 146 | fi 147 | 148 | pathcomp=$pathcomp/ 149 | done 150 | done 151 | 152 | exit $errstatus 153 | 154 | # Local Variables: 155 | # mode: shell-script 156 | # sh-indentation: 2 157 | # eval: (add-hook 'write-file-hooks 'time-stamp) 158 | # time-stamp-start: "scriptversion=" 159 | # time-stamp-format: "%:y-%02m-%02d.%02H" 160 | # time-stamp-time-zone: "UTC" 161 | # time-stamp-end: "; # UTC" 162 | # End: 163 | -------------------------------------------------------------------------------- /cmake/config.h.cmake: -------------------------------------------------------------------------------- 1 | /* libev config.h start */ 2 | 3 | 4 | /* config.h : Generated from config.h.cmake.in in CMakeLists.txt by cmake. */ 5 | 6 | /* Define to 1 if you have the `clock_gettime' function. */ 7 | #cmakedefine HAVE_CLOCK_GETTIME 1 8 | 9 | /* Define to 1 to use the syscall interface for clock_gettime */ 10 | #cmakedefine HAVE_CLOCK_SYSCALL 1 11 | 12 | /* Define to 1 if you have the header file. */ 13 | #cmakedefine HAVE_DLFCN_H 1 14 | 15 | /* Define to 1 if you have the `epoll_ctl' function. */ 16 | #cmakedefine HAVE_EPOLL_CTL 1 17 | 18 | /* Define to 1 if you have the `eventfd' function. */ 19 | #cmakedefine HAVE_EVENTFD 1 20 | 21 | /* Define to 1 if the floor function is available */ 22 | #cmakedefine HAVE_FLOOR 1 23 | 24 | /* Define to 1 if you have the `inotify_init' function. */ 25 | #cmakedefine HAVE_INOTIFY_INIT 1 26 | 27 | /* Define to 1 if you have the header file. */ 28 | #cmakedefine HAVE_INTTYPES_H 1 29 | 30 | /* Define to 1 if you have the `kqueue' function. */ 31 | #cmakedefine HAVE_KQUEUE 1 32 | 33 | /* Define to 1 if you have the `rt' library (-lrt). */ 34 | #cmakedefine HAVE_LIBRT 1 35 | 36 | /* Define to 1 if you have the header file. */ 37 | #cmakedefine HAVE_MEMORY_H 1 38 | 39 | /* Define to 1 if you have the `nanosleep' function. */ 40 | #cmakedefine HAVE_NANOSLEEP 1 41 | 42 | /* Define to 1 if you have the `poll' function. */ 43 | #cmakedefine HAVE_POLL 1 44 | 45 | /* Define to 1 if you have the header file. */ 46 | #cmakedefine HAVE_POLL_H 1 47 | 48 | /* Define to 1 if you have the `port_create' function. */ 49 | #cmakedefine HAVE_PORT_CREATE 1 50 | 51 | /* Define to 1 if you have the header file. */ 52 | #cmakedefine HAVE_PORT_H 1 53 | 54 | /* Define to 1 if you have the `select' function. */ 55 | #cmakedefine HAVE_SELECT 1 56 | 57 | /* Define to 1 if you have the header. */ 58 | #cmakedefine HAVE_WINSOCK_H 1 59 | 60 | /* Define to 1 if you have the `signalfd' function. */ 61 | #cmakedefine HAVE_SIGNALFD 1 62 | 63 | /* Define to 1 if you have the header file. */ 64 | #cmakedefine HAVE_STDINT_H 1 65 | 66 | /* Define to 1 if you have the header file. */ 67 | #cmakedefine HAVE_STDLIB_H 1 68 | 69 | /* Define to 1 if you have the header file. */ 70 | #cmakedefine HAVE_STRINGS_H 1 71 | 72 | /* Define to 1 if you have the header file. */ 73 | #cmakedefine HAVE_STRING_H 1 74 | 75 | /* Define to 1 if you have the header file. */ 76 | #cmakedefine HAVE_SYS_EPOLL_H 1 77 | 78 | /* Define to 1 if you have the header file. */ 79 | #cmakedefine HAVE_SYS_EVENTFD_H 1 80 | 81 | /* Define to 1 if you have the header file. */ 82 | #cmakedefine HAVE_SYS_EVENT_H 1 83 | 84 | /* Define to 1 if you have the header file. */ 85 | #cmakedefine HAVE_SYS_INOTIFY_H 1 86 | 87 | /* Define to 1 if you have the header file. */ 88 | #cmakedefine HAVE_SYS_SELECT_H 1 89 | 90 | /* Define to 1 if you have the header file. */ 91 | #cmakedefine HAVE_SYS_SIGNALFD_H 1 92 | 93 | /* Define to 1 if you have the header file. */ 94 | #cmakedefine HAVE_SYS_STAT_H 1 95 | 96 | /* Define to 1 if you have the header file. */ 97 | #cmakedefine HAVE_SYS_TYPES_H 1 98 | 99 | /* Define to 1 if you have the header file. */ 100 | #cmakedefine HAVE_UNISTD_H 1 101 | 102 | /* Define to the sub-directory in which libtool stores uninstalled libraries. 103 | */ 104 | #define LT_OBJDIR "@libtool_objdir@" 105 | 106 | /* Name of package */ 107 | #define PACKAGE "@package_name@" 108 | 109 | /* Define to the address where bug reports for this package should be sent. */ 110 | #define PACKAGE_BUGREPORT "@package_bugreport@" 111 | 112 | /* Define to the full name of this package. */ 113 | #define PACKAGE_NAME "" 114 | 115 | /* Define to the full name and version of this package. */ 116 | #define PACKAGE_STRING "" 117 | 118 | /* Define to the one symbol short name of this package. */ 119 | #define PACKAGE_TARNAME "" 120 | 121 | /* Define to the home page for this package. */ 122 | #define PACKAGE_URL "" 123 | 124 | /* Define to the version of this package. */ 125 | #define PACKAGE_VERSION "" 126 | 127 | /* Define to 1 if you have the ANSI C header files. */ 128 | #cmakedefine STDC_HEADERS 1 129 | 130 | /* Version number of package */ 131 | #define VERSION "@version_major@.@version_minor@" 132 | 133 | 134 | /* libev config.h end */ 135 | 136 | 137 | 138 | 139 | /* libyaml config.h start */ 140 | #define YAML_VERSION_MAJOR @YAML_VERSION_MAJOR@ 141 | #define YAML_VERSION_MINOR @YAML_VERSION_MINOR@ 142 | #define YAML_VERSION_PATCH @YAML_VERSION_PATCH@ 143 | #define YAML_VERSION_STRING "@YAML_VERSION_STRING@" 144 | /* libyaml config.h end */ 145 | -------------------------------------------------------------------------------- /src/socks5.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "socks5.h" 3 | 4 | int32_t socks5_sockset(int sockfd) { 5 | struct timeval tmo = {0}; 6 | int opt = 1; 7 | 8 | tmo.tv_sec = 2; 9 | tmo.tv_usec = 0; 10 | if (-1 == setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, (char *) &tmo, sizeof(tmo)) || 11 | -1 == setsockopt(sockfd, SOL_SOCKET, SO_SNDTIMEO, (char *) &tmo, sizeof(tmo))) { 12 | printf("setsockopt error.\n"); 13 | return -1; 14 | } 15 | 16 | #ifdef SO_NOSIGPIPE 17 | setsockopt(sockfd, SOL_SOCKET, SO_NOSIGPIPE, &opt, sizeof(opt)); 18 | #endif 19 | 20 | if (-1 == setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (uint *) &opt, sizeof(opt))) { 21 | printf("setsockopt SO_REUSEADDR fail.\n"); 22 | return -1; 23 | } 24 | 25 | return 0; 26 | } 27 | 28 | int socks5_connect(const char *proxy_host, const char *proxy_port) { 29 | int socks_fd = 0; 30 | struct sockaddr_in socks_proxy_addr; 31 | 32 | socks_proxy_addr.sin_family = AF_INET; 33 | socks_proxy_addr.sin_addr.s_addr = inet_addr(proxy_host); 34 | socks_proxy_addr.sin_port = htons(atoi(proxy_port)); 35 | 36 | if ((socks_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { 37 | printf("socket failed\n"); 38 | return -1; 39 | } 40 | // setnonblocking(socks_fd); 41 | socks5_sockset(socks_fd); 42 | if (0 > connect(socks_fd, (struct sockaddr *) &socks_proxy_addr, sizeof(socks_proxy_addr))) { 43 | printf("connect failed\n"); 44 | return -1; 45 | } 46 | 47 | return socks_fd; 48 | } 49 | 50 | int socks5_auth(int sockfd, const char *server_host, const char *server_port, u_char cmd, int atype) { 51 | char buff[BUFFER_SIZE]; 52 | /** 53 | * socks 5 method request start 54 | */ 55 | ((socks5_method_req_t *) buff)->ver = SOCKS5_VERSION; 56 | ((socks5_method_req_t *) buff)->nmethods = 0x01; 57 | ((socks5_method_req_t *) buff)->methods[0] = 0x00; 58 | 59 | send(sockfd, buff, 3, 0); 60 | 61 | // VERSION and METHODS 62 | if (-1 == recv(sockfd, buff, 2, 0)) { 63 | printf("recv VERSION and METHODS error\n"); 64 | return -1; 65 | }; 66 | if (SOCKS5_VERSION != ((socks5_method_res_t *) buff)->ver || 0x00 != ((socks5_method_res_t *) buff)->method) { 67 | printf("socks5_method_res_t error\n"); 68 | return -1; 69 | } 70 | /** 71 | * socks 5 method request end 72 | */ 73 | 74 | /** 75 | * socks 5 request start 76 | */ 77 | if (atype == 1) { 78 | unsigned char socksreq[600]; 79 | int idx; 80 | 81 | idx = 0; 82 | socksreq[idx++] = 5; /* version */ 83 | socksreq[idx++] = cmd; 84 | socksreq[idx++] = 0; 85 | socksreq[idx++] = 1; /* ATYP: IPv4 = 1 */ 86 | 87 | struct sockaddr_in *saddr_in = (struct sockaddr_in *) malloc(sizeof(struct sockaddr_in));; 88 | saddr_in->sin_family = AF_INET; 89 | inet_aton(server_host, &(saddr_in->sin_addr)); 90 | for (int i = 0; i < 4; i++) { 91 | socksreq[idx++] = ((unsigned char *) &saddr_in->sin_addr.s_addr)[i]; 92 | } 93 | 94 | int p = atoi(server_port); 95 | socksreq[idx++] = (unsigned char) ((p >> 8) & 0xff); /* PORT MSB */ 96 | socksreq[idx++] = (unsigned char) (p & 0xff); /* PORT LSB */ 97 | 98 | send(sockfd, (char *) socksreq, idx, 0); 99 | free(saddr_in); 100 | } else if (atype == 3) { 101 | char *buffer, *temp; 102 | u_char v = 0x05, rsv = 0x00, atyp = 0x03; 103 | 104 | const char host_len = (char) strlen(server_host); 105 | uint16_t port = htons(atoi(server_port)); 106 | buffer = static_cast(malloc(strlen(server_host) + 7)); 107 | temp = buffer; 108 | /* Assemble the request packet */ 109 | (void) memcpy(temp, &v, sizeof(v)); 110 | temp += sizeof(v); 111 | (void) memcpy(temp, &cmd, sizeof(cmd)); 112 | temp += sizeof(cmd); 113 | (void) memcpy(temp, &rsv, sizeof(rsv)); 114 | temp += sizeof(rsv); 115 | (void) memcpy(temp, &atyp, sizeof(atyp)); 116 | temp += sizeof(atyp); 117 | (void) memcpy(temp, &host_len, sizeof(host_len)); 118 | temp += sizeof(host_len); 119 | (void) memcpy(temp, server_host, strlen(server_host)); 120 | temp += strlen(server_host); 121 | (void) memcpy(temp, &port, sizeof(&port)); 122 | temp += sizeof(&port); 123 | send(sockfd, buffer, temp - buffer, 0); 124 | free(buffer); 125 | } else if (atype == 4) { 126 | // ipv6 TODO 127 | } 128 | /** 129 | * socks 5 request end 130 | */ 131 | 132 | /** 133 | * socks 5 response 134 | */ 135 | if (-1 == recv(sockfd, buff, 10, 0)) { 136 | printf("recv socks 5 response error\n"); 137 | return -1; 138 | }; 139 | 140 | if (SOCKS5_VERSION != ((socks5_response_t *) buff)->ver) { 141 | printf("socks 5 response version error\n"); 142 | return -1; 143 | } 144 | 145 | return 0; 146 | } 147 | -------------------------------------------------------------------------------- /scripts/custom_domain_server.conf: -------------------------------------------------------------------------------- 1 | domain_suffix=/archlinuxcn.org/114.114.114.114 2 | domain_suffix=/lipuwater.com/114.114.114.114 3 | domain_suffix=/tower.im/114.114.114.114 4 | domain_suffix=/qq.com/114.114.114.114 5 | domain_suffix=/sogou.com/114.114.114.114 6 | domain_suffix=/archlinux.org/114.114.114.114 7 | domain_suffix=/ruby-china.org/114.114.114.114 8 | domain_suffix=/igexin.com/114.114.114.114 9 | domain_suffix=/gepush.com/114.114.114.114 10 | domain_suffix=/getui.net/114.114.114.114 11 | domain_suffix=/weibo.com/114.114.114.114 12 | domain_suffix=/mi.com/114.114.114.114 13 | domain_suffix=/duokan.com/114.114.114.114 14 | domain_suffix=/miwifi.com/114.114.114.114 15 | domain_suffix=/miliao.com/114.114.114.114 16 | domain_suffix=/viglink.com/114.114.114.114 17 | domain_suffix=/importnew.com/114.114.114.114 18 | domain_suffix=/jiathis.com/114.114.114.114 19 | domain_suffix=/renren.com/114.114.114.114 20 | domain_suffix=/so.com/114.114.114.114 21 | domain_suffix=/jd.com/114.114.114.114 22 | domain_suffix=/kuaidi100.com/114.114.114.114 23 | domain_suffix=/upaiyun.com/114.114.114.114 24 | domain_suffix=/pstatp.com/114.114.114.114 25 | domain_suffix=/ipip.net/114.114.114.114 26 | domain_suffix=/segmentfault.com/114.114.114.114 27 | domain_suffix=/zaih.com/114.114.114.114 28 | domain_suffix=/eolinker.com/114.114.114.114 29 | domain_suffix=/growingio.com/114.114.114.114 30 | domain_suffix=/bintray.com/114.114.114.114 31 | domain_suffix=/apple.com/114.114.114.114 32 | domain_suffix=/gradle.org/114.114.114.114 33 | domain_suffix=/thecampus.cc/114.114.114.114 34 | domain_suffix=/live.com/114.114.114.114 35 | domain_suffix=/.cn/114.114.114.114 36 | domain_suffix=/.asia/114.114.114.114 37 | domain_suffix=/cli.im/114.114.114.114 38 | domain_suffix=/intercom.io/114.114.114.114 39 | domain_suffix=/liveneeq.com/114.114.114.114 40 | domain_suffix=/geetest.com/114.114.114.114 41 | domain_suffix=/fastapi.net/114.114.114.114 42 | domain_suffix=/wenjuan.com/114.114.114.114 43 | domain_suffix=/qhimg.com/114.114.114.114 44 | domain_suffix=/qhmsg.com/114.114.114.114 45 | domain_keyword=/china/114.114.114.114 46 | domain_keyword=/126/114.114.114.114 47 | domain_keyword=/163/114.114.114.114 48 | domain_keyword=/360/114.114.114.114 49 | domain_keyword=/58/114.114.114.114 50 | domain_keyword=/sina/114.114.114.114 51 | domain_keyword=/ifeng/114.114.114.114 52 | domain_keyword=/ganji/114.114.114.114 53 | domain_keyword=/tuniu/114.114.114.114 54 | domain_keyword=/dianping/114.114.114.114 55 | domain_keyword=/cctv/114.114.114.114 56 | domain_keyword=/fang/114.114.114.114 57 | domain_keyword=/qcloud/114.114.114.114 58 | domain_keyword=/lagou/114.114.114.114 59 | domain_keyword=/jianshu/114.114.114.114 60 | domain_keyword=/cnzz/114.114.114.114 61 | domain_keyword=/v2ex/114.114.114.114 62 | domain_keyword=/iteye/114.114.114.114 63 | domain_keyword=/jobbole/114.114.114.114 64 | domain_keyword=/cnblogs/114.114.114.114 65 | domain_keyword=/duoshuo/114.114.114.114 66 | domain_keyword=/douban/114.114.114.114 67 | domain_keyword=/tudou/114.114.114.114 68 | domain_keyword=/douyu/114.114.114.114 69 | domain_keyword=/mediav/114.114.114.114 70 | domain_keyword=/wukong/114.114.114.114 71 | domain_keyword=/xiaomi/114.114.114.114 72 | domain_keyword=/youku/114.114.114.114 73 | domain_keyword=/ykimg/114.114.114.114 74 | domain_keyword=/soku/114.114.114.114 75 | domain_keyword=/zhihu/114.114.114.114 76 | domain_keyword=/iqiyi/114.114.114.114 77 | domain_keyword=/wenwen/114.114.114.114 78 | domain_keyword=/qlogo/114.114.114.114 79 | domain_keyword=/toutiao/114.114.114.114 80 | domain_keyword=/sohu/114.114.114.114 81 | domain_keyword=/csdn/114.114.114.114 82 | domain_keyword=/oschina/114.114.114.114 83 | domain_keyword=/bdstatic/114.114.114.114 84 | domain_keyword=/baidu/114.114.114.114 85 | domain_keyword=/bdimg/114.114.114.114 86 | domain_keyword=/nginx/114.114.114.114 87 | domain_keyword=/apple-dns/114.114.114.114 88 | domain_keyword=/akadns/114.114.114.114 89 | domain_keyword=/aicdn/114.114.114.114 90 | domain_keyword=/yahooapis/114.114.114.114 91 | domain_keyword=/bootcss/114.114.114.114 92 | domain_keyword=/youdao/114.114.114.114 93 | domain_keyword=/ydstatic/114.114.114.114 94 | domain_keyword=/xunlei/114.114.114.114 95 | domain_keyword=/thunder/114.114.114.114 96 | domain_keyword=/mtime/114.114.114.114 97 | domain_keyword=/cndns/114.114.114.114 98 | domain_keyword=/anquan/114.114.114.114 99 | domain_keyword=/miui/114.114.114.114 100 | domain_keyword=/amap/114.114.114.114 101 | domain_keyword=/apache/114.114.114.114 102 | domain_keyword=/segment/114.114.114.114 103 | domain_keyword=/postman/114.114.114.114 104 | domain_keyword=/meiqia/114.114.114.114 105 | domain_keyword=/datatables/114.114.114.114 106 | domain_keyword=/clouddn/114.114.114.114 107 | domain_keyword=/jsbin/114.114.114.114 108 | domain_keyword=/aliyun/223.5.5.5 109 | domain_keyword=/alicdn/223.5.5.5 110 | domain_keyword=/alipay/223.5.5.5 111 | domain_keyword=/taobao/223.5.5.5 112 | domain_keyword=/tmall/223.5.5.5 113 | domain_keyword=/mmstat/223.5.5.5 114 | domain_keyword=/sanguosha/223.5.5.5 115 | domain_keyword=/aliapp/223.5.5.5 116 | domain_keyword=/alibaba/223.5.5.5 117 | domain_keyword=/alibabadns/223.5.5.5 118 | -------------------------------------------------------------------------------- /libev/ev_poll.c: -------------------------------------------------------------------------------- 1 | /* 2 | * libev poll fd activity backend 3 | * 4 | * Copyright (c) 2007,2008,2009,2010,2011 Marc Alexander Lehmann 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without modifica- 8 | * tion, are permitted provided that the following conditions are met: 9 | * 10 | * 1. Redistributions of source code must retain the above copyright notice, 11 | * this list of conditions and the following disclaimer. 12 | * 13 | * 2. Redistributions in binary form must reproduce the above copyright 14 | * notice, this list of conditions and the following disclaimer in the 15 | * documentation and/or other materials provided with the distribution. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 18 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MER- 19 | * CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 20 | * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPE- 21 | * CIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 22 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 23 | * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 24 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTH- 25 | * ERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 26 | * OF THE POSSIBILITY OF SUCH DAMAGE. 27 | * 28 | * Alternatively, the contents of this file may be used under the terms of 29 | * the GNU General Public License ("GPL") version 2 or any later version, 30 | * in which case the provisions of the GPL are applicable instead of 31 | * the above. If you wish to allow the use of your version of this file 32 | * only under the terms of the GPL and not to allow others to use your 33 | * version of this file under the BSD license, indicate your decision 34 | * by deleting the provisions above and replace them with the notice 35 | * and other provisions required by the GPL. If you do not delete the 36 | * provisions above, a recipient may use your version of this file under 37 | * either the BSD or the GPL. 38 | */ 39 | 40 | #include 41 | 42 | inline_size 43 | void 44 | pollidx_init (int *base, int count) 45 | { 46 | /* consider using memset (.., -1, ...), which is practically guaranteed 47 | * to work on all systems implementing poll */ 48 | while (count--) 49 | *base++ = -1; 50 | } 51 | 52 | static void 53 | poll_modify (EV_P_ int fd, int oev, int nev) 54 | { 55 | int idx; 56 | 57 | if (oev == nev) 58 | return; 59 | 60 | array_needsize (int, pollidxs, pollidxmax, fd + 1, pollidx_init); 61 | 62 | idx = pollidxs [fd]; 63 | 64 | if (idx < 0) /* need to allocate a new pollfd */ 65 | { 66 | pollidxs [fd] = idx = pollcnt++; 67 | array_needsize (struct pollfd, polls, pollmax, pollcnt, EMPTY2); 68 | polls [idx].fd = fd; 69 | } 70 | 71 | assert (polls [idx].fd == fd); 72 | 73 | if (nev) 74 | polls [idx].events = 75 | (nev & EV_READ ? POLLIN : 0) 76 | | (nev & EV_WRITE ? POLLOUT : 0); 77 | else /* remove pollfd */ 78 | { 79 | pollidxs [fd] = -1; 80 | 81 | if (expect_true (idx < --pollcnt)) 82 | { 83 | polls [idx] = polls [pollcnt]; 84 | pollidxs [polls [idx].fd] = idx; 85 | } 86 | } 87 | } 88 | 89 | static void 90 | poll_poll (EV_P_ ev_tstamp timeout) 91 | { 92 | struct pollfd *p; 93 | int res; 94 | 95 | EV_RELEASE_CB; 96 | res = poll (polls, pollcnt, timeout * 1e3); 97 | EV_ACQUIRE_CB; 98 | 99 | if (expect_false (res < 0)) 100 | { 101 | if (errno == EBADF) 102 | fd_ebadf (EV_A); 103 | else if (errno == ENOMEM && !syserr_cb) 104 | fd_enomem (EV_A); 105 | else if (errno != EINTR) 106 | ev_syserr ("(libev) poll"); 107 | } 108 | else 109 | for (p = polls; res; ++p) 110 | { 111 | assert (("libev: poll() returned illegal result, broken BSD kernel?", p < polls + pollcnt)); 112 | 113 | if (expect_false (p->revents)) /* this expect is debatable */ 114 | { 115 | --res; 116 | 117 | if (expect_false (p->revents & POLLNVAL)) 118 | fd_kill (EV_A_ p->fd); 119 | else 120 | fd_event ( 121 | EV_A_ 122 | p->fd, 123 | (p->revents & (POLLOUT | POLLERR | POLLHUP) ? EV_WRITE : 0) 124 | | (p->revents & (POLLIN | POLLERR | POLLHUP) ? EV_READ : 0) 125 | ); 126 | } 127 | } 128 | } 129 | 130 | inline_size 131 | int 132 | poll_init (EV_P_ int flags) 133 | { 134 | backend_mintime = 1e-3; 135 | backend_modify = poll_modify; 136 | backend_poll = poll_poll; 137 | 138 | pollidxs = 0; pollidxmax = 0; 139 | polls = 0; pollmax = 0; pollcnt = 0; 140 | 141 | return EVBACKEND_POLL; 142 | } 143 | 144 | inline_size 145 | void 146 | poll_destroy (EV_P) 147 | { 148 | ev_free (pollidxs); 149 | ev_free (polls); 150 | } 151 | 152 | -------------------------------------------------------------------------------- /cmake/liblwip.cmake: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8) 2 | project(lwip C) 3 | 4 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu99 -g -Wall -DLWIP_DEBUG") 5 | 6 | set(LWIPDIR lwip/src) 7 | set(LWIPARCH lwip-contrib/ports/unix/port) 8 | 9 | 10 | include_directories( 11 | ${LWIPDIR}/include 12 | ${LWIPARCH}/include 13 | ) 14 | 15 | set(LWIP_SOURCE_FILES 16 | # COREFILES 17 | ${LWIPDIR}/core/init.c 18 | ${LWIPDIR}/core/def.c 19 | ${LWIPDIR}/core/dns.c 20 | ${LWIPDIR}/core/inet_chksum.c 21 | ${LWIPDIR}/core/ip.c 22 | ${LWIPDIR}/core/mem.c 23 | ${LWIPDIR}/core/memp.c 24 | ${LWIPDIR}/core/netif.c 25 | ${LWIPDIR}/core/pbuf.c 26 | ${LWIPDIR}/core/raw.c 27 | ${LWIPDIR}/core/stats.c 28 | ${LWIPDIR}/core/sys.c 29 | ${LWIPDIR}/core/tcp.c 30 | ${LWIPDIR}/core/tcp_in.c 31 | ${LWIPDIR}/core/tcp_out.c 32 | ${LWIPDIR}/core/timeouts.c 33 | ${LWIPDIR}/core/udp.c 34 | 35 | 36 | # CORE4FILES 37 | ${LWIPDIR}/core/ipv4/autoip.c 38 | ${LWIPDIR}/core/ipv4/dhcp.c 39 | ${LWIPDIR}/core/ipv4/etharp.c 40 | ${LWIPDIR}/core/ipv4/icmp.c 41 | ${LWIPDIR}/core/ipv4/igmp.c 42 | ${LWIPDIR}/core/ipv4/ip4_frag.c 43 | ${LWIPDIR}/core/ipv4/ip4.c 44 | ${LWIPDIR}/core/ipv4/ip4_addr.c 45 | 46 | 47 | # CORE6FILES 48 | ${LWIPDIR}/core/ipv6/dhcp6.c 49 | ${LWIPDIR}/core/ipv6/ethip6.c 50 | ${LWIPDIR}/core/ipv6/icmp6.c 51 | ${LWIPDIR}/core/ipv6/inet6.c 52 | ${LWIPDIR}/core/ipv6/ip6.c 53 | ${LWIPDIR}/core/ipv6/ip6_addr.c 54 | ${LWIPDIR}/core/ipv6/ip6_frag.c 55 | ${LWIPDIR}/core/ipv6/mld6.c 56 | ${LWIPDIR}/core/ipv6/nd6.c 57 | 58 | 59 | # APIFILES: The files which implement the sequential and socket APIs. 60 | ${LWIPDIR}/api/api_lib.c 61 | ${LWIPDIR}/api/api_msg.c 62 | ${LWIPDIR}/api/err.c 63 | ${LWIPDIR}/api/netbuf.c 64 | ${LWIPDIR}/api/netdb.c 65 | ${LWIPDIR}/api/netifapi.c 66 | ${LWIPDIR}/api/sockets.c 67 | ${LWIPDIR}/api/tcpip.c 68 | 69 | 70 | # NETIFFILES: Files implementing various generic network interface functions 71 | ${LWIPDIR}/netif/ethernet.c 72 | # ${LWIPDIR}/netif/slipif.c # OSX compile will be break 73 | 74 | 75 | # SIXLOWPAN: 6LoWPAN 76 | ${LWIPDIR}/netif/lowpan6.c 77 | 78 | 79 | # PPPFILES: PPP 80 | # ${LWIPDIR}/netif/ppp/auth.c 81 | # ${LWIPDIR}/netif/ppp/ccp.c 82 | # ${LWIPDIR}/netif/ppp/chap-md5.c 83 | # ${LWIPDIR}/netif/ppp/chap_ms.c 84 | # ${LWIPDIR}/netif/ppp/chap-new.c 85 | # ${LWIPDIR}/netif/ppp/demand.c 86 | # ${LWIPDIR}/netif/ppp/eap.c 87 | # ${LWIPDIR}/netif/ppp/ecp.c 88 | # ${LWIPDIR}/netif/ppp/eui64.c 89 | # ${LWIPDIR}/netif/ppp/fsm.c 90 | # ${LWIPDIR}/netif/ppp/ipcp.c 91 | # ${LWIPDIR}/netif/ppp/ipv6cp.c 92 | # ${LWIPDIR}/netif/ppp/lcp.c 93 | # ${LWIPDIR}/netif/ppp/magic.c 94 | # ${LWIPDIR}/netif/ppp/mppe.c 95 | # ${LWIPDIR}/netif/ppp/multilink.c 96 | # ${LWIPDIR}/netif/ppp/ppp.c 97 | # ${LWIPDIR}/netif/ppp/pppapi.c 98 | # ${LWIPDIR}/netif/ppp/pppcrypt.c 99 | # ${LWIPDIR}/netif/ppp/pppoe.c 100 | # ${LWIPDIR}/netif/ppp/pppol2tp.c 101 | # ${LWIPDIR}/netif/ppp/pppos.c 102 | # ${LWIPDIR}/netif/ppp/upap.c 103 | # ${LWIPDIR}/netif/ppp/utils.c 104 | # ${LWIPDIR}/netif/ppp/vj.c 105 | # ${LWIPDIR}/netif/ppp/polarssl/arc4.c 106 | # ${LWIPDIR}/netif/ppp/polarssl/des.c 107 | # ${LWIPDIR}/netif/ppp/polarssl/md4.c 108 | # ${LWIPDIR}/netif/ppp/polarssl/md5.c 109 | # ${LWIPDIR}/netif/ppp/polarssl/sha1.c 110 | 111 | 112 | # SNMPFILES: SNMPv2c agent 113 | # ${LWIPDIR}/apps/snmp/snmp_asn1.c 114 | # ${LWIPDIR}/apps/snmp/snmp_core.c 115 | # ${LWIPDIR}/apps/snmp/snmp_mib2.c 116 | # ${LWIPDIR}/apps/snmp/snmp_mib2_icmp.c 117 | # ${LWIPDIR}/apps/snmp/snmp_mib2_interfaces.c 118 | # ${LWIPDIR}/apps/snmp/snmp_mib2_ip.c 119 | # ${LWIPDIR}/apps/snmp/snmp_mib2_snmp.c 120 | # ${LWIPDIR}/apps/snmp/snmp_mib2_system.c 121 | # ${LWIPDIR}/apps/snmp/snmp_mib2_tcp.c 122 | # ${LWIPDIR}/apps/snmp/snmp_mib2_udp.c 123 | # ${LWIPDIR}/apps/snmp/snmp_msg.c 124 | # ${LWIPDIR}/apps/snmp/snmpv3.c 125 | # ${LWIPDIR}/apps/snmp/snmp_netconn.c 126 | # ${LWIPDIR}/apps/snmp/snmp_pbuf_stream.c 127 | # ${LWIPDIR}/apps/snmp/snmp_raw.c 128 | # ${LWIPDIR}/apps/snmp/snmp_scalar.c 129 | # ${LWIPDIR}/apps/snmp/snmp_table.c 130 | # ${LWIPDIR}/apps/snmp/snmp_threadsync.c 131 | # ${LWIPDIR}/apps/snmp/snmp_traps.c 132 | # ${LWIPDIR}/apps/snmp/snmpv3_mbedtls.c 133 | # ${LWIPDIR}/apps/snmp/snmpv3_dummy.c 134 | 135 | 136 | # # HTTPDFILES: HTTP server 137 | # ${LWIPDIR}/apps/httpd/fs.c 138 | # ${LWIPDIR}/apps/httpd/httpd.c 139 | # 140 | # 141 | # # LWIPERFFILES: IPERF server 142 | # ${LWIPDIR}/apps/lwiperf/lwiperf.c 143 | # 144 | # 145 | # # SNTPFILES: SNTP client 146 | # ${LWIPDIR}/apps/sntp/sntp.c 147 | # 148 | # 149 | # # MDNSFILES: MDNS responder 150 | # ${LWIPDIR}/apps/mdns/mdns.c 151 | # 152 | # 153 | # # NETBIOSNSFILES: NetBIOS name server 154 | # ${LWIPDIR}/apps/netbiosns/netbiosns.c 155 | # 156 | # 157 | # # TFTPFILES: TFTP server files 158 | # ${LWIPDIR}/apps/tftp/tftp_server.c 159 | # 160 | # 161 | # # MQTTFILES: MQTT client files 162 | # ${LWIPDIR}/apps/mqtt/mqtt.c 163 | 164 | 165 | # patch files 166 | ${LWIPARCH}/perf.c 167 | ${LWIPARCH}/sys_arch.c 168 | ) 169 | -------------------------------------------------------------------------------- /libev/ev_win32.c: -------------------------------------------------------------------------------- 1 | /* 2 | * libev win32 compatibility cruft (_not_ a backend) 3 | * 4 | * Copyright (c) 2007,2008,2009 Marc Alexander Lehmann 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without modifica- 8 | * tion, are permitted provided that the following conditions are met: 9 | * 10 | * 1. Redistributions of source code must retain the above copyright notice, 11 | * this list of conditions and the following disclaimer. 12 | * 13 | * 2. Redistributions in binary form must reproduce the above copyright 14 | * notice, this list of conditions and the following disclaimer in the 15 | * documentation and/or other materials provided with the distribution. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 18 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MER- 19 | * CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 20 | * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPE- 21 | * CIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 22 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 23 | * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 24 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTH- 25 | * ERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 26 | * OF THE POSSIBILITY OF SUCH DAMAGE. 27 | * 28 | * Alternatively, the contents of this file may be used under the terms of 29 | * the GNU General Public License ("GPL") version 2 or any later version, 30 | * in which case the provisions of the GPL are applicable instead of 31 | * the above. If you wish to allow the use of your version of this file 32 | * only under the terms of the GPL and not to allow others to use your 33 | * version of this file under the BSD license, indicate your decision 34 | * by deleting the provisions above and replace them with the notice 35 | * and other provisions required by the GPL. If you do not delete the 36 | * provisions above, a recipient may use your version of this file under 37 | * either the BSD or the GPL. 38 | */ 39 | 40 | #ifdef _WIN32 41 | 42 | /* note: the comment below could not be substantiated, but what would I care */ 43 | /* MSDN says this is required to handle SIGFPE */ 44 | /* my wild guess would be that using something floating-pointy is required */ 45 | /* for the crt to do something about it */ 46 | volatile double SIGFPE_REQ = 0.0f; 47 | 48 | static SOCKET 49 | ev_tcp_socket (void) 50 | { 51 | #if EV_USE_WSASOCKET 52 | return WSASocket (AF_INET, SOCK_STREAM, 0, 0, 0, 0); 53 | #else 54 | return socket (AF_INET, SOCK_STREAM, 0); 55 | #endif 56 | } 57 | 58 | /* oh, the humanity! */ 59 | static int 60 | ev_pipe (int filedes [2]) 61 | { 62 | struct sockaddr_in addr = { 0 }; 63 | int addr_size = sizeof (addr); 64 | struct sockaddr_in adr2; 65 | int adr2_size = sizeof (adr2); 66 | SOCKET listener; 67 | SOCKET sock [2] = { -1, -1 }; 68 | 69 | if ((listener = ev_tcp_socket ()) == INVALID_SOCKET) 70 | return -1; 71 | 72 | addr.sin_family = AF_INET; 73 | addr.sin_addr.s_addr = htonl (INADDR_LOOPBACK); 74 | addr.sin_port = 0; 75 | 76 | if (bind (listener, (struct sockaddr *)&addr, addr_size)) 77 | goto fail; 78 | 79 | if (getsockname (listener, (struct sockaddr *)&addr, &addr_size)) 80 | goto fail; 81 | 82 | if (listen (listener, 1)) 83 | goto fail; 84 | 85 | if ((sock [0] = ev_tcp_socket ()) == INVALID_SOCKET) 86 | goto fail; 87 | 88 | if (connect (sock [0], (struct sockaddr *)&addr, addr_size)) 89 | goto fail; 90 | 91 | /* TODO: returns INVALID_SOCKET on winsock accept, not < 0. fix it */ 92 | /* when convenient, probably by just removing error checking altogether? */ 93 | if ((sock [1] = accept (listener, 0, 0)) < 0) 94 | goto fail; 95 | 96 | /* windows vista returns fantasy port numbers for sockets: 97 | * example for two interconnected tcp sockets: 98 | * 99 | * (Socket::unpack_sockaddr_in getsockname $sock0)[0] == 53364 100 | * (Socket::unpack_sockaddr_in getpeername $sock0)[0] == 53363 101 | * (Socket::unpack_sockaddr_in getsockname $sock1)[0] == 53363 102 | * (Socket::unpack_sockaddr_in getpeername $sock1)[0] == 53365 103 | * 104 | * wow! tridirectional sockets! 105 | * 106 | * this way of checking ports seems to work: 107 | */ 108 | if (getpeername (sock [0], (struct sockaddr *)&addr, &addr_size)) 109 | goto fail; 110 | 111 | if (getsockname (sock [1], (struct sockaddr *)&adr2, &adr2_size)) 112 | goto fail; 113 | 114 | errno = WSAEINVAL; 115 | if (addr_size != adr2_size 116 | || addr.sin_addr.s_addr != adr2.sin_addr.s_addr /* just to be sure, I mean, it's windows */ 117 | || addr.sin_port != adr2.sin_port) 118 | goto fail; 119 | 120 | closesocket (listener); 121 | 122 | #if EV_SELECT_IS_WINSOCKET 123 | filedes [0] = EV_WIN32_HANDLE_TO_FD (sock [0]); 124 | filedes [1] = EV_WIN32_HANDLE_TO_FD (sock [1]); 125 | #else 126 | /* when select isn't winsocket, we also expect socket, connect, accept etc. 127 | * to work on fds */ 128 | filedes [0] = sock [0]; 129 | filedes [1] = sock [1]; 130 | #endif 131 | 132 | return 0; 133 | 134 | fail: 135 | closesocket (listener); 136 | 137 | if (sock [0] != INVALID_SOCKET) closesocket (sock [0]); 138 | if (sock [1] != INVALID_SOCKET) closesocket (sock [1]); 139 | 140 | return -1; 141 | } 142 | 143 | #undef pipe 144 | #define pipe(filedes) ev_pipe (filedes) 145 | 146 | #define EV_HAVE_EV_TIME 1 147 | ev_tstamp 148 | ev_time (void) 149 | { 150 | FILETIME ft; 151 | ULARGE_INTEGER ui; 152 | 153 | GetSystemTimeAsFileTime (&ft); 154 | ui.u.LowPart = ft.dwLowDateTime; 155 | ui.u.HighPart = ft.dwHighDateTime; 156 | 157 | /* msvc cannot convert ulonglong to double... yes, it is that sucky */ 158 | return (LONGLONG)(ui.QuadPart - 116444736000000000) * 1e-7; 159 | } 160 | 161 | #endif 162 | 163 | -------------------------------------------------------------------------------- /libev/ev_wrap.h: -------------------------------------------------------------------------------- 1 | /* DO NOT EDIT, automatically generated by update_ev_wrap */ 2 | #ifndef EV_WRAP_H 3 | #define EV_WRAP_H 4 | #define acquire_cb ((loop)->acquire_cb) 5 | #define activecnt ((loop)->activecnt) 6 | #define anfdmax ((loop)->anfdmax) 7 | #define anfds ((loop)->anfds) 8 | #define async_pending ((loop)->async_pending) 9 | #define asynccnt ((loop)->asynccnt) 10 | #define asyncmax ((loop)->asyncmax) 11 | #define asyncs ((loop)->asyncs) 12 | #define backend ((loop)->backend) 13 | #define backend_fd ((loop)->backend_fd) 14 | #define backend_mintime ((loop)->backend_mintime) 15 | #define backend_modify ((loop)->backend_modify) 16 | #define backend_poll ((loop)->backend_poll) 17 | #define checkcnt ((loop)->checkcnt) 18 | #define checkmax ((loop)->checkmax) 19 | #define checks ((loop)->checks) 20 | #define cleanupcnt ((loop)->cleanupcnt) 21 | #define cleanupmax ((loop)->cleanupmax) 22 | #define cleanups ((loop)->cleanups) 23 | #define curpid ((loop)->curpid) 24 | #define epoll_epermcnt ((loop)->epoll_epermcnt) 25 | #define epoll_epermmax ((loop)->epoll_epermmax) 26 | #define epoll_eperms ((loop)->epoll_eperms) 27 | #define epoll_eventmax ((loop)->epoll_eventmax) 28 | #define epoll_events ((loop)->epoll_events) 29 | #define evpipe ((loop)->evpipe) 30 | #define fdchangecnt ((loop)->fdchangecnt) 31 | #define fdchangemax ((loop)->fdchangemax) 32 | #define fdchanges ((loop)->fdchanges) 33 | #define forkcnt ((loop)->forkcnt) 34 | #define forkmax ((loop)->forkmax) 35 | #define forks ((loop)->forks) 36 | #define fs_2625 ((loop)->fs_2625) 37 | #define fs_fd ((loop)->fs_fd) 38 | #define fs_hash ((loop)->fs_hash) 39 | #define fs_w ((loop)->fs_w) 40 | #define idleall ((loop)->idleall) 41 | #define idlecnt ((loop)->idlecnt) 42 | #define idlemax ((loop)->idlemax) 43 | #define idles ((loop)->idles) 44 | #define invoke_cb ((loop)->invoke_cb) 45 | #define io_blocktime ((loop)->io_blocktime) 46 | #define iocp ((loop)->iocp) 47 | #define kqueue_changecnt ((loop)->kqueue_changecnt) 48 | #define kqueue_changemax ((loop)->kqueue_changemax) 49 | #define kqueue_changes ((loop)->kqueue_changes) 50 | #define kqueue_eventmax ((loop)->kqueue_eventmax) 51 | #define kqueue_events ((loop)->kqueue_events) 52 | #define kqueue_fd_pid ((loop)->kqueue_fd_pid) 53 | #define loop_count ((loop)->loop_count) 54 | #define loop_depth ((loop)->loop_depth) 55 | #define loop_done ((loop)->loop_done) 56 | #define mn_now ((loop)->mn_now) 57 | #define now_floor ((loop)->now_floor) 58 | #define origflags ((loop)->origflags) 59 | #define pending_w ((loop)->pending_w) 60 | #define pendingcnt ((loop)->pendingcnt) 61 | #define pendingmax ((loop)->pendingmax) 62 | #define pendingpri ((loop)->pendingpri) 63 | #define pendings ((loop)->pendings) 64 | #define periodiccnt ((loop)->periodiccnt) 65 | #define periodicmax ((loop)->periodicmax) 66 | #define periodics ((loop)->periodics) 67 | #define pipe_w ((loop)->pipe_w) 68 | #define pipe_write_skipped ((loop)->pipe_write_skipped) 69 | #define pipe_write_wanted ((loop)->pipe_write_wanted) 70 | #define pollcnt ((loop)->pollcnt) 71 | #define pollidxmax ((loop)->pollidxmax) 72 | #define pollidxs ((loop)->pollidxs) 73 | #define pollmax ((loop)->pollmax) 74 | #define polls ((loop)->polls) 75 | #define port_eventmax ((loop)->port_eventmax) 76 | #define port_events ((loop)->port_events) 77 | #define postfork ((loop)->postfork) 78 | #define preparecnt ((loop)->preparecnt) 79 | #define preparemax ((loop)->preparemax) 80 | #define prepares ((loop)->prepares) 81 | #define release_cb ((loop)->release_cb) 82 | #define rfeedcnt ((loop)->rfeedcnt) 83 | #define rfeedmax ((loop)->rfeedmax) 84 | #define rfeeds ((loop)->rfeeds) 85 | #define rtmn_diff ((loop)->rtmn_diff) 86 | #define sig_pending ((loop)->sig_pending) 87 | #define sigfd ((loop)->sigfd) 88 | #define sigfd_set ((loop)->sigfd_set) 89 | #define sigfd_w ((loop)->sigfd_w) 90 | #define timeout_blocktime ((loop)->timeout_blocktime) 91 | #define timercnt ((loop)->timercnt) 92 | #define timermax ((loop)->timermax) 93 | #define timers ((loop)->timers) 94 | #define userdata ((loop)->userdata) 95 | #define vec_eo ((loop)->vec_eo) 96 | #define vec_max ((loop)->vec_max) 97 | #define vec_ri ((loop)->vec_ri) 98 | #define vec_ro ((loop)->vec_ro) 99 | #define vec_wi ((loop)->vec_wi) 100 | #define vec_wo ((loop)->vec_wo) 101 | #else 102 | #undef EV_WRAP_H 103 | #undef acquire_cb 104 | #undef activecnt 105 | #undef anfdmax 106 | #undef anfds 107 | #undef async_pending 108 | #undef asynccnt 109 | #undef asyncmax 110 | #undef asyncs 111 | #undef backend 112 | #undef backend_fd 113 | #undef backend_mintime 114 | #undef backend_modify 115 | #undef backend_poll 116 | #undef checkcnt 117 | #undef checkmax 118 | #undef checks 119 | #undef cleanupcnt 120 | #undef cleanupmax 121 | #undef cleanups 122 | #undef curpid 123 | #undef epoll_epermcnt 124 | #undef epoll_epermmax 125 | #undef epoll_eperms 126 | #undef epoll_eventmax 127 | #undef epoll_events 128 | #undef evpipe 129 | #undef fdchangecnt 130 | #undef fdchangemax 131 | #undef fdchanges 132 | #undef forkcnt 133 | #undef forkmax 134 | #undef forks 135 | #undef fs_2625 136 | #undef fs_fd 137 | #undef fs_hash 138 | #undef fs_w 139 | #undef idleall 140 | #undef idlecnt 141 | #undef idlemax 142 | #undef idles 143 | #undef invoke_cb 144 | #undef io_blocktime 145 | #undef iocp 146 | #undef kqueue_changecnt 147 | #undef kqueue_changemax 148 | #undef kqueue_changes 149 | #undef kqueue_eventmax 150 | #undef kqueue_events 151 | #undef kqueue_fd_pid 152 | #undef loop_count 153 | #undef loop_depth 154 | #undef loop_done 155 | #undef mn_now 156 | #undef now_floor 157 | #undef origflags 158 | #undef pending_w 159 | #undef pendingcnt 160 | #undef pendingmax 161 | #undef pendingpri 162 | #undef pendings 163 | #undef periodiccnt 164 | #undef periodicmax 165 | #undef periodics 166 | #undef pipe_w 167 | #undef pipe_write_skipped 168 | #undef pipe_write_wanted 169 | #undef pollcnt 170 | #undef pollidxmax 171 | #undef pollidxs 172 | #undef pollmax 173 | #undef polls 174 | #undef port_eventmax 175 | #undef port_events 176 | #undef postfork 177 | #undef preparecnt 178 | #undef preparemax 179 | #undef prepares 180 | #undef release_cb 181 | #undef rfeedcnt 182 | #undef rfeedmax 183 | #undef rfeeds 184 | #undef rtmn_diff 185 | #undef sig_pending 186 | #undef sigfd 187 | #undef sigfd_set 188 | #undef sigfd_w 189 | #undef timeout_blocktime 190 | #undef timercnt 191 | #undef timermax 192 | #undef timers 193 | #undef userdata 194 | #undef vec_eo 195 | #undef vec_max 196 | #undef vec_ri 197 | #undef vec_ro 198 | #undef vec_wi 199 | #undef vec_wo 200 | #endif 201 | -------------------------------------------------------------------------------- /libev/event.h: -------------------------------------------------------------------------------- 1 | /* 2 | * libevent compatibility header, only core events supported 3 | * 4 | * Copyright (c) 2007,2008,2010,2012 Marc Alexander Lehmann 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without modifica- 8 | * tion, are permitted provided that the following conditions are met: 9 | * 10 | * 1. Redistributions of source code must retain the above copyright notice, 11 | * this list of conditions and the following disclaimer. 12 | * 13 | * 2. Redistributions in binary form must reproduce the above copyright 14 | * notice, this list of conditions and the following disclaimer in the 15 | * documentation and/or other materials provided with the distribution. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 18 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MER- 19 | * CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 20 | * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPE- 21 | * CIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 22 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 23 | * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 24 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTH- 25 | * ERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 26 | * OF THE POSSIBILITY OF SUCH DAMAGE. 27 | * 28 | * Alternatively, the contents of this file may be used under the terms of 29 | * the GNU General Public License ("GPL") version 2 or any later version, 30 | * in which case the provisions of the GPL are applicable instead of 31 | * the above. If you wish to allow the use of your version of this file 32 | * only under the terms of the GPL and not to allow others to use your 33 | * version of this file under the BSD license, indicate your decision 34 | * by deleting the provisions above and replace them with the notice 35 | * and other provisions required by the GPL. If you do not delete the 36 | * provisions above, a recipient may use your version of this file under 37 | * either the BSD or the GPL. 38 | */ 39 | 40 | #ifndef EVENT_H_ 41 | #define EVENT_H_ 42 | 43 | #ifdef EV_H 44 | # include EV_H 45 | #else 46 | # include "ev.h" 47 | #endif 48 | 49 | #ifndef EVLOOP_NONBLOCK 50 | # define EVLOOP_NONBLOCK EVRUN_NOWAIT 51 | #endif 52 | #ifndef EVLOOP_ONESHOT 53 | # define EVLOOP_ONESHOT EVRUN_ONCE 54 | #endif 55 | #ifndef EV_TIMEOUT 56 | # define EV_TIMEOUT EV_TIMER 57 | #endif 58 | 59 | #ifdef __cplusplus 60 | extern "C" { 61 | #endif 62 | 63 | /* we need sys/time.h for struct timeval only */ 64 | #if !defined (WIN32) || defined (__MINGW32__) 65 | # include /* mingw seems to need this, for whatever reason */ 66 | # include 67 | #endif 68 | 69 | struct event_base; 70 | 71 | #define EVLIST_TIMEOUT 0x01 72 | #define EVLIST_INSERTED 0x02 73 | #define EVLIST_SIGNAL 0x04 74 | #define EVLIST_ACTIVE 0x08 75 | #define EVLIST_INTERNAL 0x10 76 | #define EVLIST_INIT 0x80 77 | 78 | typedef void (*event_callback_fn)(int, short, void *); 79 | 80 | struct event 81 | { 82 | /* libev watchers we map onto */ 83 | union { 84 | struct ev_io io; 85 | struct ev_signal sig; 86 | } iosig; 87 | struct ev_timer to; 88 | 89 | /* compatibility slots */ 90 | struct event_base *ev_base; 91 | event_callback_fn ev_callback; 92 | void *ev_arg; 93 | int ev_fd; 94 | int ev_pri; 95 | int ev_res; 96 | int ev_flags; 97 | short ev_events; 98 | }; 99 | 100 | event_callback_fn event_get_callback (const struct event *ev); 101 | 102 | #define EV_READ EV_READ 103 | #define EV_WRITE EV_WRITE 104 | #define EV_PERSIST 0x10 105 | #define EV_ET 0x20 /* nop */ 106 | 107 | #define EVENT_SIGNAL(ev) ((int) (ev)->ev_fd) 108 | #define EVENT_FD(ev) ((int) (ev)->ev_fd) 109 | 110 | #define event_initialized(ev) ((ev)->ev_flags & EVLIST_INIT) 111 | 112 | #define evtimer_add(ev,tv) event_add (ev, tv) 113 | #define evtimer_set(ev,cb,data) event_set (ev, -1, 0, cb, data) 114 | #define evtimer_del(ev) event_del (ev) 115 | #define evtimer_pending(ev,tv) event_pending (ev, EV_TIMEOUT, tv) 116 | #define evtimer_initialized(ev) event_initialized (ev) 117 | 118 | #define timeout_add(ev,tv) evtimer_add (ev, tv) 119 | #define timeout_set(ev,cb,data) evtimer_set (ev, cb, data) 120 | #define timeout_del(ev) evtimer_del (ev) 121 | #define timeout_pending(ev,tv) evtimer_pending (ev, tv) 122 | #define timeout_initialized(ev) evtimer_initialized (ev) 123 | 124 | #define signal_add(ev,tv) event_add (ev, tv) 125 | #define signal_set(ev,sig,cb,data) event_set (ev, sig, EV_SIGNAL | EV_PERSIST, cb, data) 126 | #define signal_del(ev) event_del (ev) 127 | #define signal_pending(ev,tv) event_pending (ev, EV_SIGNAL, tv) 128 | #define signal_initialized(ev) event_initialized (ev) 129 | 130 | const char *event_get_version (void); 131 | const char *event_get_method (void); 132 | 133 | void *event_init (void); 134 | void event_base_free (struct event_base *base); 135 | 136 | #define EVLOOP_ONCE EVLOOP_ONESHOT 137 | int event_loop (int); 138 | int event_loopexit (struct timeval *tv); 139 | int event_dispatch (void); 140 | 141 | #define _EVENT_LOG_DEBUG 0 142 | #define _EVENT_LOG_MSG 1 143 | #define _EVENT_LOG_WARN 2 144 | #define _EVENT_LOG_ERR 3 145 | typedef void (*event_log_cb)(int severity, const char *msg); 146 | void event_set_log_callback(event_log_cb cb); 147 | 148 | void event_set (struct event *ev, int fd, short events, void (*cb)(int, short, void *), void *arg); 149 | int event_once (int fd, short events, void (*cb)(int, short, void *), void *arg, struct timeval *tv); 150 | 151 | int event_add (struct event *ev, struct timeval *tv); 152 | int event_del (struct event *ev); 153 | void event_active (struct event *ev, int res, short ncalls); /* ncalls is being ignored */ 154 | 155 | int event_pending (struct event *ev, short, struct timeval *tv); 156 | 157 | int event_priority_init (int npri); 158 | int event_priority_set (struct event *ev, int pri); 159 | 160 | struct event_base *event_base_new (void); 161 | const char *event_base_get_method (const struct event_base *); 162 | int event_base_set (struct event_base *base, struct event *ev); 163 | int event_base_loop (struct event_base *base, int); 164 | int event_base_loopexit (struct event_base *base, struct timeval *tv); 165 | int event_base_dispatch (struct event_base *base); 166 | int event_base_once (struct event_base *base, int fd, short events, void (*cb)(int, short, void *), void *arg, struct timeval *tv); 167 | int event_base_priority_init (struct event_base *base, int fd); 168 | 169 | /* next line is different in the libevent+libev version */ 170 | /*libevent-include*/ 171 | 172 | #ifdef __cplusplus 173 | } 174 | #endif 175 | 176 | #endif 177 | 178 | -------------------------------------------------------------------------------- /libev/ev_vars.h: -------------------------------------------------------------------------------- 1 | /* 2 | * loop member variable declarations 3 | * 4 | * Copyright (c) 2007,2008,2009,2010,2011,2012,2013 Marc Alexander Lehmann 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without modifica- 8 | * tion, are permitted provided that the following conditions are met: 9 | * 10 | * 1. Redistributions of source code must retain the above copyright notice, 11 | * this list of conditions and the following disclaimer. 12 | * 13 | * 2. Redistributions in binary form must reproduce the above copyright 14 | * notice, this list of conditions and the following disclaimer in the 15 | * documentation and/or other materials provided with the distribution. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 18 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MER- 19 | * CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 20 | * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPE- 21 | * CIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 22 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 23 | * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 24 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTH- 25 | * ERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 26 | * OF THE POSSIBILITY OF SUCH DAMAGE. 27 | * 28 | * Alternatively, the contents of this file may be used under the terms of 29 | * the GNU General Public License ("GPL") version 2 or any later version, 30 | * in which case the provisions of the GPL are applicable instead of 31 | * the above. If you wish to allow the use of your version of this file 32 | * only under the terms of the GPL and not to allow others to use your 33 | * version of this file under the BSD license, indicate your decision 34 | * by deleting the provisions above and replace them with the notice 35 | * and other provisions required by the GPL. If you do not delete the 36 | * provisions above, a recipient may use your version of this file under 37 | * either the BSD or the GPL. 38 | */ 39 | 40 | #define VARx(type,name) VAR(name, type name) 41 | 42 | VARx(ev_tstamp, now_floor) /* last time we refreshed rt_time */ 43 | VARx(ev_tstamp, mn_now) /* monotonic clock "now" */ 44 | VARx(ev_tstamp, rtmn_diff) /* difference realtime - monotonic time */ 45 | 46 | /* for reverse feeding of events */ 47 | VARx(W *, rfeeds) 48 | VARx(int, rfeedmax) 49 | VARx(int, rfeedcnt) 50 | 51 | VAR (pendings, ANPENDING *pendings [NUMPRI]) 52 | VAR (pendingmax, int pendingmax [NUMPRI]) 53 | VAR (pendingcnt, int pendingcnt [NUMPRI]) 54 | VARx(int, pendingpri) /* highest priority currently pending */ 55 | VARx(ev_prepare, pending_w) /* dummy pending watcher */ 56 | 57 | VARx(ev_tstamp, io_blocktime) 58 | VARx(ev_tstamp, timeout_blocktime) 59 | 60 | VARx(int, backend) 61 | VARx(int, activecnt) /* total number of active events ("refcount") */ 62 | VARx(EV_ATOMIC_T, loop_done) /* signal by ev_break */ 63 | 64 | VARx(int, backend_fd) 65 | VARx(ev_tstamp, backend_mintime) /* assumed typical timer resolution */ 66 | VAR (backend_modify, void (*backend_modify)(EV_P_ int fd, int oev, int nev)) 67 | VAR (backend_poll , void (*backend_poll)(EV_P_ ev_tstamp timeout)) 68 | 69 | VARx(ANFD *, anfds) 70 | VARx(int, anfdmax) 71 | 72 | VAR (evpipe, int evpipe [2]) 73 | VARx(ev_io, pipe_w) 74 | VARx(EV_ATOMIC_T, pipe_write_wanted) 75 | VARx(EV_ATOMIC_T, pipe_write_skipped) 76 | 77 | #if !defined(_WIN32) || EV_GENWRAP 78 | VARx(pid_t, curpid) 79 | #endif 80 | 81 | VARx(char, postfork) /* true if we need to recreate kernel state after fork */ 82 | 83 | #if EV_USE_SELECT || EV_GENWRAP 84 | VARx(void *, vec_ri) 85 | VARx(void *, vec_ro) 86 | VARx(void *, vec_wi) 87 | VARx(void *, vec_wo) 88 | #if defined(_WIN32) || EV_GENWRAP 89 | VARx(void *, vec_eo) 90 | #endif 91 | VARx(int, vec_max) 92 | #endif 93 | 94 | #if EV_USE_POLL || EV_GENWRAP 95 | VARx(struct pollfd *, polls) 96 | VARx(int, pollmax) 97 | VARx(int, pollcnt) 98 | VARx(int *, pollidxs) /* maps fds into structure indices */ 99 | VARx(int, pollidxmax) 100 | #endif 101 | 102 | #if EV_USE_EPOLL || EV_GENWRAP 103 | VARx(struct epoll_event *, epoll_events) 104 | VARx(int, epoll_eventmax) 105 | VARx(int *, epoll_eperms) 106 | VARx(int, epoll_epermcnt) 107 | VARx(int, epoll_epermmax) 108 | #endif 109 | 110 | #if EV_USE_KQUEUE || EV_GENWRAP 111 | VARx(pid_t, kqueue_fd_pid) 112 | VARx(struct kevent *, kqueue_changes) 113 | VARx(int, kqueue_changemax) 114 | VARx(int, kqueue_changecnt) 115 | VARx(struct kevent *, kqueue_events) 116 | VARx(int, kqueue_eventmax) 117 | #endif 118 | 119 | #if EV_USE_PORT || EV_GENWRAP 120 | VARx(struct port_event *, port_events) 121 | VARx(int, port_eventmax) 122 | #endif 123 | 124 | #if EV_USE_IOCP || EV_GENWRAP 125 | VARx(HANDLE, iocp) 126 | #endif 127 | 128 | VARx(int *, fdchanges) 129 | VARx(int, fdchangemax) 130 | VARx(int, fdchangecnt) 131 | 132 | VARx(ANHE *, timers) 133 | VARx(int, timermax) 134 | VARx(int, timercnt) 135 | 136 | #if EV_PERIODIC_ENABLE || EV_GENWRAP 137 | VARx(ANHE *, periodics) 138 | VARx(int, periodicmax) 139 | VARx(int, periodiccnt) 140 | #endif 141 | 142 | #if EV_IDLE_ENABLE || EV_GENWRAP 143 | VAR (idles, ev_idle **idles [NUMPRI]) 144 | VAR (idlemax, int idlemax [NUMPRI]) 145 | VAR (idlecnt, int idlecnt [NUMPRI]) 146 | #endif 147 | VARx(int, idleall) /* total number */ 148 | 149 | VARx(struct ev_prepare **, prepares) 150 | VARx(int, preparemax) 151 | VARx(int, preparecnt) 152 | 153 | VARx(struct ev_check **, checks) 154 | VARx(int, checkmax) 155 | VARx(int, checkcnt) 156 | 157 | #if EV_FORK_ENABLE || EV_GENWRAP 158 | VARx(struct ev_fork **, forks) 159 | VARx(int, forkmax) 160 | VARx(int, forkcnt) 161 | #endif 162 | 163 | #if EV_CLEANUP_ENABLE || EV_GENWRAP 164 | VARx(struct ev_cleanup **, cleanups) 165 | VARx(int, cleanupmax) 166 | VARx(int, cleanupcnt) 167 | #endif 168 | 169 | #if EV_ASYNC_ENABLE || EV_GENWRAP 170 | VARx(EV_ATOMIC_T, async_pending) 171 | VARx(struct ev_async **, asyncs) 172 | VARx(int, asyncmax) 173 | VARx(int, asynccnt) 174 | #endif 175 | 176 | #if EV_USE_INOTIFY || EV_GENWRAP 177 | VARx(int, fs_fd) 178 | VARx(ev_io, fs_w) 179 | VARx(char, fs_2625) /* whether we are running in linux 2.6.25 or newer */ 180 | VAR (fs_hash, ANFS fs_hash [EV_INOTIFY_HASHSIZE]) 181 | #endif 182 | 183 | VARx(EV_ATOMIC_T, sig_pending) 184 | #if EV_USE_SIGNALFD || EV_GENWRAP 185 | VARx(int, sigfd) 186 | VARx(ev_io, sigfd_w) 187 | VARx(sigset_t, sigfd_set) 188 | #endif 189 | 190 | VARx(unsigned int, origflags) /* original loop flags */ 191 | 192 | #if EV_FEATURE_API || EV_GENWRAP 193 | VARx(unsigned int, loop_count) /* total number of loop iterations/blocks */ 194 | VARx(unsigned int, loop_depth) /* #ev_run enters - #ev_run leaves */ 195 | 196 | VARx(void *, userdata) 197 | /* C++ doesn't support the ev_loop_callback typedef here. stinks. */ 198 | VAR (release_cb, void (*release_cb)(EV_P) EV_THROW) 199 | VAR (acquire_cb, void (*acquire_cb)(EV_P) EV_THROW) 200 | VAR (invoke_cb , ev_loop_callback invoke_cb) 201 | #endif 202 | 203 | #undef VARx 204 | 205 | -------------------------------------------------------------------------------- /libev/ev_port.c: -------------------------------------------------------------------------------- 1 | /* 2 | * libev solaris event port backend 3 | * 4 | * Copyright (c) 2007,2008,2009,2010,2011 Marc Alexander Lehmann 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without modifica- 8 | * tion, are permitted provided that the following conditions are met: 9 | * 10 | * 1. Redistributions of source code must retain the above copyright notice, 11 | * this list of conditions and the following disclaimer. 12 | * 13 | * 2. Redistributions in binary form must reproduce the above copyright 14 | * notice, this list of conditions and the following disclaimer in the 15 | * documentation and/or other materials provided with the distribution. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 18 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MER- 19 | * CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 20 | * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPE- 21 | * CIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 22 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 23 | * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 24 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTH- 25 | * ERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 26 | * OF THE POSSIBILITY OF SUCH DAMAGE. 27 | * 28 | * Alternatively, the contents of this file may be used under the terms of 29 | * the GNU General Public License ("GPL") version 2 or any later version, 30 | * in which case the provisions of the GPL are applicable instead of 31 | * the above. If you wish to allow the use of your version of this file 32 | * only under the terms of the GPL and not to allow others to use your 33 | * version of this file under the BSD license, indicate your decision 34 | * by deleting the provisions above and replace them with the notice 35 | * and other provisions required by the GPL. If you do not delete the 36 | * provisions above, a recipient may use your version of this file under 37 | * either the BSD or the GPL. 38 | */ 39 | 40 | /* useful reading: 41 | * 42 | * http://bugs.opensolaris.org/view_bug.do?bug_id=6268715 (random results) 43 | * http://bugs.opensolaris.org/view_bug.do?bug_id=6455223 (just totally broken) 44 | * http://bugs.opensolaris.org/view_bug.do?bug_id=6873782 (manpage ETIME) 45 | * http://bugs.opensolaris.org/view_bug.do?bug_id=6874410 (implementation ETIME) 46 | * http://www.mail-archive.com/networking-discuss@opensolaris.org/msg11898.html ETIME vs. nget 47 | * http://src.opensolaris.org/source/xref/onnv/onnv-gate/usr/src/lib/libc/port/gen/event_port.c (libc) 48 | * http://cvs.opensolaris.org/source/xref/onnv/onnv-gate/usr/src/uts/common/fs/portfs/port.c#1325 (kernel) 49 | */ 50 | 51 | #include 52 | #include 53 | #include 54 | #include 55 | #include 56 | #include 57 | 58 | inline_speed 59 | void 60 | port_associate_and_check (EV_P_ int fd, int ev) 61 | { 62 | if (0 > 63 | port_associate ( 64 | backend_fd, PORT_SOURCE_FD, fd, 65 | (ev & EV_READ ? POLLIN : 0) 66 | | (ev & EV_WRITE ? POLLOUT : 0), 67 | 0 68 | ) 69 | ) 70 | { 71 | if (errno == EBADFD) 72 | fd_kill (EV_A_ fd); 73 | else 74 | ev_syserr ("(libev) port_associate"); 75 | } 76 | } 77 | 78 | static void 79 | port_modify (EV_P_ int fd, int oev, int nev) 80 | { 81 | /* we need to reassociate no matter what, as closes are 82 | * once more silently being discarded. 83 | */ 84 | if (!nev) 85 | { 86 | if (oev) 87 | port_dissociate (backend_fd, PORT_SOURCE_FD, fd); 88 | } 89 | else 90 | port_associate_and_check (EV_A_ fd, nev); 91 | } 92 | 93 | static void 94 | port_poll (EV_P_ ev_tstamp timeout) 95 | { 96 | int res, i; 97 | struct timespec ts; 98 | uint_t nget = 1; 99 | 100 | /* we initialise this to something we will skip in the loop, as */ 101 | /* port_getn can return with nget unchanged, but no indication */ 102 | /* whether it was the original value or has been updated :/ */ 103 | port_events [0].portev_source = 0; 104 | 105 | EV_RELEASE_CB; 106 | EV_TS_SET (ts, timeout); 107 | res = port_getn (backend_fd, port_events, port_eventmax, &nget, &ts); 108 | EV_ACQUIRE_CB; 109 | 110 | /* port_getn may or may not set nget on error */ 111 | /* so we rely on port_events [0].portev_source not being updated */ 112 | if (res == -1 && errno != ETIME && errno != EINTR) 113 | ev_syserr ("(libev) port_getn (see http://bugs.opensolaris.org/view_bug.do?bug_id=6268715, try LIBEV_FLAGS=3 env variable)"); 114 | 115 | for (i = 0; i < nget; ++i) 116 | { 117 | if (port_events [i].portev_source == PORT_SOURCE_FD) 118 | { 119 | int fd = port_events [i].portev_object; 120 | 121 | fd_event ( 122 | EV_A_ 123 | fd, 124 | (port_events [i].portev_events & (POLLOUT | POLLERR | POLLHUP) ? EV_WRITE : 0) 125 | | (port_events [i].portev_events & (POLLIN | POLLERR | POLLHUP) ? EV_READ : 0) 126 | ); 127 | 128 | fd_change (EV_A_ fd, EV__IOFDSET); 129 | } 130 | } 131 | 132 | if (expect_false (nget == port_eventmax)) 133 | { 134 | ev_free (port_events); 135 | port_eventmax = array_nextsize (sizeof (port_event_t), port_eventmax, port_eventmax + 1); 136 | port_events = (port_event_t *)ev_malloc (sizeof (port_event_t) * port_eventmax); 137 | } 138 | } 139 | 140 | inline_size 141 | int 142 | port_init (EV_P_ int flags) 143 | { 144 | /* Initialize the kernel queue */ 145 | if ((backend_fd = port_create ()) < 0) 146 | return 0; 147 | 148 | assert (("libev: PORT_SOURCE_FD must not be zero", PORT_SOURCE_FD)); 149 | 150 | fcntl (backend_fd, F_SETFD, FD_CLOEXEC); /* not sure if necessary, hopefully doesn't hurt */ 151 | 152 | /* if my reading of the opensolaris kernel sources are correct, then 153 | * opensolaris does something very stupid: it checks if the time has already 154 | * elapsed and doesn't round up if that is the case,m otherwise it DOES round 155 | * up. Since we can't know what the case is, we need to guess by using a 156 | * "large enough" timeout. Normally, 1e-9 would be correct. 157 | */ 158 | backend_mintime = 1e-3; /* needed to compensate for port_getn returning early */ 159 | backend_modify = port_modify; 160 | backend_poll = port_poll; 161 | 162 | port_eventmax = 64; /* initial number of events receivable per poll */ 163 | port_events = (port_event_t *)ev_malloc (sizeof (port_event_t) * port_eventmax); 164 | 165 | return EVBACKEND_PORT; 166 | } 167 | 168 | inline_size 169 | void 170 | port_destroy (EV_P) 171 | { 172 | ev_free (port_events); 173 | } 174 | 175 | inline_size 176 | void 177 | port_fork (EV_P) 178 | { 179 | close (backend_fd); 180 | 181 | while ((backend_fd = port_create ()) < 0) 182 | ev_syserr ("(libev) port"); 183 | 184 | fcntl (backend_fd, F_SETFD, FD_CLOEXEC); 185 | 186 | /* re-register interest in fds */ 187 | fd_rearm_all (EV_A); 188 | } 189 | 190 | -------------------------------------------------------------------------------- /libev/ev_kqueue.c: -------------------------------------------------------------------------------- 1 | /* 2 | * libev kqueue backend 3 | * 4 | * Copyright (c) 2007,2008,2009,2010,2011,2012,2013 Marc Alexander Lehmann 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without modifica- 8 | * tion, are permitted provided that the following conditions are met: 9 | * 10 | * 1. Redistributions of source code must retain the above copyright notice, 11 | * this list of conditions and the following disclaimer. 12 | * 13 | * 2. Redistributions in binary form must reproduce the above copyright 14 | * notice, this list of conditions and the following disclaimer in the 15 | * documentation and/or other materials provided with the distribution. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 18 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MER- 19 | * CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 20 | * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPE- 21 | * CIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 22 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 23 | * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 24 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTH- 25 | * ERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 26 | * OF THE POSSIBILITY OF SUCH DAMAGE. 27 | * 28 | * Alternatively, the contents of this file may be used under the terms of 29 | * the GNU General Public License ("GPL") version 2 or any later version, 30 | * in which case the provisions of the GPL are applicable instead of 31 | * the above. If you wish to allow the use of your version of this file 32 | * only under the terms of the GPL and not to allow others to use your 33 | * version of this file under the BSD license, indicate your decision 34 | * by deleting the provisions above and replace them with the notice 35 | * and other provisions required by the GPL. If you do not delete the 36 | * provisions above, a recipient may use your version of this file under 37 | * either the BSD or the GPL. 38 | */ 39 | 40 | #include 41 | #include 42 | #include 43 | #include 44 | #include 45 | 46 | inline_speed 47 | void 48 | kqueue_change (EV_P_ int fd, int filter, int flags, int fflags) 49 | { 50 | ++kqueue_changecnt; 51 | array_needsize (struct kevent, kqueue_changes, kqueue_changemax, kqueue_changecnt, EMPTY2); 52 | 53 | EV_SET (&kqueue_changes [kqueue_changecnt - 1], fd, filter, flags, fflags, 0, 0); 54 | } 55 | 56 | /* OS X at least needs this */ 57 | #ifndef EV_ENABLE 58 | # define EV_ENABLE 0 59 | #endif 60 | #ifndef NOTE_EOF 61 | # define NOTE_EOF 0 62 | #endif 63 | 64 | static void 65 | kqueue_modify (EV_P_ int fd, int oev, int nev) 66 | { 67 | if (oev != nev) 68 | { 69 | if (oev & EV_READ) 70 | kqueue_change (EV_A_ fd, EVFILT_READ , EV_DELETE, 0); 71 | 72 | if (oev & EV_WRITE) 73 | kqueue_change (EV_A_ fd, EVFILT_WRITE, EV_DELETE, 0); 74 | } 75 | 76 | /* to detect close/reopen reliably, we have to re-add */ 77 | /* event requests even when oev == nev */ 78 | 79 | if (nev & EV_READ) 80 | kqueue_change (EV_A_ fd, EVFILT_READ , EV_ADD | EV_ENABLE, NOTE_EOF); 81 | 82 | if (nev & EV_WRITE) 83 | kqueue_change (EV_A_ fd, EVFILT_WRITE, EV_ADD | EV_ENABLE, NOTE_EOF); 84 | } 85 | 86 | static void 87 | kqueue_poll (EV_P_ ev_tstamp timeout) 88 | { 89 | int res, i; 90 | struct timespec ts; 91 | 92 | /* need to resize so there is enough space for errors */ 93 | if (kqueue_changecnt > kqueue_eventmax) 94 | { 95 | ev_free (kqueue_events); 96 | kqueue_eventmax = array_nextsize (sizeof (struct kevent), kqueue_eventmax, kqueue_changecnt); 97 | kqueue_events = (struct kevent *)ev_malloc (sizeof (struct kevent) * kqueue_eventmax); 98 | } 99 | 100 | EV_RELEASE_CB; 101 | EV_TS_SET (ts, timeout); 102 | res = kevent (backend_fd, kqueue_changes, kqueue_changecnt, kqueue_events, kqueue_eventmax, &ts); 103 | EV_ACQUIRE_CB; 104 | kqueue_changecnt = 0; 105 | 106 | if (expect_false (res < 0)) 107 | { 108 | if (errno != EINTR) 109 | ev_syserr ("(libev) kevent"); 110 | 111 | return; 112 | } 113 | 114 | for (i = 0; i < res; ++i) 115 | { 116 | int fd = kqueue_events [i].ident; 117 | 118 | if (expect_false (kqueue_events [i].flags & EV_ERROR)) 119 | { 120 | int err = kqueue_events [i].data; 121 | 122 | /* we are only interested in errors for fds that we are interested in :) */ 123 | if (anfds [fd].events) 124 | { 125 | if (err == ENOENT) /* resubmit changes on ENOENT */ 126 | kqueue_modify (EV_A_ fd, 0, anfds [fd].events); 127 | else if (err == EBADF) /* on EBADF, we re-check the fd */ 128 | { 129 | if (fd_valid (fd)) 130 | kqueue_modify (EV_A_ fd, 0, anfds [fd].events); 131 | else 132 | fd_kill (EV_A_ fd); 133 | } 134 | else /* on all other errors, we error out on the fd */ 135 | fd_kill (EV_A_ fd); 136 | } 137 | } 138 | else 139 | fd_event ( 140 | EV_A_ 141 | fd, 142 | kqueue_events [i].filter == EVFILT_READ ? EV_READ 143 | : kqueue_events [i].filter == EVFILT_WRITE ? EV_WRITE 144 | : 0 145 | ); 146 | } 147 | 148 | if (expect_false (res == kqueue_eventmax)) 149 | { 150 | ev_free (kqueue_events); 151 | kqueue_eventmax = array_nextsize (sizeof (struct kevent), kqueue_eventmax, kqueue_eventmax + 1); 152 | kqueue_events = (struct kevent *)ev_malloc (sizeof (struct kevent) * kqueue_eventmax); 153 | } 154 | } 155 | 156 | inline_size 157 | int 158 | kqueue_init (EV_P_ int flags) 159 | { 160 | /* initialize the kernel queue */ 161 | kqueue_fd_pid = getpid (); 162 | if ((backend_fd = kqueue ()) < 0) 163 | return 0; 164 | 165 | fcntl (backend_fd, F_SETFD, FD_CLOEXEC); /* not sure if necessary, hopefully doesn't hurt */ 166 | 167 | backend_mintime = 1e-9; /* apparently, they did the right thing in freebsd */ 168 | backend_modify = kqueue_modify; 169 | backend_poll = kqueue_poll; 170 | 171 | kqueue_eventmax = 64; /* initial number of events receivable per poll */ 172 | kqueue_events = (struct kevent *)ev_malloc (sizeof (struct kevent) * kqueue_eventmax); 173 | 174 | kqueue_changes = 0; 175 | kqueue_changemax = 0; 176 | kqueue_changecnt = 0; 177 | 178 | return EVBACKEND_KQUEUE; 179 | } 180 | 181 | inline_size 182 | void 183 | kqueue_destroy (EV_P) 184 | { 185 | ev_free (kqueue_events); 186 | ev_free (kqueue_changes); 187 | } 188 | 189 | inline_size 190 | void 191 | kqueue_fork (EV_P) 192 | { 193 | /* some BSD kernels don't just destroy the kqueue itself, 194 | * but also close the fd, which isn't documented, and 195 | * impossible to support properly. 196 | * we remember the pid of the kqueue call and only close 197 | * the fd if the pid is still the same. 198 | * this leaks fds on sane kernels, but BSD interfaces are 199 | * notoriously buggy and rarely get fixed. 200 | */ 201 | pid_t newpid = getpid (); 202 | 203 | if (newpid == kqueue_fd_pid) 204 | close (backend_fd); 205 | 206 | kqueue_fd_pid = newpid; 207 | while ((backend_fd = kqueue ()) < 0) 208 | ev_syserr ("(libev) kqueue"); 209 | 210 | fcntl (backend_fd, F_SETFD, FD_CLOEXEC); 211 | 212 | /* re-register interest in fds */ 213 | fd_rearm_all (EV_A); 214 | } 215 | 216 | /* sys/event.h defines EV_ERROR */ 217 | #undef EV_ERROR 218 | 219 | -------------------------------------------------------------------------------- /libev/missing: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | # Common wrapper for a few potentially missing GNU programs. 3 | 4 | scriptversion=2013-10-28.13; # UTC 5 | 6 | # Copyright (C) 1996-2014 Free Software Foundation, Inc. 7 | # Originally written by Fran,cois Pinard , 1996. 8 | 9 | # This program is free software; you can redistribute it and/or modify 10 | # it under the terms of the GNU General Public License as published by 11 | # the Free Software Foundation; either version 2, or (at your option) 12 | # any later version. 13 | 14 | # This program is distributed in the hope that it will be useful, 15 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | # GNU General Public License for more details. 18 | 19 | # You should have received a copy of the GNU General Public License 20 | # along with this program. If not, see . 21 | 22 | # As a special exception to the GNU General Public License, if you 23 | # distribute this file as part of a program that contains a 24 | # configuration script generated by Autoconf, you may include it under 25 | # the same distribution terms that you use for the rest of that program. 26 | 27 | if test $# -eq 0; then 28 | echo 1>&2 "Try '$0 --help' for more information" 29 | exit 1 30 | fi 31 | 32 | case $1 in 33 | 34 | --is-lightweight) 35 | # Used by our autoconf macros to check whether the available missing 36 | # script is modern enough. 37 | exit 0 38 | ;; 39 | 40 | --run) 41 | # Back-compat with the calling convention used by older automake. 42 | shift 43 | ;; 44 | 45 | -h|--h|--he|--hel|--help) 46 | echo "\ 47 | $0 [OPTION]... PROGRAM [ARGUMENT]... 48 | 49 | Run 'PROGRAM [ARGUMENT]...', returning a proper advice when this fails due 50 | to PROGRAM being missing or too old. 51 | 52 | Options: 53 | -h, --help display this help and exit 54 | -v, --version output version information and exit 55 | 56 | Supported PROGRAM values: 57 | aclocal autoconf autoheader autom4te automake makeinfo 58 | bison yacc flex lex help2man 59 | 60 | Version suffixes to PROGRAM as well as the prefixes 'gnu-', 'gnu', and 61 | 'g' are ignored when checking the name. 62 | 63 | Send bug reports to ." 64 | exit $? 65 | ;; 66 | 67 | -v|--v|--ve|--ver|--vers|--versi|--versio|--version) 68 | echo "missing $scriptversion (GNU Automake)" 69 | exit $? 70 | ;; 71 | 72 | -*) 73 | echo 1>&2 "$0: unknown '$1' option" 74 | echo 1>&2 "Try '$0 --help' for more information" 75 | exit 1 76 | ;; 77 | 78 | esac 79 | 80 | # Run the given program, remember its exit status. 81 | "$@"; st=$? 82 | 83 | # If it succeeded, we are done. 84 | test $st -eq 0 && exit 0 85 | 86 | # Also exit now if we it failed (or wasn't found), and '--version' was 87 | # passed; such an option is passed most likely to detect whether the 88 | # program is present and works. 89 | case $2 in --version|--help) exit $st;; esac 90 | 91 | # Exit code 63 means version mismatch. This often happens when the user 92 | # tries to use an ancient version of a tool on a file that requires a 93 | # minimum version. 94 | if test $st -eq 63; then 95 | msg="probably too old" 96 | elif test $st -eq 127; then 97 | # Program was missing. 98 | msg="missing on your system" 99 | else 100 | # Program was found and executed, but failed. Give up. 101 | exit $st 102 | fi 103 | 104 | perl_URL=http://www.perl.org/ 105 | flex_URL=http://flex.sourceforge.net/ 106 | gnu_software_URL=http://www.gnu.org/software 107 | 108 | program_details () 109 | { 110 | case $1 in 111 | aclocal|automake) 112 | echo "The '$1' program is part of the GNU Automake package:" 113 | echo "<$gnu_software_URL/automake>" 114 | echo "It also requires GNU Autoconf, GNU m4 and Perl in order to run:" 115 | echo "<$gnu_software_URL/autoconf>" 116 | echo "<$gnu_software_URL/m4/>" 117 | echo "<$perl_URL>" 118 | ;; 119 | autoconf|autom4te|autoheader) 120 | echo "The '$1' program is part of the GNU Autoconf package:" 121 | echo "<$gnu_software_URL/autoconf/>" 122 | echo "It also requires GNU m4 and Perl in order to run:" 123 | echo "<$gnu_software_URL/m4/>" 124 | echo "<$perl_URL>" 125 | ;; 126 | esac 127 | } 128 | 129 | give_advice () 130 | { 131 | # Normalize program name to check for. 132 | normalized_program=`echo "$1" | sed ' 133 | s/^gnu-//; t 134 | s/^gnu//; t 135 | s/^g//; t'` 136 | 137 | printf '%s\n' "'$1' is $msg." 138 | 139 | configure_deps="'configure.ac' or m4 files included by 'configure.ac'" 140 | case $normalized_program in 141 | autoconf*) 142 | echo "You should only need it if you modified 'configure.ac'," 143 | echo "or m4 files included by it." 144 | program_details 'autoconf' 145 | ;; 146 | autoheader*) 147 | echo "You should only need it if you modified 'acconfig.h' or" 148 | echo "$configure_deps." 149 | program_details 'autoheader' 150 | ;; 151 | automake*) 152 | echo "You should only need it if you modified 'Makefile.am' or" 153 | echo "$configure_deps." 154 | program_details 'automake' 155 | ;; 156 | aclocal*) 157 | echo "You should only need it if you modified 'acinclude.m4' or" 158 | echo "$configure_deps." 159 | program_details 'aclocal' 160 | ;; 161 | autom4te*) 162 | echo "You might have modified some maintainer files that require" 163 | echo "the 'autom4te' program to be rebuilt." 164 | program_details 'autom4te' 165 | ;; 166 | bison*|yacc*) 167 | echo "You should only need it if you modified a '.y' file." 168 | echo "You may want to install the GNU Bison package:" 169 | echo "<$gnu_software_URL/bison/>" 170 | ;; 171 | lex*|flex*) 172 | echo "You should only need it if you modified a '.l' file." 173 | echo "You may want to install the Fast Lexical Analyzer package:" 174 | echo "<$flex_URL>" 175 | ;; 176 | help2man*) 177 | echo "You should only need it if you modified a dependency" \ 178 | "of a man page." 179 | echo "You may want to install the GNU Help2man package:" 180 | echo "<$gnu_software_URL/help2man/>" 181 | ;; 182 | makeinfo*) 183 | echo "You should only need it if you modified a '.texi' file, or" 184 | echo "any other file indirectly affecting the aspect of the manual." 185 | echo "You might want to install the Texinfo package:" 186 | echo "<$gnu_software_URL/texinfo/>" 187 | echo "The spurious makeinfo call might also be the consequence of" 188 | echo "using a buggy 'make' (AIX, DU, IRIX), in which case you might" 189 | echo "want to install GNU make:" 190 | echo "<$gnu_software_URL/make/>" 191 | ;; 192 | *) 193 | echo "You might have modified some files without having the proper" 194 | echo "tools for further handling them. Check the 'README' file, it" 195 | echo "often tells you about the needed prerequisites for installing" 196 | echo "this package. You may also peek at any GNU archive site, in" 197 | echo "case some other package contains this missing '$1' program." 198 | ;; 199 | esac 200 | } 201 | 202 | give_advice "$1" | sed -e '1s/^/WARNING: /' \ 203 | -e '2,$s/^/ /' >&2 204 | 205 | # Propagate the correct exit status (expected to be 127 for a program 206 | # not found, 63 for a program that failed due to version mismatch). 207 | exit $st 208 | 209 | # Local variables: 210 | # eval: (add-hook 'write-file-hooks 'time-stamp) 211 | # time-stamp-start: "scriptversion=" 212 | # time-stamp-format: "%:y-%02m-%02d.%02H" 213 | # time-stamp-time-zone: "UTC" 214 | # time-stamp-end: "; # UTC" 215 | # End: 216 | -------------------------------------------------------------------------------- /libev/compile: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | # Wrapper for compilers which do not understand '-c -o'. 3 | 4 | scriptversion=2012-10-14.11; # UTC 5 | 6 | # Copyright (C) 1999-2014 Free Software Foundation, Inc. 7 | # Written by Tom Tromey . 8 | # 9 | # This program is free software; you can redistribute it and/or modify 10 | # it under the terms of the GNU General Public License as published by 11 | # the Free Software Foundation; either version 2, or (at your option) 12 | # any later version. 13 | # 14 | # This program is distributed in the hope that it will be useful, 15 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | # GNU General Public License for more details. 18 | # 19 | # You should have received a copy of the GNU General Public License 20 | # along with this program. If not, see . 21 | 22 | # As a special exception to the GNU General Public License, if you 23 | # distribute this file as part of a program that contains a 24 | # configuration script generated by Autoconf, you may include it under 25 | # the same distribution terms that you use for the rest of that program. 26 | 27 | # This file is maintained in Automake, please report 28 | # bugs to or send patches to 29 | # . 30 | 31 | nl=' 32 | ' 33 | 34 | # We need space, tab and new line, in precisely that order. Quoting is 35 | # there to prevent tools from complaining about whitespace usage. 36 | IFS=" "" $nl" 37 | 38 | file_conv= 39 | 40 | # func_file_conv build_file lazy 41 | # Convert a $build file to $host form and store it in $file 42 | # Currently only supports Windows hosts. If the determined conversion 43 | # type is listed in (the comma separated) LAZY, no conversion will 44 | # take place. 45 | func_file_conv () 46 | { 47 | file=$1 48 | case $file in 49 | / | /[!/]*) # absolute file, and not a UNC file 50 | if test -z "$file_conv"; then 51 | # lazily determine how to convert abs files 52 | case `uname -s` in 53 | MINGW*) 54 | file_conv=mingw 55 | ;; 56 | CYGWIN*) 57 | file_conv=cygwin 58 | ;; 59 | *) 60 | file_conv=wine 61 | ;; 62 | esac 63 | fi 64 | case $file_conv/,$2, in 65 | *,$file_conv,*) 66 | ;; 67 | mingw/*) 68 | file=`cmd //C echo "$file " | sed -e 's/"\(.*\) " *$/\1/'` 69 | ;; 70 | cygwin/*) 71 | file=`cygpath -m "$file" || echo "$file"` 72 | ;; 73 | wine/*) 74 | file=`winepath -w "$file" || echo "$file"` 75 | ;; 76 | esac 77 | ;; 78 | esac 79 | } 80 | 81 | # func_cl_dashL linkdir 82 | # Make cl look for libraries in LINKDIR 83 | func_cl_dashL () 84 | { 85 | func_file_conv "$1" 86 | if test -z "$lib_path"; then 87 | lib_path=$file 88 | else 89 | lib_path="$lib_path;$file" 90 | fi 91 | linker_opts="$linker_opts -LIBPATH:$file" 92 | } 93 | 94 | # func_cl_dashl library 95 | # Do a library search-path lookup for cl 96 | func_cl_dashl () 97 | { 98 | lib=$1 99 | found=no 100 | save_IFS=$IFS 101 | IFS=';' 102 | for dir in $lib_path $LIB 103 | do 104 | IFS=$save_IFS 105 | if $shared && test -f "$dir/$lib.dll.lib"; then 106 | found=yes 107 | lib=$dir/$lib.dll.lib 108 | break 109 | fi 110 | if test -f "$dir/$lib.lib"; then 111 | found=yes 112 | lib=$dir/$lib.lib 113 | break 114 | fi 115 | if test -f "$dir/lib$lib.a"; then 116 | found=yes 117 | lib=$dir/lib$lib.a 118 | break 119 | fi 120 | done 121 | IFS=$save_IFS 122 | 123 | if test "$found" != yes; then 124 | lib=$lib.lib 125 | fi 126 | } 127 | 128 | # func_cl_wrapper cl arg... 129 | # Adjust compile command to suit cl 130 | func_cl_wrapper () 131 | { 132 | # Assume a capable shell 133 | lib_path= 134 | shared=: 135 | linker_opts= 136 | for arg 137 | do 138 | if test -n "$eat"; then 139 | eat= 140 | else 141 | case $1 in 142 | -o) 143 | # configure might choose to run compile as 'compile cc -o foo foo.c'. 144 | eat=1 145 | case $2 in 146 | *.o | *.[oO][bB][jJ]) 147 | func_file_conv "$2" 148 | set x "$@" -Fo"$file" 149 | shift 150 | ;; 151 | *) 152 | func_file_conv "$2" 153 | set x "$@" -Fe"$file" 154 | shift 155 | ;; 156 | esac 157 | ;; 158 | -I) 159 | eat=1 160 | func_file_conv "$2" mingw 161 | set x "$@" -I"$file" 162 | shift 163 | ;; 164 | -I*) 165 | func_file_conv "${1#-I}" mingw 166 | set x "$@" -I"$file" 167 | shift 168 | ;; 169 | -l) 170 | eat=1 171 | func_cl_dashl "$2" 172 | set x "$@" "$lib" 173 | shift 174 | ;; 175 | -l*) 176 | func_cl_dashl "${1#-l}" 177 | set x "$@" "$lib" 178 | shift 179 | ;; 180 | -L) 181 | eat=1 182 | func_cl_dashL "$2" 183 | ;; 184 | -L*) 185 | func_cl_dashL "${1#-L}" 186 | ;; 187 | -static) 188 | shared=false 189 | ;; 190 | -Wl,*) 191 | arg=${1#-Wl,} 192 | save_ifs="$IFS"; IFS=',' 193 | for flag in $arg; do 194 | IFS="$save_ifs" 195 | linker_opts="$linker_opts $flag" 196 | done 197 | IFS="$save_ifs" 198 | ;; 199 | -Xlinker) 200 | eat=1 201 | linker_opts="$linker_opts $2" 202 | ;; 203 | -*) 204 | set x "$@" "$1" 205 | shift 206 | ;; 207 | *.cc | *.CC | *.cxx | *.CXX | *.[cC]++) 208 | func_file_conv "$1" 209 | set x "$@" -Tp"$file" 210 | shift 211 | ;; 212 | *.c | *.cpp | *.CPP | *.lib | *.LIB | *.Lib | *.OBJ | *.obj | *.[oO]) 213 | func_file_conv "$1" mingw 214 | set x "$@" "$file" 215 | shift 216 | ;; 217 | *) 218 | set x "$@" "$1" 219 | shift 220 | ;; 221 | esac 222 | fi 223 | shift 224 | done 225 | if test -n "$linker_opts"; then 226 | linker_opts="-link$linker_opts" 227 | fi 228 | exec "$@" $linker_opts 229 | exit 1 230 | } 231 | 232 | eat= 233 | 234 | case $1 in 235 | '') 236 | echo "$0: No command. Try '$0 --help' for more information." 1>&2 237 | exit 1; 238 | ;; 239 | -h | --h*) 240 | cat <<\EOF 241 | Usage: compile [--help] [--version] PROGRAM [ARGS] 242 | 243 | Wrapper for compilers which do not understand '-c -o'. 244 | Remove '-o dest.o' from ARGS, run PROGRAM with the remaining 245 | arguments, and rename the output as expected. 246 | 247 | If you are trying to build a whole package this is not the 248 | right script to run: please start by reading the file 'INSTALL'. 249 | 250 | Report bugs to . 251 | EOF 252 | exit $? 253 | ;; 254 | -v | --v*) 255 | echo "compile $scriptversion" 256 | exit $? 257 | ;; 258 | cl | *[/\\]cl | cl.exe | *[/\\]cl.exe ) 259 | func_cl_wrapper "$@" # Doesn't return... 260 | ;; 261 | esac 262 | 263 | ofile= 264 | cfile= 265 | 266 | for arg 267 | do 268 | if test -n "$eat"; then 269 | eat= 270 | else 271 | case $1 in 272 | -o) 273 | # configure might choose to run compile as 'compile cc -o foo foo.c'. 274 | # So we strip '-o arg' only if arg is an object. 275 | eat=1 276 | case $2 in 277 | *.o | *.obj) 278 | ofile=$2 279 | ;; 280 | *) 281 | set x "$@" -o "$2" 282 | shift 283 | ;; 284 | esac 285 | ;; 286 | *.c) 287 | cfile=$1 288 | set x "$@" "$1" 289 | shift 290 | ;; 291 | *) 292 | set x "$@" "$1" 293 | shift 294 | ;; 295 | esac 296 | fi 297 | shift 298 | done 299 | 300 | if test -z "$ofile" || test -z "$cfile"; then 301 | # If no '-o' option was seen then we might have been invoked from a 302 | # pattern rule where we don't need one. That is ok -- this is a 303 | # normal compilation that the losing compiler can handle. If no 304 | # '.c' file was seen then we are probably linking. That is also 305 | # ok. 306 | exec "$@" 307 | fi 308 | 309 | # Name of file we expect compiler to create. 310 | cofile=`echo "$cfile" | sed 's|^.*[\\/]||; s|^[a-zA-Z]:||; s/\.c$/.o/'` 311 | 312 | # Create the lock directory. 313 | # Note: use '[/\\:.-]' here to ensure that we don't use the same name 314 | # that we are using for the .o file. Also, base the name on the expected 315 | # object file name, since that is what matters with a parallel build. 316 | lockdir=`echo "$cofile" | sed -e 's|[/\\:.-]|_|g'`.d 317 | while true; do 318 | if mkdir "$lockdir" >/dev/null 2>&1; then 319 | break 320 | fi 321 | sleep 1 322 | done 323 | # FIXME: race condition here if user kills between mkdir and trap. 324 | trap "rmdir '$lockdir'; exit 1" 1 2 15 325 | 326 | # Run the compile. 327 | "$@" 328 | ret=$? 329 | 330 | if test -f "$cofile"; then 331 | test "$cofile" = "$ofile" || mv "$cofile" "$ofile" 332 | elif test -f "${cofile}bj"; then 333 | test "${cofile}bj" = "$ofile" || mv "${cofile}bj" "$ofile" 334 | fi 335 | 336 | rmdir "$lockdir" 337 | exit $ret 338 | 339 | # Local Variables: 340 | # mode: shell-script 341 | # sh-indentation: 2 342 | # eval: (add-hook 'write-file-hooks 'time-stamp) 343 | # time-stamp-start: "scriptversion=" 344 | # time-stamp-format: "%:y-%02m-%02d.%02H" 345 | # time-stamp-time-zone: "UTC" 346 | # time-stamp-end: "; # UTC" 347 | # End: 348 | -------------------------------------------------------------------------------- /src/netif/tapif.c: -------------------------------------------------------------------------------- 1 | /** 2 | * based on lwip-contrib 3 | */ 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #include "lwip/opt.h" 13 | #include "lwip/ip.h" 14 | #include "lwip/snmp.h" 15 | #include "netif/etharp.h" 16 | 17 | #if defined(LWIP_DEBUG) && defined(LWIP_TCPDUMP) 18 | #include "netif/tcpdump.h" 19 | #endif /* LWIP_DEBUG && LWIP_TCPDUMP */ 20 | 21 | #include "netif/tapif.h" 22 | #include "netif/socket_util.h" 23 | 24 | #define IFCONFIG_BIN "/sbin/ifconfig " 25 | 26 | #if defined(LWIP_UNIX_LINUX) 27 | 28 | #include 29 | #include 30 | /* 31 | * Creating a tap interface requires special privileges. If the interfaces 32 | * is created in advance with `tunctl -u ` it can be opened as a regular 33 | * user. The network must already be configured. If DEVTAP_IF is defined it 34 | * will be opened instead of creating a new tap device. 35 | */ 36 | #ifndef DEVTAP 37 | #define DEVTAP "/dev/net/tun" 38 | #endif 39 | 40 | #define NETMASK_ARGS "netmask %d.%d.%d.%d" 41 | #define IFCONFIG_ARGS "%s inet %d.%d.%d.%d " NETMASK_ARGS 42 | #elif defined(LWIP_UNIX_OPENBSD) 43 | #define DEVTAP "/dev/tun0" 44 | #define NETMASK_ARGS "netmask %d.%d.%d.%d" 45 | #define IFCONFIG_ARGS "%s inet %d.%d.%d.%d " NETMASK_ARGS " link0" 46 | #else /* others */ 47 | #define DEVTAP "/dev/tap0" 48 | #define NETMASK_ARGS "netmask %d.%d.%d.%d" 49 | #define IFCONFIG_ARGS "%s inet %d.%d.%d.%d " NETMASK_ARGS 50 | #endif 51 | 52 | /* Define those to better describe your network interface. */ 53 | #define IFNAME0 't' 54 | #define IFNAME1 'p' 55 | 56 | #ifndef TAPIF_DEBUG 57 | #define TAPIF_DEBUG LWIP_DBG_OFF 58 | #endif 59 | 60 | struct tapif { 61 | /* Add whatever per-interface state that is needed here. */ 62 | int fd; 63 | }; 64 | 65 | /* Forward declarations. */ 66 | void tapif_input(struct netif *netif); 67 | 68 | int tap_create(char *dev) { 69 | int fd = -1; 70 | 71 | if ((fd = open(DEVTAP, O_RDWR)) < 0) { 72 | printf("open %s failed\n", DEVTAP); 73 | return fd; 74 | } 75 | 76 | #ifdef LWIP_UNIX_LINUX 77 | struct ifreq ifr; 78 | memset(&ifr, 0, sizeof(ifr)); 79 | ifr.ifr_flags = IFF_TAP | IFF_NO_PI; 80 | 81 | if (ioctl(fd, TUNSETIFF, (void *) &ifr) < 0) { 82 | printf("failed to open tap device\n"); 83 | close(fd); 84 | return -1; 85 | } 86 | strcpy(dev, ifr.ifr_name); 87 | 88 | printf("Open tun device: %s for reading...\n", ifr.ifr_name); 89 | #endif /* LWIP_UNIX_LINUX */ 90 | return fd; 91 | } 92 | 93 | /*-----------------------------------------------------------------------------------*/ 94 | static void 95 | low_level_init(struct netif *netif) { 96 | struct tapif *tapif; 97 | #if LWIP_IPV4 98 | int ret; 99 | char buf[1024]; 100 | #endif /* LWIP_IPV4 */ 101 | tapif = (struct tapif *) netif->state; 102 | 103 | #if defined(LWIP_UNIX_LINUX) 104 | char tap_name[IFNAMSIZ]; 105 | #endif 106 | tap_name[0] = '\0'; 107 | 108 | /* Obtain MAC address from network interface. */ 109 | 110 | /* (We just fake an address...) */ 111 | netif->hwaddr[0] = 0x02; 112 | netif->hwaddr[1] = 0x12; 113 | netif->hwaddr[2] = 0x34; 114 | netif->hwaddr[3] = 0x56; 115 | netif->hwaddr[4] = 0x78; 116 | netif->hwaddr[5] = 0xab; 117 | netif->hwaddr_len = 6; 118 | 119 | /* device capabilities */ 120 | netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_IGMP; 121 | 122 | tapif->fd = tap_create(tap_name); 123 | LWIP_DEBUGF(TAPIF_DEBUG, ("tapif_init: fd %d\n", tapif->fd)); 124 | if (tapif->fd == -1) { 125 | #ifdef LWIP_UNIX_LINUX 126 | perror("tapif_init: try running \"modprobe tun\" or rebuilding your kernel with CONFIG_TUN; cannot open "DEVTAP); 127 | #else /* LWIP_UNIX_LINUX */ 128 | perror("tapif_init: cannot open "DEVTAP); 129 | #endif /* LWIP_UNIX_LINUX */ 130 | exit(1); 131 | } 132 | 133 | setnonblocking(tapif->fd); 134 | 135 | netif_set_link_up(netif); 136 | 137 | #if LWIP_IPV4 138 | snprintf(buf, 1024, IFCONFIG_BIN 139 | IFCONFIG_ARGS, 140 | tap_name, 141 | ip4_addr1(netif_ip4_gw(netif)), 142 | ip4_addr2(netif_ip4_gw(netif)), 143 | ip4_addr3(netif_ip4_gw(netif)), 144 | ip4_addr4(netif_ip4_gw(netif)), 145 | ip4_addr1(netif_ip4_netmask(netif)), 146 | ip4_addr2(netif_ip4_netmask(netif)), 147 | ip4_addr3(netif_ip4_netmask(netif)), 148 | ip4_addr4(netif_ip4_netmask(netif)) 149 | ); 150 | 151 | LWIP_DEBUGF(TAPIF_DEBUG, ("tapif_init: system(\"%s\");\n", buf)); 152 | ret = system(buf); 153 | if (ret < 0) { 154 | perror("ifconfig failed"); 155 | exit(1); 156 | } 157 | if (ret != 0) { 158 | printf("ifconfig returned %d\n", ret); 159 | } 160 | #else /* LWIP_IPV4 */ 161 | perror("todo: support IPv6 support for non-preconfigured tapif"); 162 | exit(1); 163 | #endif /* LWIP_IPV4 */ 164 | } 165 | /*-----------------------------------------------------------------------------------*/ 166 | /* 167 | * low_level_output(): 168 | * 169 | * Should do the actual transmission of the packet. The packet is 170 | * contained in the pbuf that is passed to the function. This pbuf 171 | * might be chained. 172 | * 173 | */ 174 | /*-----------------------------------------------------------------------------------*/ 175 | 176 | static err_t 177 | low_level_output(struct netif *netif, struct pbuf *p) { 178 | struct tapif *tapif = (struct tapif *) netif->state; 179 | char buf[1514]; 180 | ssize_t written; 181 | 182 | #if 0 183 | if (((double)rand()/(double)RAND_MAX) < 0.2) { 184 | printf("drop output\n"); 185 | return ERR_OK; 186 | } 187 | #endif 188 | 189 | /* initiate transfer(); */ 190 | pbuf_copy_partial(p, buf, p->tot_len, 0); 191 | 192 | /* signal that packet should be sent(); */ 193 | written = write(tapif->fd, buf, p->tot_len); 194 | if (written == -1) { 195 | MIB2_STATS_NETIF_INC(netif, ifoutdiscards); 196 | perror("tapif: write"); 197 | } else { 198 | MIB2_STATS_NETIF_ADD(netif, ifoutoctets, written); 199 | } 200 | return ERR_OK; 201 | } 202 | /*-----------------------------------------------------------------------------------*/ 203 | /* 204 | * low_level_input(): 205 | * 206 | * Should allocate a pbuf and transfer the bytes of the incoming 207 | * packet from the interface into the pbuf. 208 | * 209 | */ 210 | /*-----------------------------------------------------------------------------------*/ 211 | static struct pbuf * 212 | low_level_input(struct netif *netif) { 213 | struct pbuf *p; 214 | u16_t len; 215 | char buf[1514]; 216 | struct tapif *tapif = (struct tapif *) netif->state; 217 | 218 | /* Obtain the size of the packet and put it into the "len" 219 | variable. */ 220 | len = read(tapif->fd, buf, sizeof(buf)); 221 | if (len == (u16_t) -1) { 222 | perror("read returned -1"); 223 | exit(1); 224 | } 225 | 226 | MIB2_STATS_NETIF_ADD(netif, ifinoctets, len); 227 | 228 | #if 0 229 | if (((double)rand()/(double)RAND_MAX) < 0.2) { 230 | printf("drop\n"); 231 | return NULL; 232 | } 233 | #endif 234 | 235 | /* We allocate a pbuf chain of pbufs from the pool. */ 236 | p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL); 237 | if (p != NULL) { 238 | pbuf_take(p, buf, len); 239 | /* acknowledge that packet has been read(); */ 240 | } else { 241 | /* drop packet(); */ 242 | MIB2_STATS_NETIF_INC(netif, ifindiscards); 243 | LWIP_DEBUGF(NETIF_DEBUG, ("tapif_input: could not allocate pbuf\n")); 244 | } 245 | 246 | return p; 247 | } 248 | 249 | /*-----------------------------------------------------------------------------------*/ 250 | /* 251 | * tapif_input(): 252 | * 253 | * This function should be called when a packet is ready to be read 254 | * from the interface. It uses the function low_level_input() that 255 | * should handle the actual reception of bytes from the network 256 | * interface. 257 | * 258 | */ 259 | /*-----------------------------------------------------------------------------------*/ 260 | void 261 | tapif_input(struct netif *netif) { 262 | struct pbuf *p = low_level_input(netif); 263 | 264 | if (p == NULL) { 265 | #if LINK_STATS 266 | LINK_STATS_INC(link.recv); 267 | #endif /* LINK_STATS */ 268 | LWIP_DEBUGF(TAPIF_DEBUG, ("tapif_input: low_level_input returned NULL\n")); 269 | return; 270 | } 271 | 272 | err_t err = netif->input(p, netif); 273 | if (err != ERR_OK) { 274 | printf("============================> tapif_input: netif input error %d\n", err); 275 | pbuf_free(p); 276 | } 277 | } 278 | /*-----------------------------------------------------------------------------------*/ 279 | /* 280 | * tapif_init(): 281 | * 282 | * Should be called at the beginning of the program to set up the 283 | * network interface. It calls the function low_level_init() to do the 284 | * actual setup of the hardware. 285 | * 286 | */ 287 | /*-----------------------------------------------------------------------------------*/ 288 | err_t 289 | tapif_init(struct netif *netif) { 290 | struct tapif *tapif = (struct tapif *) mem_malloc(sizeof(struct tapif)); 291 | 292 | if (tapif == NULL) { 293 | LWIP_DEBUGF(NETIF_DEBUG, ("tapif_init: out of memory for tapif\n")); 294 | return ERR_MEM; 295 | } 296 | netif->state = tapif; 297 | MIB2_INIT_NETIF(netif, snmp_ifType_other, 100000000); 298 | 299 | netif->name[0] = IFNAME0; 300 | netif->name[1] = IFNAME1; 301 | #if LWIP_IPV4 302 | netif->output = etharp_output; 303 | #endif /* LWIP_IPV4 */ 304 | #if LWIP_IPV6 305 | netif->output_ip6 = ethip6_output; 306 | #endif /* LWIP_IPV6 */ 307 | netif->linkoutput = low_level_output; 308 | netif->mtu = 1500; 309 | 310 | low_level_init(netif); 311 | 312 | return ERR_OK; 313 | } 314 | -------------------------------------------------------------------------------- /libev/ev_select.c: -------------------------------------------------------------------------------- 1 | /* 2 | * libev select fd activity backend 3 | * 4 | * Copyright (c) 2007,2008,2009,2010,2011 Marc Alexander Lehmann 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without modifica- 8 | * tion, are permitted provided that the following conditions are met: 9 | * 10 | * 1. Redistributions of source code must retain the above copyright notice, 11 | * this list of conditions and the following disclaimer. 12 | * 13 | * 2. Redistributions in binary form must reproduce the above copyright 14 | * notice, this list of conditions and the following disclaimer in the 15 | * documentation and/or other materials provided with the distribution. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 18 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MER- 19 | * CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 20 | * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPE- 21 | * CIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 22 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 23 | * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 24 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTH- 25 | * ERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 26 | * OF THE POSSIBILITY OF SUCH DAMAGE. 27 | * 28 | * Alternatively, the contents of this file may be used under the terms of 29 | * the GNU General Public License ("GPL") version 2 or any later version, 30 | * in which case the provisions of the GPL are applicable instead of 31 | * the above. If you wish to allow the use of your version of this file 32 | * only under the terms of the GPL and not to allow others to use your 33 | * version of this file under the BSD license, indicate your decision 34 | * by deleting the provisions above and replace them with the notice 35 | * and other provisions required by the GPL. If you do not delete the 36 | * provisions above, a recipient may use your version of this file under 37 | * either the BSD or the GPL. 38 | */ 39 | 40 | #ifndef _WIN32 41 | /* for unix systems */ 42 | # include 43 | # ifndef __hpux 44 | /* for REAL unix systems */ 45 | # include 46 | # endif 47 | #endif 48 | 49 | #ifndef EV_SELECT_USE_FD_SET 50 | # ifdef NFDBITS 51 | # define EV_SELECT_USE_FD_SET 0 52 | # else 53 | # define EV_SELECT_USE_FD_SET 1 54 | # endif 55 | #endif 56 | 57 | #if EV_SELECT_IS_WINSOCKET 58 | # undef EV_SELECT_USE_FD_SET 59 | # define EV_SELECT_USE_FD_SET 1 60 | # undef NFDBITS 61 | # define NFDBITS 0 62 | #endif 63 | 64 | #if !EV_SELECT_USE_FD_SET 65 | # define NFDBYTES (NFDBITS / 8) 66 | #endif 67 | 68 | #include 69 | 70 | static void 71 | select_modify (EV_P_ int fd, int oev, int nev) 72 | { 73 | if (oev == nev) 74 | return; 75 | 76 | { 77 | #if EV_SELECT_USE_FD_SET 78 | 79 | #if EV_SELECT_IS_WINSOCKET 80 | SOCKET handle = anfds [fd].handle; 81 | #else 82 | int handle = fd; 83 | #endif 84 | 85 | assert (("libev: fd >= FD_SETSIZE passed to fd_set-based select backend", fd < FD_SETSIZE)); 86 | 87 | /* FD_SET is broken on windows (it adds the fd to a set twice or more, 88 | * which eventually leads to overflows). Need to call it only on changes. 89 | */ 90 | #if EV_SELECT_IS_WINSOCKET 91 | if ((oev ^ nev) & EV_READ) 92 | #endif 93 | if (nev & EV_READ) 94 | FD_SET (handle, (fd_set *)vec_ri); 95 | else 96 | FD_CLR (handle, (fd_set *)vec_ri); 97 | 98 | #if EV_SELECT_IS_WINSOCKET 99 | if ((oev ^ nev) & EV_WRITE) 100 | #endif 101 | if (nev & EV_WRITE) 102 | FD_SET (handle, (fd_set *)vec_wi); 103 | else 104 | FD_CLR (handle, (fd_set *)vec_wi); 105 | 106 | #else 107 | 108 | int word = fd / NFDBITS; 109 | fd_mask mask = 1UL << (fd % NFDBITS); 110 | 111 | if (expect_false (vec_max <= word)) 112 | { 113 | int new_max = word + 1; 114 | 115 | vec_ri = ev_realloc (vec_ri, new_max * NFDBYTES); 116 | vec_ro = ev_realloc (vec_ro, new_max * NFDBYTES); /* could free/malloc */ 117 | vec_wi = ev_realloc (vec_wi, new_max * NFDBYTES); 118 | vec_wo = ev_realloc (vec_wo, new_max * NFDBYTES); /* could free/malloc */ 119 | #ifdef _WIN32 120 | vec_eo = ev_realloc (vec_eo, new_max * NFDBYTES); /* could free/malloc */ 121 | #endif 122 | 123 | for (; vec_max < new_max; ++vec_max) 124 | ((fd_mask *)vec_ri) [vec_max] = 125 | ((fd_mask *)vec_wi) [vec_max] = 0; 126 | } 127 | 128 | ((fd_mask *)vec_ri) [word] |= mask; 129 | if (!(nev & EV_READ)) 130 | ((fd_mask *)vec_ri) [word] &= ~mask; 131 | 132 | ((fd_mask *)vec_wi) [word] |= mask; 133 | if (!(nev & EV_WRITE)) 134 | ((fd_mask *)vec_wi) [word] &= ~mask; 135 | #endif 136 | } 137 | } 138 | 139 | static void 140 | select_poll (EV_P_ ev_tstamp timeout) 141 | { 142 | struct timeval tv; 143 | int res; 144 | int fd_setsize; 145 | 146 | EV_RELEASE_CB; 147 | EV_TV_SET (tv, timeout); 148 | 149 | #if EV_SELECT_USE_FD_SET 150 | fd_setsize = sizeof (fd_set); 151 | #else 152 | fd_setsize = vec_max * NFDBYTES; 153 | #endif 154 | 155 | memcpy (vec_ro, vec_ri, fd_setsize); 156 | memcpy (vec_wo, vec_wi, fd_setsize); 157 | 158 | #ifdef _WIN32 159 | /* pass in the write set as except set. 160 | * the idea behind this is to work around a windows bug that causes 161 | * errors to be reported as an exception and not by setting 162 | * the writable bit. this is so uncontrollably lame. 163 | */ 164 | memcpy (vec_eo, vec_wi, fd_setsize); 165 | res = select (vec_max * NFDBITS, (fd_set *)vec_ro, (fd_set *)vec_wo, (fd_set *)vec_eo, &tv); 166 | #elif EV_SELECT_USE_FD_SET 167 | fd_setsize = anfdmax < FD_SETSIZE ? anfdmax : FD_SETSIZE; 168 | res = select (fd_setsize, (fd_set *)vec_ro, (fd_set *)vec_wo, 0, &tv); 169 | #else 170 | res = select (vec_max * NFDBITS, (fd_set *)vec_ro, (fd_set *)vec_wo, 0, &tv); 171 | #endif 172 | EV_ACQUIRE_CB; 173 | 174 | if (expect_false (res < 0)) 175 | { 176 | #if EV_SELECT_IS_WINSOCKET 177 | errno = WSAGetLastError (); 178 | #endif 179 | #ifdef WSABASEERR 180 | /* on windows, select returns incompatible error codes, fix this */ 181 | if (errno >= WSABASEERR && errno < WSABASEERR + 1000) 182 | if (errno == WSAENOTSOCK) 183 | errno = EBADF; 184 | else 185 | errno -= WSABASEERR; 186 | #endif 187 | 188 | #ifdef _WIN32 189 | /* select on windows erroneously returns EINVAL when no fd sets have been 190 | * provided (this is documented). what microsoft doesn't tell you that this bug 191 | * exists even when the fd sets _are_ provided, so we have to check for this bug 192 | * here and emulate by sleeping manually. 193 | * we also get EINVAL when the timeout is invalid, but we ignore this case here 194 | * and assume that EINVAL always means: you have to wait manually. 195 | */ 196 | if (errno == EINVAL) 197 | { 198 | if (timeout) 199 | { 200 | unsigned long ms = timeout * 1e3; 201 | Sleep (ms ? ms : 1); 202 | } 203 | 204 | return; 205 | } 206 | #endif 207 | 208 | if (errno == EBADF) 209 | fd_ebadf (EV_A); 210 | else if (errno == ENOMEM && !syserr_cb) 211 | fd_enomem (EV_A); 212 | else if (errno != EINTR) 213 | ev_syserr ("(libev) select"); 214 | 215 | return; 216 | } 217 | 218 | #if EV_SELECT_USE_FD_SET 219 | 220 | { 221 | int fd; 222 | 223 | for (fd = 0; fd < anfdmax; ++fd) 224 | if (anfds [fd].events) 225 | { 226 | int events = 0; 227 | #if EV_SELECT_IS_WINSOCKET 228 | SOCKET handle = anfds [fd].handle; 229 | #else 230 | int handle = fd; 231 | #endif 232 | 233 | if (FD_ISSET (handle, (fd_set *)vec_ro)) events |= EV_READ; 234 | if (FD_ISSET (handle, (fd_set *)vec_wo)) events |= EV_WRITE; 235 | #ifdef _WIN32 236 | if (FD_ISSET (handle, (fd_set *)vec_eo)) events |= EV_WRITE; 237 | #endif 238 | 239 | if (expect_true (events)) 240 | fd_event (EV_A_ fd, events); 241 | } 242 | } 243 | 244 | #else 245 | 246 | { 247 | int word, bit; 248 | for (word = vec_max; word--; ) 249 | { 250 | fd_mask word_r = ((fd_mask *)vec_ro) [word]; 251 | fd_mask word_w = ((fd_mask *)vec_wo) [word]; 252 | #ifdef _WIN32 253 | word_w |= ((fd_mask *)vec_eo) [word]; 254 | #endif 255 | 256 | if (word_r || word_w) 257 | for (bit = NFDBITS; bit--; ) 258 | { 259 | fd_mask mask = 1UL << bit; 260 | int events = 0; 261 | 262 | events |= word_r & mask ? EV_READ : 0; 263 | events |= word_w & mask ? EV_WRITE : 0; 264 | 265 | if (expect_true (events)) 266 | fd_event (EV_A_ word * NFDBITS + bit, events); 267 | } 268 | } 269 | } 270 | 271 | #endif 272 | } 273 | 274 | inline_size 275 | int 276 | select_init (EV_P_ int flags) 277 | { 278 | backend_mintime = 1e-6; 279 | backend_modify = select_modify; 280 | backend_poll = select_poll; 281 | 282 | #if EV_SELECT_USE_FD_SET 283 | vec_ri = ev_malloc (sizeof (fd_set)); FD_ZERO ((fd_set *)vec_ri); 284 | vec_ro = ev_malloc (sizeof (fd_set)); 285 | vec_wi = ev_malloc (sizeof (fd_set)); FD_ZERO ((fd_set *)vec_wi); 286 | vec_wo = ev_malloc (sizeof (fd_set)); 287 | #ifdef _WIN32 288 | vec_eo = ev_malloc (sizeof (fd_set)); 289 | #endif 290 | #else 291 | vec_max = 0; 292 | vec_ri = 0; 293 | vec_ro = 0; 294 | vec_wi = 0; 295 | vec_wo = 0; 296 | #ifdef _WIN32 297 | vec_eo = 0; 298 | #endif 299 | #endif 300 | 301 | return EVBACKEND_SELECT; 302 | } 303 | 304 | inline_size 305 | void 306 | select_destroy (EV_P) 307 | { 308 | ev_free (vec_ri); 309 | ev_free (vec_ro); 310 | ev_free (vec_wi); 311 | ev_free (vec_wo); 312 | #ifdef _WIN32 313 | ev_free (vec_eo); 314 | #endif 315 | } 316 | 317 | -------------------------------------------------------------------------------- /libev/ev_epoll.c: -------------------------------------------------------------------------------- 1 | /* 2 | * libev epoll fd activity backend 3 | * 4 | * Copyright (c) 2007,2008,2009,2010,2011 Marc Alexander Lehmann 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without modifica- 8 | * tion, are permitted provided that the following conditions are met: 9 | * 10 | * 1. Redistributions of source code must retain the above copyright notice, 11 | * this list of conditions and the following disclaimer. 12 | * 13 | * 2. Redistributions in binary form must reproduce the above copyright 14 | * notice, this list of conditions and the following disclaimer in the 15 | * documentation and/or other materials provided with the distribution. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 18 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MER- 19 | * CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 20 | * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPE- 21 | * CIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 22 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 23 | * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 24 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTH- 25 | * ERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 26 | * OF THE POSSIBILITY OF SUCH DAMAGE. 27 | * 28 | * Alternatively, the contents of this file may be used under the terms of 29 | * the GNU General Public License ("GPL") version 2 or any later version, 30 | * in which case the provisions of the GPL are applicable instead of 31 | * the above. If you wish to allow the use of your version of this file 32 | * only under the terms of the GPL and not to allow others to use your 33 | * version of this file under the BSD license, indicate your decision 34 | * by deleting the provisions above and replace them with the notice 35 | * and other provisions required by the GPL. If you do not delete the 36 | * provisions above, a recipient may use your version of this file under 37 | * either the BSD or the GPL. 38 | */ 39 | 40 | /* 41 | * general notes about epoll: 42 | * 43 | * a) epoll silently removes fds from the fd set. as nothing tells us 44 | * that an fd has been removed otherwise, we have to continually 45 | * "rearm" fds that we suspect *might* have changed (same 46 | * problem with kqueue, but much less costly there). 47 | * b) the fact that ADD != MOD creates a lot of extra syscalls due to a) 48 | * and seems not to have any advantage. 49 | * c) the inability to handle fork or file descriptors (think dup) 50 | * limits the applicability over poll, so this is not a generic 51 | * poll replacement. 52 | * d) epoll doesn't work the same as select with many file descriptors 53 | * (such as files). while not critical, no other advanced interface 54 | * seems to share this (rather non-unixy) limitation. 55 | * e) epoll claims to be embeddable, but in practise you never get 56 | * a ready event for the epoll fd (broken: <=2.6.26, working: >=2.6.32). 57 | * f) epoll_ctl returning EPERM means the fd is always ready. 58 | * 59 | * lots of "weird code" and complication handling in this file is due 60 | * to these design problems with epoll, as we try very hard to avoid 61 | * epoll_ctl syscalls for common usage patterns and handle the breakage 62 | * ensuing from receiving events for closed and otherwise long gone 63 | * file descriptors. 64 | */ 65 | 66 | #include 67 | 68 | #define EV_EMASK_EPERM 0x80 69 | 70 | static void 71 | epoll_modify (EV_P_ int fd, int oev, int nev) 72 | { 73 | struct epoll_event ev; 74 | unsigned char oldmask; 75 | 76 | /* 77 | * we handle EPOLL_CTL_DEL by ignoring it here 78 | * on the assumption that the fd is gone anyways 79 | * if that is wrong, we have to handle the spurious 80 | * event in epoll_poll. 81 | * if the fd is added again, we try to ADD it, and, if that 82 | * fails, we assume it still has the same eventmask. 83 | */ 84 | if (!nev) 85 | return; 86 | 87 | oldmask = anfds [fd].emask; 88 | anfds [fd].emask = nev; 89 | 90 | /* store the generation counter in the upper 32 bits, the fd in the lower 32 bits */ 91 | ev.data.u64 = (uint64_t)(uint32_t)fd 92 | | ((uint64_t)(uint32_t)++anfds [fd].egen << 32); 93 | ev.events = (nev & EV_READ ? EPOLLIN : 0) 94 | | (nev & EV_WRITE ? EPOLLOUT : 0); 95 | 96 | if (expect_true (!epoll_ctl (backend_fd, oev && oldmask != nev ? EPOLL_CTL_MOD : EPOLL_CTL_ADD, fd, &ev))) 97 | return; 98 | 99 | if (expect_true (errno == ENOENT)) 100 | { 101 | /* if ENOENT then the fd went away, so try to do the right thing */ 102 | if (!nev) 103 | goto dec_egen; 104 | 105 | if (!epoll_ctl (backend_fd, EPOLL_CTL_ADD, fd, &ev)) 106 | return; 107 | } 108 | else if (expect_true (errno == EEXIST)) 109 | { 110 | /* EEXIST means we ignored a previous DEL, but the fd is still active */ 111 | /* if the kernel mask is the same as the new mask, we assume it hasn't changed */ 112 | if (oldmask == nev) 113 | goto dec_egen; 114 | 115 | if (!epoll_ctl (backend_fd, EPOLL_CTL_MOD, fd, &ev)) 116 | return; 117 | } 118 | else if (expect_true (errno == EPERM)) 119 | { 120 | /* EPERM means the fd is always ready, but epoll is too snobbish */ 121 | /* to handle it, unlike select or poll. */ 122 | anfds [fd].emask = EV_EMASK_EPERM; 123 | 124 | /* add fd to epoll_eperms, if not already inside */ 125 | if (!(oldmask & EV_EMASK_EPERM)) 126 | { 127 | array_needsize (int, epoll_eperms, epoll_epermmax, epoll_epermcnt + 1, EMPTY2); 128 | epoll_eperms [epoll_epermcnt++] = fd; 129 | } 130 | 131 | return; 132 | } 133 | 134 | fd_kill (EV_A_ fd); 135 | 136 | dec_egen: 137 | /* we didn't successfully call epoll_ctl, so decrement the generation counter again */ 138 | --anfds [fd].egen; 139 | } 140 | 141 | static void 142 | epoll_poll (EV_P_ ev_tstamp timeout) 143 | { 144 | int i; 145 | int eventcnt; 146 | 147 | if (expect_false (epoll_epermcnt)) 148 | timeout = 0.; 149 | 150 | /* epoll wait times cannot be larger than (LONG_MAX - 999UL) / HZ msecs, which is below */ 151 | /* the default libev max wait time, however. */ 152 | EV_RELEASE_CB; 153 | eventcnt = epoll_wait (backend_fd, epoll_events, epoll_eventmax, timeout * 1e3); 154 | EV_ACQUIRE_CB; 155 | 156 | if (expect_false (eventcnt < 0)) 157 | { 158 | if (errno != EINTR) 159 | ev_syserr ("(libev) epoll_wait"); 160 | 161 | return; 162 | } 163 | 164 | for (i = 0; i < eventcnt; ++i) 165 | { 166 | struct epoll_event *ev = epoll_events + i; 167 | 168 | int fd = (uint32_t)ev->data.u64; /* mask out the lower 32 bits */ 169 | int want = anfds [fd].events; 170 | int got = (ev->events & (EPOLLOUT | EPOLLERR | EPOLLHUP) ? EV_WRITE : 0) 171 | | (ev->events & (EPOLLIN | EPOLLERR | EPOLLHUP) ? EV_READ : 0); 172 | 173 | /* 174 | * check for spurious notification. 175 | * this only finds spurious notifications on egen updates 176 | * other spurious notifications will be found by epoll_ctl, below 177 | * we assume that fd is always in range, as we never shrink the anfds array 178 | */ 179 | if (expect_false ((uint32_t)anfds [fd].egen != (uint32_t)(ev->data.u64 >> 32))) 180 | { 181 | /* recreate kernel state */ 182 | postfork |= 2; 183 | continue; 184 | } 185 | 186 | if (expect_false (got & ~want)) 187 | { 188 | anfds [fd].emask = want; 189 | 190 | /* 191 | * we received an event but are not interested in it, try mod or del 192 | * this often happens because we optimistically do not unregister fds 193 | * when we are no longer interested in them, but also when we get spurious 194 | * notifications for fds from another process. this is partially handled 195 | * above with the gencounter check (== our fd is not the event fd), and 196 | * partially here, when epoll_ctl returns an error (== a child has the fd 197 | * but we closed it). 198 | */ 199 | ev->events = (want & EV_READ ? EPOLLIN : 0) 200 | | (want & EV_WRITE ? EPOLLOUT : 0); 201 | 202 | /* pre-2.6.9 kernels require a non-null pointer with EPOLL_CTL_DEL, */ 203 | /* which is fortunately easy to do for us. */ 204 | if (epoll_ctl (backend_fd, want ? EPOLL_CTL_MOD : EPOLL_CTL_DEL, fd, ev)) 205 | { 206 | postfork |= 2; /* an error occurred, recreate kernel state */ 207 | continue; 208 | } 209 | } 210 | 211 | fd_event (EV_A_ fd, got); 212 | } 213 | 214 | /* if the receive array was full, increase its size */ 215 | if (expect_false (eventcnt == epoll_eventmax)) 216 | { 217 | ev_free (epoll_events); 218 | epoll_eventmax = array_nextsize (sizeof (struct epoll_event), epoll_eventmax, epoll_eventmax + 1); 219 | epoll_events = (struct epoll_event *)ev_malloc (sizeof (struct epoll_event) * epoll_eventmax); 220 | } 221 | 222 | /* now synthesize events for all fds where epoll fails, while select works... */ 223 | for (i = epoll_epermcnt; i--; ) 224 | { 225 | int fd = epoll_eperms [i]; 226 | unsigned char events = anfds [fd].events & (EV_READ | EV_WRITE); 227 | 228 | if (anfds [fd].emask & EV_EMASK_EPERM && events) 229 | fd_event (EV_A_ fd, events); 230 | else 231 | { 232 | epoll_eperms [i] = epoll_eperms [--epoll_epermcnt]; 233 | anfds [fd].emask = 0; 234 | } 235 | } 236 | } 237 | 238 | inline_size 239 | int 240 | epoll_init (EV_P_ int flags) 241 | { 242 | #ifdef EPOLL_CLOEXEC 243 | backend_fd = epoll_create1 (EPOLL_CLOEXEC); 244 | 245 | if (backend_fd < 0 && (errno == EINVAL || errno == ENOSYS)) 246 | #endif 247 | backend_fd = epoll_create (256); 248 | 249 | if (backend_fd < 0) 250 | return 0; 251 | 252 | fcntl (backend_fd, F_SETFD, FD_CLOEXEC); 253 | 254 | backend_mintime = 1e-3; /* epoll does sometimes return early, this is just to avoid the worst */ 255 | backend_modify = epoll_modify; 256 | backend_poll = epoll_poll; 257 | 258 | epoll_eventmax = 64; /* initial number of events receivable per poll */ 259 | epoll_events = (struct epoll_event *)ev_malloc (sizeof (struct epoll_event) * epoll_eventmax); 260 | 261 | return EVBACKEND_EPOLL; 262 | } 263 | 264 | inline_size 265 | void 266 | epoll_destroy (EV_P) 267 | { 268 | ev_free (epoll_events); 269 | array_free (epoll_eperm, EMPTY); 270 | } 271 | 272 | inline_size 273 | void 274 | epoll_fork (EV_P) 275 | { 276 | close (backend_fd); 277 | 278 | while ((backend_fd = epoll_create (256)) < 0) 279 | ev_syserr ("(libev) epoll_create"); 280 | 281 | fcntl (backend_fd, F_SETFD, FD_CLOEXEC); 282 | 283 | fd_rearm_all (EV_A); 284 | } 285 | 286 | -------------------------------------------------------------------------------- /libev/event.c: -------------------------------------------------------------------------------- 1 | /* 2 | * libevent compatibility layer 3 | * 4 | * Copyright (c) 2007,2008,2009,2010,2012 Marc Alexander Lehmann 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without modifica- 8 | * tion, are permitted provided that the following conditions are met: 9 | * 10 | * 1. Redistributions of source code must retain the above copyright notice, 11 | * this list of conditions and the following disclaimer. 12 | * 13 | * 2. Redistributions in binary form must reproduce the above copyright 14 | * notice, this list of conditions and the following disclaimer in the 15 | * documentation and/or other materials provided with the distribution. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 18 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MER- 19 | * CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 20 | * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPE- 21 | * CIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 22 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 23 | * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 24 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTH- 25 | * ERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 26 | * OF THE POSSIBILITY OF SUCH DAMAGE. 27 | * 28 | * Alternatively, the contents of this file may be used under the terms of 29 | * the GNU General Public License ("GPL") version 2 or any later version, 30 | * in which case the provisions of the GPL are applicable instead of 31 | * the above. If you wish to allow the use of your version of this file 32 | * only under the terms of the GPL and not to allow others to use your 33 | * version of this file under the BSD license, indicate your decision 34 | * by deleting the provisions above and replace them with the notice 35 | * and other provisions required by the GPL. If you do not delete the 36 | * provisions above, a recipient may use your version of this file under 37 | * either the BSD or the GPL. 38 | */ 39 | 40 | #include 41 | #include 42 | #include 43 | 44 | #ifdef EV_EVENT_H 45 | # include EV_EVENT_H 46 | #else 47 | # include "event.h" 48 | #endif 49 | 50 | #if EV_MULTIPLICITY 51 | # define dLOOPev struct ev_loop *loop = (struct ev_loop *)ev->ev_base 52 | # define dLOOPbase struct ev_loop *loop = (struct ev_loop *)base 53 | #else 54 | # define dLOOPev 55 | # define dLOOPbase 56 | #endif 57 | 58 | /* never accessed, will always be cast from/to ev_loop */ 59 | struct event_base 60 | { 61 | int dummy; 62 | }; 63 | 64 | static struct event_base *ev_x_cur; 65 | 66 | static ev_tstamp 67 | ev_tv_get (struct timeval *tv) 68 | { 69 | if (tv) 70 | { 71 | ev_tstamp after = tv->tv_sec + tv->tv_usec * 1e-6; 72 | return after ? after : 1e-6; 73 | } 74 | else 75 | return -1.; 76 | } 77 | 78 | #define EVENT_STRINGIFY(s) # s 79 | #define EVENT_VERSION(a,b) EVENT_STRINGIFY (a) "." EVENT_STRINGIFY (b) 80 | 81 | const char * 82 | event_get_version (void) 83 | { 84 | /* returns ABI, not API or library, version */ 85 | return EVENT_VERSION (EV_VERSION_MAJOR, EV_VERSION_MINOR); 86 | } 87 | 88 | const char * 89 | event_get_method (void) 90 | { 91 | return "libev"; 92 | } 93 | 94 | void *event_init (void) 95 | { 96 | #if EV_MULTIPLICITY 97 | if (ev_x_cur) 98 | ev_x_cur = (struct event_base *)ev_loop_new (EVFLAG_AUTO); 99 | else 100 | ev_x_cur = (struct event_base *)ev_default_loop (EVFLAG_AUTO); 101 | #else 102 | assert (("libev: multiple event bases not supported when not compiled with EV_MULTIPLICITY", !ev_x_cur)); 103 | 104 | ev_x_cur = (struct event_base *)(long)ev_default_loop (EVFLAG_AUTO); 105 | #endif 106 | 107 | return ev_x_cur; 108 | } 109 | 110 | const char * 111 | event_base_get_method (const struct event_base *base) 112 | { 113 | return "libev"; 114 | } 115 | 116 | struct event_base * 117 | event_base_new (void) 118 | { 119 | #if EV_MULTIPLICITY 120 | return (struct event_base *)ev_loop_new (EVFLAG_AUTO); 121 | #else 122 | assert (("libev: multiple event bases not supported when not compiled with EV_MULTIPLICITY")); 123 | return NULL; 124 | #endif 125 | } 126 | 127 | void event_base_free (struct event_base *base) 128 | { 129 | dLOOPbase; 130 | 131 | #if EV_MULTIPLICITY 132 | if (!ev_is_default_loop (loop)) 133 | ev_loop_destroy (loop); 134 | #endif 135 | } 136 | 137 | int event_dispatch (void) 138 | { 139 | return event_base_dispatch (ev_x_cur); 140 | } 141 | 142 | #ifdef EV_STANDALONE 143 | void event_set_log_callback (event_log_cb cb) 144 | { 145 | /* nop */ 146 | } 147 | #endif 148 | 149 | int event_loop (int flags) 150 | { 151 | return event_base_loop (ev_x_cur, flags); 152 | } 153 | 154 | int event_loopexit (struct timeval *tv) 155 | { 156 | return event_base_loopexit (ev_x_cur, tv); 157 | } 158 | 159 | event_callback_fn event_get_callback 160 | (const struct event *ev) 161 | { 162 | return ev->ev_callback; 163 | } 164 | 165 | static void 166 | ev_x_cb (struct event *ev, int revents) 167 | { 168 | revents &= EV_READ | EV_WRITE | EV_TIMER | EV_SIGNAL; 169 | 170 | ev->ev_res = revents; 171 | ev->ev_callback (ev->ev_fd, (short)revents, ev->ev_arg); 172 | } 173 | 174 | static void 175 | ev_x_cb_sig (EV_P_ struct ev_signal *w, int revents) 176 | { 177 | struct event *ev = (struct event *)(((char *)w) - offsetof (struct event, iosig.sig)); 178 | 179 | if (revents & EV_ERROR) 180 | event_del (ev); 181 | 182 | ev_x_cb (ev, revents); 183 | } 184 | 185 | static void 186 | ev_x_cb_io (EV_P_ struct ev_io *w, int revents) 187 | { 188 | struct event *ev = (struct event *)(((char *)w) - offsetof (struct event, iosig.io)); 189 | 190 | if ((revents & EV_ERROR) || !(ev->ev_events & EV_PERSIST)) 191 | event_del (ev); 192 | 193 | ev_x_cb (ev, revents); 194 | } 195 | 196 | static void 197 | ev_x_cb_to (EV_P_ struct ev_timer *w, int revents) 198 | { 199 | struct event *ev = (struct event *)(((char *)w) - offsetof (struct event, to)); 200 | 201 | event_del (ev); 202 | 203 | ev_x_cb (ev, revents); 204 | } 205 | 206 | void event_set (struct event *ev, int fd, short events, void (*cb)(int, short, void *), void *arg) 207 | { 208 | if (events & EV_SIGNAL) 209 | ev_init (&ev->iosig.sig, ev_x_cb_sig); 210 | else 211 | ev_init (&ev->iosig.io, ev_x_cb_io); 212 | 213 | ev_init (&ev->to, ev_x_cb_to); 214 | 215 | ev->ev_base = ev_x_cur; /* not threadsafe, but it's how libevent works */ 216 | ev->ev_fd = fd; 217 | ev->ev_events = events; 218 | ev->ev_pri = 0; 219 | ev->ev_callback = cb; 220 | ev->ev_arg = arg; 221 | ev->ev_res = 0; 222 | ev->ev_flags = EVLIST_INIT; 223 | } 224 | 225 | int event_once (int fd, short events, void (*cb)(int, short, void *), void *arg, struct timeval *tv) 226 | { 227 | return event_base_once (ev_x_cur, fd, events, cb, arg, tv); 228 | } 229 | 230 | int event_add (struct event *ev, struct timeval *tv) 231 | { 232 | dLOOPev; 233 | 234 | if (ev->ev_events & EV_SIGNAL) 235 | { 236 | if (!ev_is_active (&ev->iosig.sig)) 237 | { 238 | ev_signal_set (&ev->iosig.sig, ev->ev_fd); 239 | ev_signal_start (EV_A_ &ev->iosig.sig); 240 | 241 | ev->ev_flags |= EVLIST_SIGNAL; 242 | } 243 | } 244 | else if (ev->ev_events & (EV_READ | EV_WRITE)) 245 | { 246 | if (!ev_is_active (&ev->iosig.io)) 247 | { 248 | ev_io_set (&ev->iosig.io, ev->ev_fd, ev->ev_events & (EV_READ | EV_WRITE)); 249 | ev_io_start (EV_A_ &ev->iosig.io); 250 | 251 | ev->ev_flags |= EVLIST_INSERTED; 252 | } 253 | } 254 | 255 | if (tv) 256 | { 257 | ev->to.repeat = ev_tv_get (tv); 258 | ev_timer_again (EV_A_ &ev->to); 259 | ev->ev_flags |= EVLIST_TIMEOUT; 260 | } 261 | else 262 | { 263 | ev_timer_stop (EV_A_ &ev->to); 264 | ev->ev_flags &= ~EVLIST_TIMEOUT; 265 | } 266 | 267 | ev->ev_flags |= EVLIST_ACTIVE; 268 | 269 | return 0; 270 | } 271 | 272 | int event_del (struct event *ev) 273 | { 274 | dLOOPev; 275 | 276 | if (ev->ev_events & EV_SIGNAL) 277 | ev_signal_stop (EV_A_ &ev->iosig.sig); 278 | else if (ev->ev_events & (EV_READ | EV_WRITE)) 279 | ev_io_stop (EV_A_ &ev->iosig.io); 280 | 281 | if (ev_is_active (&ev->to)) 282 | ev_timer_stop (EV_A_ &ev->to); 283 | 284 | ev->ev_flags = EVLIST_INIT; 285 | 286 | return 0; 287 | } 288 | 289 | void event_active (struct event *ev, int res, short ncalls) 290 | { 291 | dLOOPev; 292 | 293 | if (res & EV_TIMEOUT) 294 | ev_feed_event (EV_A_ &ev->to, res & EV_TIMEOUT); 295 | 296 | if (res & EV_SIGNAL) 297 | ev_feed_event (EV_A_ &ev->iosig.sig, res & EV_SIGNAL); 298 | 299 | if (res & (EV_READ | EV_WRITE)) 300 | ev_feed_event (EV_A_ &ev->iosig.io, res & (EV_READ | EV_WRITE)); 301 | } 302 | 303 | int event_pending (struct event *ev, short events, struct timeval *tv) 304 | { 305 | short revents = 0; 306 | dLOOPev; 307 | 308 | if (ev->ev_events & EV_SIGNAL) 309 | { 310 | /* sig */ 311 | if (ev_is_active (&ev->iosig.sig) || ev_is_pending (&ev->iosig.sig)) 312 | revents |= EV_SIGNAL; 313 | } 314 | else if (ev->ev_events & (EV_READ | EV_WRITE)) 315 | { 316 | /* io */ 317 | if (ev_is_active (&ev->iosig.io) || ev_is_pending (&ev->iosig.io)) 318 | revents |= ev->ev_events & (EV_READ | EV_WRITE); 319 | } 320 | 321 | if (ev->ev_events & EV_TIMEOUT || ev_is_active (&ev->to) || ev_is_pending (&ev->to)) 322 | { 323 | revents |= EV_TIMEOUT; 324 | 325 | if (tv) 326 | { 327 | ev_tstamp at = ev_now (EV_A); 328 | 329 | tv->tv_sec = (long)at; 330 | tv->tv_usec = (long)((at - (ev_tstamp)tv->tv_sec) * 1e6); 331 | } 332 | } 333 | 334 | return events & revents; 335 | } 336 | 337 | int event_priority_init (int npri) 338 | { 339 | return event_base_priority_init (ev_x_cur, npri); 340 | } 341 | 342 | int event_priority_set (struct event *ev, int pri) 343 | { 344 | ev->ev_pri = pri; 345 | 346 | return 0; 347 | } 348 | 349 | int event_base_set (struct event_base *base, struct event *ev) 350 | { 351 | ev->ev_base = base; 352 | 353 | return 0; 354 | } 355 | 356 | int event_base_loop (struct event_base *base, int flags) 357 | { 358 | dLOOPbase; 359 | 360 | return !ev_run (EV_A_ flags); 361 | } 362 | 363 | int event_base_dispatch (struct event_base *base) 364 | { 365 | return event_base_loop (base, 0); 366 | } 367 | 368 | static void 369 | ev_x_loopexit_cb (int revents, void *base) 370 | { 371 | dLOOPbase; 372 | 373 | ev_break (EV_A_ EVBREAK_ONE); 374 | } 375 | 376 | int event_base_loopexit (struct event_base *base, struct timeval *tv) 377 | { 378 | ev_tstamp after = ev_tv_get (tv); 379 | dLOOPbase; 380 | 381 | ev_once (EV_A_ -1, 0, after >= 0. ? after : 0., ev_x_loopexit_cb, (void *)base); 382 | 383 | return 0; 384 | } 385 | 386 | struct ev_x_once 387 | { 388 | int fd; 389 | void (*cb)(int, short, void *); 390 | void *arg; 391 | }; 392 | 393 | static void 394 | ev_x_once_cb (int revents, void *arg) 395 | { 396 | struct ev_x_once *once = (struct ev_x_once *)arg; 397 | 398 | once->cb (once->fd, (short)revents, once->arg); 399 | free (once); 400 | } 401 | 402 | int event_base_once (struct event_base *base, int fd, short events, void (*cb)(int, short, void *), void *arg, struct timeval *tv) 403 | { 404 | struct ev_x_once *once = (struct ev_x_once *)malloc (sizeof (struct ev_x_once)); 405 | dLOOPbase; 406 | 407 | if (!once) 408 | return -1; 409 | 410 | once->fd = fd; 411 | once->cb = cb; 412 | once->arg = arg; 413 | 414 | ev_once (EV_A_ fd, events & (EV_READ | EV_WRITE), ev_tv_get (tv), ev_x_once_cb, (void *)once); 415 | 416 | return 0; 417 | } 418 | 419 | int event_base_priority_init (struct event_base *base, int npri) 420 | { 421 | /*dLOOPbase;*/ 422 | 423 | return 0; 424 | } 425 | 426 | -------------------------------------------------------------------------------- /src/netif/tunif.c: -------------------------------------------------------------------------------- 1 | /** 2 | * based on lwip-contrib 3 | */ 4 | #include "netif/tunif.h" 5 | #include "netif/socket_util.h" 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | #include "lwip/ip.h" 12 | 13 | 14 | #if LWIP_IPV4 /* @todo: IPv6 */ 15 | 16 | #define IFNAME0 't' 17 | #define IFNAME1 'n' 18 | 19 | #ifndef TUNIF_DEBUG 20 | #define TUNIF_DEBUG LWIP_DBG_OFF 21 | #endif 22 | 23 | #if defined(LWIP_UNIX_LINUX) 24 | 25 | #include 26 | #include 27 | #include 28 | #include 29 | 30 | 31 | #ifndef DEVTUN 32 | #define DEVTUN "/dev/net/tun" 33 | #endif 34 | 35 | #define IP_ADDR_ARGS "addr add %d.%d.%d.%d/24 dev %s" 36 | #define IP_UP_ARGS "link set %s up" 37 | #define IP_BIN "/sbin/ip " 38 | #elif defined(LWIP_UNIX_OPENBSD) 39 | #define DEVTUN "/dev/tun0" 40 | 41 | #define IP_ADDR_ARGS "addr add %d.%d.%d.%d/24 dev %s" 42 | #define IP_UP_ARGS "link set %s up" 43 | #define IP_BIN "/sbin/ip " 44 | #endif 45 | 46 | #if defined(LWIP_UNIX_MACH) 47 | 48 | #include 49 | #include 50 | #include 51 | #include 52 | #include 53 | #include 54 | 55 | #define IFCONFIG_ARGS "%s %d.%d.%d.%d %d.%d.%d.%d mtu %d netmask %d.%d.%d.%d up" 56 | 57 | #endif /* LWIP_UNIX_MACH */ 58 | 59 | #define IFCONFIG_BIN "/sbin/ifconfig " 60 | 61 | struct tunif { 62 | int fd; 63 | }; 64 | 65 | #define BUFFER_SIZE 1500 66 | 67 | /* Forward declarations. */ 68 | void tunif_input(struct netif *netif); 69 | 70 | static err_t tunif_output(struct netif *netif, struct pbuf *p, 71 | const ip4_addr_t *ipaddr); 72 | 73 | 74 | #if defined(LWIP_UNIX_MACH) 75 | 76 | static inline int utun_modified_len(int len) { 77 | if (len > 0) 78 | return (len > sizeof(u_int32_t)) ? len - sizeof(u_int32_t) : 0; 79 | else 80 | return len; 81 | } 82 | 83 | static int utun_write(int fd, void *buf, size_t len) { 84 | u_int32_t type; 85 | struct iovec iv[2]; 86 | struct ip *iph; 87 | 88 | iph = (struct ip *) buf; 89 | 90 | if (iph->ip_v == 6) 91 | type = htonl(AF_INET6); 92 | else 93 | type = htonl(AF_INET); 94 | 95 | iv[0].iov_base = &type; 96 | iv[0].iov_len = sizeof(type); 97 | iv[1].iov_base = buf; 98 | iv[1].iov_len = len; 99 | 100 | return utun_modified_len(writev(fd, iv, 2)); 101 | } 102 | 103 | static int utun_read(int fd, void *buf, size_t len) { 104 | u_int32_t type; 105 | struct iovec iv[2]; 106 | 107 | iv[0].iov_base = &type; 108 | iv[0].iov_len = sizeof(type); 109 | iv[1].iov_base = buf; 110 | iv[1].iov_len = len; 111 | 112 | return utun_modified_len(readv(fd, iv, 2)); 113 | } 114 | 115 | #endif /* LWIP_UNIX_MACH */ 116 | 117 | #if defined(LWIP_UNIX_MACH) 118 | #define tun_read(...) utun_read(__VA_ARGS__) 119 | #define tun_write(...) utun_write(__VA_ARGS__) 120 | #endif /* LWIP_UNIX_MACH */ 121 | 122 | /*-----------------------------------------------------------------------------------*/ 123 | #if defined(LWIP_UNIX_MACH) 124 | 125 | int utun_create(char *dev, u_int32_t unit) { 126 | int fd; 127 | struct ctl_info ctlInfo; 128 | struct sockaddr_ctl sc; 129 | 130 | memset(&ctlInfo, 0, sizeof(ctlInfo)); 131 | if (strlcpy(ctlInfo.ctl_name, UTUN_CONTROL_NAME, sizeof(ctlInfo.ctl_name)) >= 132 | sizeof(ctlInfo.ctl_name)) { 133 | printf("can not setup utun device: UTUN_CONTROL_NAME too long"); 134 | return -1; 135 | } 136 | 137 | fd = socket(PF_SYSTEM, SOCK_DGRAM, SYSPROTO_CONTROL); 138 | 139 | if (fd == -1) { 140 | printf("socket[SYSPROTO_CONTROL]"); 141 | return -1; 142 | } 143 | 144 | if (ioctl(fd, CTLIOCGINFO, &ctlInfo) == -1) { 145 | close(fd); 146 | printf("ioctl[CTLIOCGINFO]"); 147 | return -1; 148 | } 149 | 150 | sc.sc_id = ctlInfo.ctl_id; 151 | sc.sc_len = sizeof(sc); 152 | sc.sc_family = AF_SYSTEM; 153 | sc.ss_sysaddr = AF_SYS_CONTROL; 154 | sc.sc_unit = unit + 1; 155 | 156 | if (connect(fd, (struct sockaddr *) &sc, sizeof(sc)) == -1) { 157 | close(fd); 158 | printf("connect[AF_SYS_CONTROL]"); 159 | return -1; 160 | } 161 | 162 | // Get iface name of newly created utun dev. 163 | char utunname[20]; 164 | socklen_t utunname_len = sizeof(utunname); 165 | if (getsockopt(fd, SYSPROTO_CONTROL, UTUN_OPT_IFNAME, utunname, &utunname_len)) 166 | return -1; 167 | memcpy(dev, utunname, strlen(utunname)); 168 | return fd; 169 | } 170 | 171 | #endif /* LWIP_UNIX_MACH */ 172 | 173 | int tun_create(char *dev) { 174 | int fd = -1; 175 | #if defined(LWIP_UNIX_LINUX) 176 | struct ifreq ifr; 177 | 178 | if ((fd = open(DEVTUN, O_RDWR)) < 0) { 179 | printf("open %s failed\n", DEVTUN); 180 | return fd; 181 | } 182 | 183 | memset(&ifr, 0, sizeof(ifr)); 184 | ifr.ifr_flags = IFF_TUN | IFF_NO_PI; 185 | 186 | if (ioctl(fd, TUNSETIFF, (void *) &ifr) < 0) { 187 | printf("failed to open tun device\n"); 188 | close(fd); 189 | return -1; 190 | } 191 | strcpy(dev, ifr.ifr_name); 192 | 193 | printf("Open tun device: %s for reading...\n", ifr.ifr_name); 194 | #endif 195 | 196 | #if defined(LWIP_UNIX_MACH) 197 | for (u_int32_t unit = 0; unit < 256; ++unit) { 198 | fd = utun_create(dev, unit); 199 | if (fd >= 0) 200 | break; 201 | } 202 | #endif /* LWIP_UNIX_MACH */ 203 | 204 | return fd; 205 | } 206 | 207 | static void 208 | low_level_init(struct netif *netif) { 209 | struct tunif *tunif; 210 | int ret = 0; 211 | char buf[1024]; 212 | 213 | #if defined(LWIP_UNIX_MACH) 214 | char tun_name[16]; 215 | #endif /* LWIP_UNIX_MACH */ 216 | 217 | #if defined(LWIP_UNIX_LINUX) 218 | char tun_name[IFNAMSIZ]; 219 | #endif 220 | tun_name[0] = '\0'; 221 | 222 | 223 | tunif = (struct tunif *) netif->state; 224 | 225 | /* Obtain MAC address from network interface. */ 226 | 227 | /* Do whatever else is needed to initialize interface. */ 228 | 229 | tunif->fd = tun_create(tun_name); 230 | if (tunif->fd < 1) { 231 | perror("tunif_init failed\n"); 232 | exit(1); 233 | } 234 | 235 | printf("tun name is %s\n", tun_name); 236 | 237 | #if defined(LWIP_UNIX_MACH) 238 | // ifconfig $intf $local_tun_ip $remote_tun_ip mtu $mtu netmask 255.255.255.0 up 239 | snprintf(buf, 1024, IFCONFIG_BIN 240 | IFCONFIG_ARGS, 241 | tun_name, 242 | ip4_addr1(netif_ip4_gw(netif)), 243 | ip4_addr2(netif_ip4_gw(netif)), 244 | ip4_addr3(netif_ip4_gw(netif)), 245 | ip4_addr4(netif_ip4_gw(netif)), 246 | ip4_addr1(netif_ip4_gw(netif)), 247 | ip4_addr2(netif_ip4_gw(netif)), 248 | ip4_addr3(netif_ip4_gw(netif)), 249 | ip4_addr4(netif_ip4_gw(netif)), 250 | BUFFER_SIZE, 251 | ip4_addr1(netif_ip4_netmask(netif)), 252 | ip4_addr2(netif_ip4_netmask(netif)), 253 | ip4_addr3(netif_ip4_netmask(netif)), 254 | ip4_addr4(netif_ip4_netmask(netif)) 255 | ); 256 | ret = system(buf); 257 | #endif /* LWIP_UNIX_MACH */ 258 | #if defined(LWIP_UNIX_LINUX) 259 | snprintf(buf, 1024, IP_BIN IP_ADDR_ARGS, 260 | ip4_addr1(netif_ip4_gw(netif)), 261 | ip4_addr2(netif_ip4_gw(netif)), 262 | ip4_addr3(netif_ip4_gw(netif)), 263 | ip4_addr4(netif_ip4_gw(netif)), 264 | tun_name); 265 | ret = system(buf); 266 | snprintf(buf, 1024, IP_BIN IP_UP_ARGS, 267 | tun_name); 268 | ret = system(buf); 269 | #endif 270 | 271 | if (ret < 0) { 272 | perror("ifconfig failed"); 273 | exit(1); 274 | } 275 | 276 | setnonblocking(tunif->fd); 277 | } 278 | /*-----------------------------------------------------------------------------------*/ 279 | /* 280 | * low_level_output(): 281 | * 282 | * Should do the actual transmission of the packet. The packet is 283 | * contained in the pbuf that is passed to the function. This pbuf 284 | * might be chained. 285 | * 286 | */ 287 | /*-----------------------------------------------------------------------------------*/ 288 | 289 | static err_t 290 | low_level_output(struct tunif *tunif, struct pbuf *p) { 291 | char buf[BUFFER_SIZE]; 292 | int ret; 293 | 294 | /* initiate transfer(); */ 295 | 296 | pbuf_copy_partial(p, buf, p->tot_len, 0); 297 | 298 | /* signal that packet should be sent(); */ 299 | #if defined(LWIP_UNIX_MACH) 300 | ret = tun_write(tunif->fd, buf, p->tot_len); 301 | #endif 302 | #if defined(LWIP_UNIX_LINUX) 303 | ret = write(tunif->fd, buf, p->tot_len); 304 | #endif 305 | if (ret == -1) { 306 | perror("tunif: write failed\n"); 307 | } 308 | return ERR_OK; 309 | } 310 | /*-----------------------------------------------------------------------------------*/ 311 | /* 312 | * low_level_input(): 313 | * 314 | * Should allocate a pbuf and transfer the bytes of the incoming 315 | * packet from the interface into the pbuf. 316 | * 317 | */ 318 | /*-----------------------------------------------------------------------------------*/ 319 | static struct pbuf * 320 | low_level_input(struct tunif *tunif) { 321 | struct pbuf *p; 322 | ssize_t len; 323 | char buf[BUFFER_SIZE]; 324 | 325 | /* Obtain the size of the packet and put it into the "len" 326 | variable. */ 327 | #if defined(LWIP_UNIX_MACH) 328 | len = tun_read(tunif->fd, buf, sizeof(buf)); 329 | #endif /* LWIP_UNIX_MACH */ 330 | #if defined(LWIP_UNIX_LINUX) 331 | len = read(tunif->fd, buf, sizeof(buf)); 332 | #endif 333 | if ((len <= 0) || (len > 0xffff)) { 334 | return NULL; 335 | } 336 | 337 | /* We allocate a pbuf chain of pbufs from the pool. */ 338 | p = pbuf_alloc(PBUF_LINK, (u16_t) len, PBUF_POOL); 339 | 340 | if (p != NULL) { 341 | pbuf_take(p, buf, (u16_t) len); 342 | /* acknowledge that packet has been read(); */ 343 | } else { 344 | /* drop packet(); */ 345 | printf("pbuf_alloc failed\n"); 346 | return NULL; 347 | } 348 | 349 | return p; 350 | } 351 | 352 | /*-----------------------------------------------------------------------------------*/ 353 | /* 354 | * tunif_output(): 355 | * 356 | * This function is called by the TCP/IP stack when an IP packet 357 | * should be sent. It calls the function called low_level_output() to 358 | * do the actuall transmission of the packet. 359 | * 360 | */ 361 | /*-----------------------------------------------------------------------------------*/ 362 | static err_t 363 | tunif_output(struct netif *netif, struct pbuf *p, 364 | const ip4_addr_t *ipaddr) { 365 | struct tunif *tunif; 366 | LWIP_UNUSED_ARG(ipaddr); 367 | 368 | tunif = (struct tunif *) netif->state; 369 | 370 | return low_level_output(tunif, p); 371 | 372 | } 373 | /*-----------------------------------------------------------------------------------*/ 374 | /* 375 | * tunif_input(): 376 | * 377 | * This function should be called when a packet is ready to be read 378 | * from the interface. It uses the function low_level_input() that 379 | * should handle the actual reception of bytes from the network 380 | * interface. 381 | * 382 | */ 383 | /*-----------------------------------------------------------------------------------*/ 384 | void 385 | tunif_input(struct netif *netif) { 386 | struct tunif *tunif; 387 | struct pbuf *p; 388 | 389 | tunif = (struct tunif *) netif->state; 390 | 391 | p = low_level_input(tunif); 392 | 393 | if (p == NULL) { 394 | LWIP_DEBUGF(TUNIF_DEBUG, ("tunif_input: low_level_input returned NULL\n")); 395 | return; 396 | } 397 | 398 | err_t err = netif->input(p, netif); 399 | if (err != ERR_OK) { 400 | printf("============================> tapif_input: netif input error %s\n", lwip_strerr(err)); 401 | pbuf_free(p); 402 | } 403 | } 404 | /*-----------------------------------------------------------------------------------*/ 405 | /* 406 | * tunif_init(): 407 | * 408 | * Should be called at the beginning of the program to set up the 409 | * network interface. It calls the function low_level_init() to do the 410 | * actual setup of the hardware. 411 | * 412 | */ 413 | /*-----------------------------------------------------------------------------------*/ 414 | err_t 415 | tunif_init(struct netif *netif) { 416 | struct tunif *tunif; 417 | 418 | tunif = (struct tunif *) mem_malloc(sizeof(struct tunif)); 419 | if (!tunif) { 420 | return ERR_MEM; 421 | } 422 | netif->state = tunif; 423 | netif->name[0] = IFNAME0; 424 | netif->name[1] = IFNAME1; 425 | netif->output = tunif_output; 426 | 427 | low_level_init(netif); 428 | return ERR_OK; 429 | } 430 | /*-----------------------------------------------------------------------------------*/ 431 | 432 | #endif /* LWIP_IPV4 */ 433 | -------------------------------------------------------------------------------- /src/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "ev.h" 9 | #include "yaml.h" 10 | 11 | #include "lwip/init.h" 12 | #include "lwip/mem.h" 13 | #include "lwip/timeouts.h" 14 | #include "lwip/ip.h" 15 | #include "lwip/ip4_frag.h" 16 | 17 | #include "struct.h" 18 | #include "util.h" 19 | #include "var.h" 20 | 21 | #if defined(LWIP_UNIX_LINUX) 22 | 23 | #include "netif/tapif.h" 24 | #include "netif/etharp.h" 25 | 26 | #endif 27 | 28 | #include "netif/tunif.h" 29 | 30 | #include "udp_raw.h" 31 | #include "tcp_raw.h" 32 | 33 | /* lwip host IP configuration */ 34 | struct netif netif; 35 | static ip4_addr_t ipaddr, netmask, gw; 36 | static char *config_file; 37 | 38 | /* nonstatic debug cmd option, exported in lwipopts.h */ 39 | unsigned char debug_flags; 40 | 41 | static struct option longopts[] = { 42 | /* turn on debugging output (if build with LWIP_DEBUG) */ 43 | {"debug", no_argument, NULL, 'd'}, 44 | /* help */ 45 | {"help", no_argument, NULL, 'h'}, 46 | /* config file */ 47 | {"config", required_argument, NULL, 'c'}, 48 | /* new command line options go here! */ 49 | {NULL, 0, NULL, 0} 50 | }; 51 | 52 | 53 | void on_shell(); 54 | 55 | void down_shell(); 56 | 57 | void tuntap_read_cb(struct ev_loop *loop, struct ev_io *watcher, int revents); 58 | 59 | void sigterm_cb(struct ev_loop *loop, ev_signal *watcher, int revents); 60 | 61 | void sigint_cb(struct ev_loop *loop, ev_signal *watcher, int revents); 62 | 63 | void sigusr2_cb(struct ev_loop *loop, ev_signal *watcher, int revents); 64 | 65 | static void 66 | usage(void) { 67 | unsigned char i; 68 | printf("options:\n"); 69 | for (i = 0; i < NUM_OPTS; i++) { 70 | printf("-%c --%s\n", longopts[i].val, longopts[i].name); 71 | } 72 | } 73 | 74 | void parse_config(int argc, char **argv) { 75 | int ch; 76 | char ip_str[16] = {0}, nm_str[16] = {0}, gw_str[16] = {0}; 77 | 78 | /* startup defaults (may be overridden by one or more opts) */ 79 | IP4_ADDR(&gw, 10, 0, 0, 1); 80 | // ip4_addr_set_any(&gw); 81 | ip4_addr_set_any(&ipaddr); 82 | IP4_ADDR(&ipaddr, 10, 0, 0, 2); 83 | IP4_ADDR(&netmask, 255, 255, 255, 0); 84 | 85 | /* use debug flags defined by debug.h */ 86 | debug_flags = LWIP_DBG_OFF; 87 | 88 | while ((ch = getopt_long(argc, argv, "dhc:", longopts, NULL)) != -1) { 89 | switch (ch) { 90 | case 'd': 91 | debug_flags |= (LWIP_DBG_ON | LWIP_DBG_TRACE | LWIP_DBG_STATE | LWIP_DBG_FRESH | LWIP_DBG_HALT); 92 | break; 93 | case 'h': 94 | usage(); 95 | exit(0); 96 | case 'c': 97 | config_file = optarg; 98 | break; 99 | default: 100 | usage(); 101 | break; 102 | } 103 | } 104 | argc -= optind; 105 | argv += optind; 106 | 107 | if (config_file == NULL) { 108 | printf("Please provide config file\n"); 109 | exit(0); 110 | } 111 | 112 | /** 113 | * yaml config parser start 114 | */ 115 | FILE *fh = fopen(config_file, "r"); 116 | yaml_parser_t parser; 117 | yaml_token_t token; /* new variable */ 118 | 119 | /* Initialize parser */ 120 | if (!yaml_parser_initialize(&parser)) 121 | fputs("Failed to initialize parser!\n", stderr); 122 | if (fh == NULL) 123 | fputs("Failed to open file!\n", stderr); 124 | 125 | /* Set input file */ 126 | yaml_parser_set_input_file(&parser, fh); 127 | 128 | /** 129 | * state = 0 = expect key 130 | * state = 1 = expect value 131 | */ 132 | int state = 0; 133 | char **datap; 134 | char *tk; 135 | 136 | /* BEGIN new code */ 137 | do { 138 | yaml_parser_scan(&parser, &token); 139 | switch (token.type) { 140 | /* Stream start/end */ 141 | case YAML_STREAM_START_TOKEN: 142 | break; 143 | case YAML_STREAM_END_TOKEN: 144 | break; 145 | /* Token types (read before actual token) */ 146 | case YAML_KEY_TOKEN: 147 | state = 0; 148 | break; 149 | case YAML_VALUE_TOKEN: 150 | state = 1; 151 | break; 152 | /* Block delimeters */ 153 | case YAML_BLOCK_SEQUENCE_START_TOKEN: 154 | break; 155 | case YAML_BLOCK_ENTRY_TOKEN: 156 | break; 157 | case YAML_BLOCK_END_TOKEN: 158 | break; 159 | /* Data */ 160 | case YAML_BLOCK_MAPPING_START_TOKEN: 161 | break; 162 | case YAML_SCALAR_TOKEN: 163 | tk = (char *) token.data.scalar.value; 164 | if (state == 0) { 165 | if (strcmp(tk, "ip_mode") == 0) { 166 | datap = &conf->ip_mode; 167 | } else if (strcmp(tk, "dns_mode") == 0) { 168 | datap = &conf->dns_mode; 169 | } else if (strcmp(tk, "socks_server") == 0) { 170 | datap = &conf->socks_server; 171 | } else if (strcmp(tk, "socks_port") == 0) { 172 | datap = &conf->socks_port; 173 | } else if (strcmp(tk, "remote_dns_server") == 0) { 174 | datap = &conf->remote_dns_server; 175 | } else if (strcmp(tk, "remote_dns_port") == 0) { 176 | datap = &conf->remote_dns_port; 177 | } else if (strcmp(tk, "local_dns_port") == 0) { 178 | datap = &conf->local_dns_port; 179 | } else if (strcmp(tk, "relay_none_dns_packet_with_udp") == 0) { 180 | datap = &conf->relay_none_dns_packet_with_udp; 181 | } else if (strcmp(tk, "custom_domian_server_file") == 0) { 182 | datap = &conf->custom_domian_server_file; 183 | } else if (strcmp(tk, "gw") == 0) { 184 | datap = &conf->gw; 185 | } else if (strcmp(tk, "addr") == 0) { 186 | datap = &conf->addr; 187 | } else if (strcmp(tk, "netmask") == 0) { 188 | datap = &conf->netmask; 189 | } else if (strcmp(tk, "after_start_shell") == 0) { 190 | datap = &conf->after_start_shell; 191 | } else if (strcmp(tk, "before_shutdown_shell") == 0) { 192 | datap = &conf->before_shutdown_shell; 193 | } else { 194 | printf("Unrecognised key: %s\n", tk); 195 | } 196 | } else { 197 | *datap = strdup(tk); 198 | } 199 | break; 200 | /* Others */ 201 | default: 202 | break; 203 | } 204 | if (token.type != YAML_STREAM_END_TOKEN) 205 | yaml_token_delete(&token); 206 | } while (token.type != YAML_STREAM_END_TOKEN); 207 | yaml_token_delete(&token); 208 | /* END new code */ 209 | 210 | /* Cleanup */ 211 | yaml_parser_delete(&parser); 212 | fclose(fh); 213 | /** 214 | * yaml config parser end 215 | */ 216 | 217 | /** 218 | * if config, overside default value 219 | */ 220 | if (conf->gw != NULL) { 221 | ip4addr_aton(conf->gw, &gw); 222 | } 223 | if (conf->addr != NULL) { 224 | ip4addr_aton(conf->addr, &ipaddr); 225 | } 226 | if (conf->netmask != NULL) { 227 | ip4addr_aton(conf->netmask, &netmask); 228 | } 229 | 230 | if (conf->ip_mode == NULL) { 231 | memcpy(conf->ip_mode, "tun", 3); 232 | } else { 233 | #if defined(LWIP_UNIX_MACH) 234 | if (strcmp("tap", conf->ip_mode) == 0) { 235 | printf("Darwin does not support tap mode!!!\n"); 236 | exit(0); 237 | } 238 | #endif /* LWIP_UNIX_MACH */ 239 | } 240 | if (conf->dns_mode == NULL) { 241 | memcpy(conf->dns_mode, "tcp", 3); 242 | } 243 | 244 | strncpy(ip_str, ip4addr_ntoa(&ipaddr), sizeof(ip_str)); 245 | strncpy(nm_str, ip4addr_ntoa(&netmask), sizeof(nm_str)); 246 | strncpy(gw_str, ip4addr_ntoa(&gw), sizeof(gw_str)); 247 | printf("Lwip netstack host %s mask %s gateway %s\n", ip_str, nm_str, gw_str); 248 | 249 | 250 | if (conf->custom_domian_server_file != NULL) { 251 | std::string line; 252 | std::string file_sp(";"); 253 | std::string sp(SLASH); 254 | 255 | std::vector> domains; 256 | 257 | std::vector files; 258 | std::string ffs(conf->custom_domian_server_file); 259 | split(ffs, file_sp, &files); 260 | for (int i = 0; i < files.size(); ++i) { 261 | if (!files.at(i).empty()) { 262 | std::ifstream chndomains(files.at(i)); 263 | if (chndomains.is_open()) { 264 | while (getline(chndomains, line)) { 265 | if (!line.empty() && line.substr(0, 1) != "#") { 266 | std::vector v; 267 | split(line, sp, &v); 268 | domains.push_back(v); 269 | } 270 | } 271 | chndomains.close(); 272 | } else { 273 | std::cout << "Unable to open dns domain file " << files.at(i) << std::endl; 274 | } 275 | } 276 | } 277 | conf->domains = domains; 278 | } 279 | } 280 | 281 | int 282 | main(int argc, char **argv) { 283 | parse_config(argc, argv); 284 | /* lwip/src/core/init.c */ 285 | lwip_init(); 286 | 287 | if (strcmp(conf->ip_mode, "tun") == 0) { 288 | netif_add(&netif, &ipaddr, &netmask, &gw, NULL, tunif_init, ip_input); // IPV4 IPV6 TODO 289 | } else { 290 | #if defined(LWIP_UNIX_LINUX) 291 | netif_add(&netif, &ipaddr, &netmask, &gw, NULL, tapif_init, ethernet_input); 292 | #endif 293 | } 294 | netif_set_default(&netif); 295 | netif_set_link_up(&netif); 296 | /* lwip/core/netif.c */ 297 | netif_set_up(&netif); 298 | #if LWIP_IPV6 299 | netif_create_ip6_linklocal_address(&netif, 1); 300 | #endif 301 | 302 | udp_raw_init(); 303 | tcp_raw_init(); 304 | 305 | struct ev_io *tuntap_io = (struct ev_io *) mem_malloc(sizeof(struct ev_io)); 306 | if (tuntap_io == NULL) { 307 | printf("tuntap_io: out of memory for tuntap_io\n"); 308 | return -1; 309 | } 310 | struct ev_loop *loop = ev_default_loop(0); 311 | 312 | struct tuntapif *tuntapif; 313 | tuntapif = (struct tuntapif *) ((&netif)->state); 314 | 315 | /** 316 | * signal start 317 | */ 318 | // eg: kill 319 | ev_signal signal_term_watcher; 320 | ev_signal_init(&signal_term_watcher, sigterm_cb, SIGTERM); 321 | ev_signal_start(loop, &signal_term_watcher); 322 | 323 | // eg: ctrl + c 324 | ev_signal signal_int_watcher; 325 | ev_signal_init(&signal_int_watcher, sigint_cb, SIGINT); 326 | ev_signal_start(loop, &signal_int_watcher); 327 | 328 | ev_signal signal_usr2_watcher; 329 | ev_signal_init(&signal_usr2_watcher, sigusr2_cb, SIGUSR2); 330 | ev_signal_start(loop, &signal_usr2_watcher); 331 | /** 332 | * signal end 333 | */ 334 | 335 | ev_io_init(tuntap_io, tuntap_read_cb, tuntapif->fd, EV_READ); 336 | ev_io_start(loop, tuntap_io); 337 | 338 | 339 | // TODO 340 | sys_check_timeouts(); 341 | 342 | /** 343 | * setup shell scripts 344 | */ 345 | on_shell(); 346 | 347 | std::cout << "Ip2socks started!" << std::endl; 348 | return ev_run(loop, 0); 349 | } 350 | 351 | /** 352 | * down shell scripts 353 | */ 354 | void down_shell() { 355 | if (conf->before_shutdown_shell != NULL) { 356 | std::string sh("sh "); 357 | sh.append(conf->before_shutdown_shell); 358 | sh.append(" "); 359 | 360 | if (strcmp(conf->ip_mode, "tun") == 0) { 361 | sh.append(conf->gw); 362 | } else { 363 | sh.append(conf->addr); 364 | } 365 | 366 | printf("exec down shell %s\n", sh.c_str()); 367 | 368 | system(sh.c_str()); 369 | } 370 | } 371 | 372 | /** 373 | * setup shell scripts 374 | */ 375 | void on_shell() { 376 | if (conf->after_start_shell != NULL) { 377 | std::string sh("sh "); 378 | sh.append(conf->after_start_shell); 379 | sh.append(" "); 380 | 381 | if (strcmp(conf->ip_mode, "tun") == 0) { 382 | sh.append(conf->gw); 383 | } else { 384 | sh.append(conf->addr); 385 | } 386 | 387 | printf("exec setup shell %s\n", sh.c_str()); 388 | 389 | system(sh.c_str()); 390 | } 391 | } 392 | 393 | void sigterm_cb(struct ev_loop *loop, ev_signal *watcher, int revents) { 394 | printf("SIGTERM handler called in process!!!\n"); 395 | down_shell(); 396 | ev_break(loop, EVBREAK_ALL); 397 | exit(0); // kill all threads 398 | } 399 | 400 | void sigint_cb(struct ev_loop *loop, ev_signal *watcher, int revents) { 401 | printf("SIGINT handler called in process!!!\n"); 402 | down_shell(); 403 | ev_break(loop, EVBREAK_ALL); 404 | exit(0); // kill all threads 405 | } 406 | 407 | void sigusr2_cb(struct ev_loop *loop, ev_signal *watcher, int revents) { 408 | printf("SIGUSR2 handler called in process!!! TODO reload config.\n"); 409 | } 410 | 411 | void tuntap_read_cb(struct ev_loop *loop, struct ev_io *watcher, int revents) { 412 | if (strcmp(conf->ip_mode, "tun") == 0) { 413 | tunif_input(&netif); 414 | } else { 415 | #if defined(LWIP_UNIX_LINUX) 416 | tapif_input(&netif); 417 | #endif 418 | } 419 | } 420 | -------------------------------------------------------------------------------- /src/tcp_raw.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * based on lwip-contrib 3 | */ 4 | #include 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | #include "socks5.h" 11 | #include "struct.h" 12 | #include "var.h" 13 | #include "tcp_raw.h" 14 | 15 | #include "lwip/opt.h" 16 | #include "lwip/stats.h" 17 | #include "lwip/tcp.h" 18 | 19 | #if LWIP_TCP && LWIP_CALLBACK_API 20 | 21 | static struct tcp_pcb *tcp_raw_pcb; 22 | static ev_timer timeout_watcher; 23 | 24 | 25 | static ev_tstamp timeout = 60.; 26 | 27 | static void tcp_raw_send(struct tcp_pcb *tpcb, struct tcp_raw_state *es); 28 | 29 | 30 | static void 31 | tcp_raw_free(struct tcp_raw_state *es) { 32 | if (es != NULL) { 33 | if (es->pcb != NULL) { 34 | tcp_close(es->pcb); 35 | } 36 | free(es); 37 | } 38 | } 39 | 40 | static void 41 | tcp_raw_close(struct tcp_pcb *tpcb, struct tcp_raw_state *es) { 42 | if (tpcb != NULL) { 43 | tcp_arg(tpcb, NULL); 44 | tcp_sent(tpcb, NULL); 45 | tcp_recv(tpcb, NULL); 46 | tcp_err(tpcb, NULL); 47 | tcp_poll(tpcb, NULL, 0); 48 | tcp_close(tpcb); 49 | } 50 | 51 | if (es != NULL) { 52 | es->socks_buf_used = 0; 53 | es->buf_used = 0; 54 | if (es->socks_fd > 0) { 55 | if (&(es->io) != NULL) { 56 | close(es->socks_fd); 57 | ev_io_stop(EV_DEFAULT, &(es->io)); 58 | } 59 | } 60 | 61 | 62 | if (es->block_ctx->watcher.active != 0) { 63 | ev_timer_stop(EV_DEFAULT, &(es->block_ctx->watcher)); 64 | } 65 | if (es->timeout_ctx->watcher.active != 0) { 66 | ev_timer_stop(EV_DEFAULT, &(es->timeout_ctx->watcher)); 67 | } 68 | 69 | free(es->block_ctx); 70 | free(es->timeout_ctx); 71 | 72 | tcp_raw_free(es); 73 | } 74 | } 75 | 76 | static void 77 | tcp_raw_send(struct tcp_pcb *tpcb, struct tcp_raw_state *es) { 78 | if (es->buf_used > 0) { 79 | // 缓冲区的数据全部发送 80 | ssize_t ret = send(es->socks_fd, es->buf.c_str(), es->buf_used, 0); 81 | 82 | if (ret > 0) { 83 | u16_t plen = es->buf_used; 84 | 85 | es->buf.clear(); 86 | es->buf_used = 0; 87 | 88 | /* we can read more data now */ 89 | tcp_recved(tpcb, plen); 90 | } else { 91 | printf("<-------------------------------------- send to socks failed %ld\n", ret); 92 | tcp_raw_close(tpcb, es); 93 | } 94 | } 95 | } 96 | 97 | static void 98 | tcp_raw_error(void *arg, err_t err) { 99 | struct tcp_raw_state *es; 100 | 101 | LWIP_UNUSED_ARG(err); 102 | 103 | es = (struct tcp_raw_state *) arg; 104 | 105 | if (es != NULL) { 106 | printf("tcp_raw_error is %d %s\n", err, lwip_strerr(err)); 107 | if (es->pcb != NULL) { 108 | tcp_raw_close(es->pcb, es); 109 | } else { 110 | tcp_raw_free(es); 111 | } 112 | } 113 | } 114 | 115 | static err_t 116 | tcp_raw_poll(void *arg, struct tcp_pcb *tpcb) { 117 | err_t ret_err; 118 | struct tcp_raw_state *es; 119 | 120 | es = (struct tcp_raw_state *) arg; 121 | if (es != NULL) { 122 | if (es->buf_used > 0) { 123 | /* there is a remaining pbuf (chain) */ 124 | tcp_raw_send(tpcb, es); 125 | } else { 126 | /* no remaining pbuf (chain) */ 127 | if (es->state == ES_CLOSING) { 128 | tcp_raw_close(tpcb, es); 129 | } 130 | } 131 | ret_err = ERR_OK; 132 | } else { 133 | /* nothing to be done */ 134 | tcp_abort(tpcb); 135 | ret_err = ERR_ABRT; 136 | } 137 | return ret_err; 138 | } 139 | 140 | static err_t 141 | tcp_raw_sent(void *arg, struct tcp_pcb *tpcb, u16_t len) { 142 | struct tcp_raw_state *es; 143 | 144 | LWIP_UNUSED_ARG(len); 145 | 146 | es = (struct tcp_raw_state *) arg; 147 | es->retries = 0; 148 | 149 | if (es->buf_used > 0) { 150 | /* still got pbufs to send */ 151 | tcp_sent(tpcb, tcp_raw_sent); 152 | tcp_raw_send(tpcb, es); 153 | } else { 154 | /* no more pbufs to send */ 155 | if (es->state == ES_CLOSING) { 156 | tcp_raw_close(tpcb, es); 157 | } 158 | } 159 | return ERR_OK; 160 | } 161 | 162 | static err_t 163 | tcp_raw_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err) { 164 | if (arg == NULL) { 165 | return ERR_ARG; 166 | } 167 | struct tcp_raw_state *es; 168 | err_t ret_err; 169 | 170 | char buf[TCP_WND]; 171 | 172 | LWIP_ASSERT("arg != NULL", arg != NULL); 173 | es = (struct tcp_raw_state *) arg; 174 | if (p == NULL) { 175 | /* remote host closed connection */ 176 | es->state = ES_CLOSING; 177 | if (es->buf_used <= 0) { 178 | /* we're done sending, close it */ 179 | tcp_raw_close(tpcb, es); 180 | } else { 181 | /* we're not done yet */ 182 | tcp_raw_send(tpcb, es); 183 | } 184 | ret_err = ERR_OK; 185 | } else if (err != ERR_OK) { 186 | /* cleanup, for unknown reason */ 187 | if (p != NULL) { 188 | pbuf_free(p); 189 | } 190 | // send last data 191 | tcp_raw_send(tpcb, es); 192 | ret_err = err; 193 | } else if (es->state == ES_ACCEPTED) { 194 | /* first data chunk in p->payload */ 195 | es->state = ES_RECEIVED; 196 | 197 | pbuf_copy_partial(p, buf, p->tot_len, 0); 198 | 199 | std::string buf_cpp(buf, p->tot_len); 200 | es->buf.append(buf_cpp); 201 | es->buf_used += p->tot_len; 202 | 203 | tcp_raw_send(tpcb, es); 204 | ret_err = ERR_OK; 205 | } else if (es->state == ES_RECEIVED) { 206 | /* read some more data */ 207 | pbuf_copy_partial(p, buf, p->tot_len, 0); 208 | 209 | std::string buf_cpp(buf, p->tot_len); 210 | es->buf.append(buf_cpp); 211 | es->buf_used += p->tot_len; 212 | tcp_raw_send(tpcb, es); 213 | 214 | ret_err = ERR_OK; 215 | } else { 216 | /* unkown es->state, trash data */ 217 | tcp_recved(tpcb, p->tot_len); 218 | pbuf_free(p); 219 | // send last data 220 | tcp_raw_send(tpcb, es); 221 | ret_err = ERR_OK; 222 | } 223 | return ret_err; 224 | } 225 | 226 | static void free_all(struct ev_loop *loop, ev_io *watcher, struct tcp_raw_state *es, struct tcp_pcb *pcb) { 227 | close(watcher->fd); 228 | ev_io_stop(EV_DEFAULT, watcher); 229 | es->socks_fd = 0; 230 | tcp_raw_close(pcb, es); 231 | } 232 | 233 | 234 | // https://github.com/dreamcat4/lwip/blob/master/contrib/apps/httpserver_raw/httpd.c 235 | static void send_data_lwip(struct tcp_pcb *pcb, struct tcp_raw_state *es) { 236 | if (pcb != NULL && es != NULL) { 237 | err_t err; 238 | u16_t len; 239 | 240 | /* We cannot send more data than space available in the send buffer. */ 241 | if (pcb->state != 0) { 242 | if (tcp_sndbuf(pcb) < es->socks_buf_used) { 243 | len = tcp_sndbuf(pcb); 244 | } else { 245 | len = es->socks_buf_used; 246 | } 247 | 248 | // 发送缓冲区满 249 | if (tcp_sndbuf(pcb) == 0) { 250 | // FIXME 251 | // return; 252 | } 253 | 254 | if (len > 0) { 255 | do { 256 | err = tcp_write(pcb, es->socks_buf.c_str(), len, TCP_WRITE_FLAG_COPY); 257 | 258 | if (err == ERR_MEM) { 259 | if ((tcp_sndbuf(pcb) == 0) || (tcp_sndqueuelen(pcb) >= TCP_SND_QUEUELEN)) { 260 | /* no need to try smaller sizes */ 261 | len = 1; 262 | } else { 263 | len /= 2; 264 | } 265 | printf("Send failed, trying less (%d bytes)\n", len); 266 | } 267 | } while (err == ERR_MEM && len > 1); 268 | 269 | if (err == ERR_OK) { 270 | if (es->socks_buf.size() == len) { 271 | es->socks_buf.clear(); 272 | } else { 273 | es->socks_buf.erase(es->socks_buf.begin(), es->socks_buf.end() - (es->socks_buf.size() - len)); 274 | } 275 | es->socks_buf_used -= len; 276 | 277 | err_t wr_err = tcp_output(pcb); 278 | if (wr_err != ERR_OK) { 279 | printf("<---------------------------------- tcp_output wr_wrr is %s\n", lwip_strerr(wr_err)); 280 | } else { 281 | if (es->lwip_blocked) { 282 | es->lwip_blocked = 0; 283 | } 284 | } 285 | } else { 286 | printf("send_data_lwip: error %s len %d %d\n", lwip_strerr(err), len, tcp_sndbuf(pcb)); 287 | } 288 | } 289 | } 290 | } 291 | } 292 | 293 | static void write_and_output(struct tcp_pcb *pcb, struct tcp_raw_state *es) { 294 | send_data_lwip(pcb, es); 295 | } 296 | 297 | static void 298 | timeout_cb(struct ev_loop *loop, ev_timer *watcher, int revents) { 299 | timer_ctx *timeout_ctx = container_of(watcher, timer_ctx, watcher); 300 | struct tcp_raw_state *es = timeout_ctx->raw_state; 301 | write_and_output(es->pcb, es); 302 | printf("timeout, clean\n"); 303 | free_all(loop, &(es->io), es, es->pcb); 304 | } 305 | 306 | static void 307 | block_cb(struct ev_loop *loop, ev_timer *watcher, int revents) { 308 | timer_ctx *block_ctx = container_of(watcher, timer_ctx, watcher); 309 | struct tcp_raw_state *es = block_ctx->raw_state; 310 | write_and_output(es->pcb, es); 311 | es->lwip_blocked = 0; 312 | printf("Reset lwip block\n"); 313 | ev_timer_stop(EV_DEFAULT, watcher); 314 | } 315 | 316 | 317 | static void read_cb(struct ev_loop *loop, ev_io *watcher, int revents) { 318 | struct tcp_raw_state *es = container_of(watcher, struct tcp_raw_state, io); 319 | struct tcp_pcb *pcb = es->pcb; 320 | 321 | ev_timer_again(EV_A_ &(es->timeout_ctx->watcher)); 322 | 323 | if (es->socks_buf_used > BUFFER_SIZE) { 324 | es->lwip_blocked = 1; 325 | ev_timer_start(EV_DEFAULT, &(es->block_ctx->watcher)); 326 | return; 327 | } 328 | 329 | char buffer[BUFFER_SIZE]; 330 | ssize_t nreads; 331 | 332 | nreads = recv(watcher->fd, buffer, BUFFER_SIZE, 0); 333 | if (nreads < 0) { 334 | printf("<---------------------------------- read error [%d] force close!!!\n", errno); 335 | free_all(loop, watcher, es, pcb); 336 | return; 337 | } 338 | 339 | // EOF 340 | if (0 == nreads) { 341 | write_and_output(pcb, es); 342 | free_all(loop, watcher, es, pcb); 343 | return; 344 | } 345 | 346 | std::string buf_cpp(buffer, nreads); 347 | es->socks_buf.append(buf_cpp); 348 | es->socks_buf_used += nreads; 349 | 350 | if (es->socks_buf_used > nreads) { 351 | std::cout << "recv " << nreads << " data, " << "es->socks_buf_used is " << es->socks_buf_used 352 | << ", (tcp_sndbuf(pcb) is " << tcp_sndbuf(pcb) << std::endl; 353 | } 354 | 355 | write_and_output(pcb, es); 356 | } 357 | 358 | static err_t 359 | tcp_raw_accept(void *arg, struct tcp_pcb *newpcb, err_t err) { 360 | err_t ret_err; 361 | struct tcp_raw_state *es; 362 | 363 | LWIP_UNUSED_ARG(arg); 364 | if ((err != ERR_OK) || (newpcb == NULL)) { 365 | return ERR_VAL; 366 | } 367 | 368 | /* Unless this pcb should have NORMAL priority, set its priority now. 369 | When running out of pcbs, low priority pcbs can be aborted to create 370 | new pcbs of higher priority. */ 371 | tcp_setprio(newpcb, TCP_PRIO_MIN); 372 | 373 | /** 374 | * local ip local port <-> remote ip remote port 375 | */ 376 | char localip_str[INET_ADDRSTRLEN]; 377 | inet_ntop(AF_INET, &(newpcb->local_ip), localip_str, INET_ADDRSTRLEN); 378 | char remoteip_str[INET_ADDRSTRLEN]; 379 | inet_ntop(AF_INET, &(newpcb->remote_ip), remoteip_str, INET_ADDRSTRLEN); 380 | 381 | // flow 119.23.211.95:80 <-> 172.16.0.1:53536 382 | // printf("<--------------------- tcp flow %s:%d <-> %s:%d\n", localip_str, newpcb->local_port, remoteip_str, newpcb->remote_port); 383 | 384 | /** 385 | * socks 5 386 | */ 387 | int socks_fd = 0; 388 | 389 | socks_fd = socks5_connect(conf->socks_server, conf->socks_port); 390 | if (socks_fd < 1) { 391 | printf("socks5 connect failed\n"); 392 | return -1; 393 | } 394 | 395 | char port[64]; 396 | sprintf(port, "%d", newpcb->local_port); 397 | 398 | int ret = socks5_auth(socks_fd, localip_str, port, 0x01, 1); 399 | if (ret < 0) { 400 | printf("socks5 auth error\n"); 401 | return -1; 402 | } 403 | 404 | es = (tcp_raw_state *) malloc(sizeof(tcp_raw_state)); 405 | memset(es, 0, sizeof(tcp_raw_state)); 406 | 407 | es->block_ctx = (timer_ctx *) malloc(sizeof(timer_ctx)); 408 | memset(es->block_ctx, 0, sizeof(timer_ctx)); 409 | es->block_ctx->raw_state = es; 410 | 411 | es->timeout_ctx = (timer_ctx *) malloc(sizeof(timer_ctx)); 412 | memset(es->timeout_ctx, 0, sizeof(timer_ctx)); 413 | es->timeout_ctx->raw_state = es; 414 | 415 | if (es != NULL) { 416 | es->state = ES_ACCEPTED; 417 | es->pcb = newpcb; 418 | es->retries = 0; 419 | 420 | es->buf_used = 0; 421 | es->socks_buf_used = 0; 422 | es->lwip_blocked = 0; 423 | 424 | es->socks_fd = socks_fd; 425 | 426 | 427 | ev_timer_init(&(es->timeout_ctx->watcher), timeout_cb, timeout, 0.); 428 | ev_timer_start(EV_DEFAULT, &(es->timeout_ctx->watcher)); 429 | 430 | ev_timer_init(&(es->block_ctx->watcher), block_cb, 0.1, 0.); 431 | 432 | ev_io_init(&(es->io), read_cb, socks_fd, EV_READ); 433 | ev_io_start(EV_DEFAULT, &(es->io)); 434 | 435 | /** 436 | * enable tcp keepalive 437 | */ 438 | newpcb->so_options |= SOF_KEEPALIVE; 439 | newpcb->so_options |= SOF_REUSEADDR; 440 | newpcb->keep_intvl = 75000; /* 75 seconds */ 441 | 442 | /* pass newly allocated es to our callbacks */ 443 | tcp_arg(newpcb, es); 444 | tcp_recv(newpcb, tcp_raw_recv); 445 | tcp_err(newpcb, tcp_raw_error); 446 | tcp_poll(newpcb, tcp_raw_poll, 4); 447 | tcp_sent(newpcb, tcp_raw_sent); 448 | ret_err = ERR_OK; 449 | } else { 450 | ret_err = ERR_MEM; 451 | } 452 | return ret_err; 453 | } 454 | 455 | void 456 | tcp_raw_init(void) { 457 | tcp_raw_pcb = tcp_new_ip_type(IPADDR_TYPE_ANY); 458 | if (tcp_raw_pcb != NULL) { 459 | err_t err; 460 | 461 | err = tcp_bind(tcp_raw_pcb, IP_ANY_TYPE, 0); 462 | if (err == ERR_OK) { 463 | tcp_raw_pcb = tcp_listen(tcp_raw_pcb); 464 | tcp_accept(tcp_raw_pcb, tcp_raw_accept); 465 | } else { 466 | /* abort? output diagnostic? */ 467 | } 468 | } else { 469 | /* abort? output diagnostic? */ 470 | } 471 | } 472 | 473 | #endif /* LWIP_TCP && LWIP_CALLBACK_API */ 474 | --------------------------------------------------------------------------------