├── .gitignore ├── README.md ├── client ├── Makefile ├── include │ └── sshinner_c.h ├── settings.json ├── source │ ├── client.c │ ├── sshinner_c_dns.c │ ├── sshinner_c_event.c │ ├── sshinner_c_sockets.c │ ├── sshinner_c_threads.c │ └── sshinner_c_utils.c └── ssl │ └── public.key ├── common └── sshinner_crypt.c ├── include ├── rbtree.h ├── rbtree_augmented.h ├── sshinner.h ├── sshinner_crypt.h ├── st_others.h └── st_slist.h └── server ├── Makefile ├── include └── sshinner_s.h ├── settings.json ├── source ├── rbtree.c ├── server.c ├── sshinner_s_data.c ├── sshinner_s_event.c ├── sshinner_s_threads.c └── sshinner_s_utils.c └── ssl └── private.key /.gitignore: -------------------------------------------------------------------------------- 1 | ### These files should get ignored no matter where they appear. 2 | 3 | # Editors leave these lying around 4 | \#*\# 5 | .#* 6 | *~ 7 | *.swp 8 | 9 | # C stuff 10 | *.o 11 | 12 | # Windows stuff 13 | *.obj 14 | *.exe 15 | *.lib 16 | 17 | # Patch leaves these lying arround 18 | *.orig 19 | *.rej 20 | 21 | # gcov stuff 22 | *.gcno 23 | *.gcov 24 | *.gcda 25 | 26 | # gdb stuff 27 | .gdb_history 28 | 29 | # Autotools stuff 30 | .deps 31 | .dirstamp 32 | Makefile.in 33 | 34 | # Libtool stuff 35 | .libs 36 | *.lo 37 | *.la 38 | 39 | # ctags stuff 40 | TAGS 41 | tags 42 | 43 | # Stuff made by our makefiles 44 | *.pc 45 | *.log 46 | *.trs 47 | 48 | ## The initial / makes these files only get ignored in particular directories. 49 | /autom4te.cache 50 | 51 | # Libtool adds these, at least sometimes 52 | /m4/libtool.m4 53 | /m4/ltoptions.m4 54 | /m4/ltsugar.m4 55 | /m4/ltversion.m4 56 | /m4/lt~obsolete.m4 57 | 58 | /aclocal.m4 59 | /compile 60 | /doxygen 61 | /config.cache 62 | /config.guess 63 | /config.log 64 | /config.status 65 | /config.sub 66 | /configure 67 | /configure.lineno 68 | /depcomp 69 | /config.h 70 | /config.h.in 71 | /install-sh 72 | /libtool 73 | /ltmain.sh 74 | /missing 75 | /stamp-h1 76 | /stamp-h2 77 | 78 | /include/event2/event-config.h 79 | /evconfig-private.h 80 | 81 | /sample/dns-example 82 | /sample/event-read-fifo 83 | /sample/hello-world 84 | /sample/http-server 85 | /sample/http-connect 86 | /sample/le-proxy 87 | /sample/https-client 88 | /sample/signal-test 89 | /sample/time-test 90 | /sample/event-test 91 | 92 | /test-driver 93 | /test/bench 94 | /test/bench_cascade 95 | /test/bench_http 96 | /test/bench_httpclient 97 | /test/regress 98 | /test/regress.gen.c 99 | /test/regress.gen.h 100 | /test/rpcgen-attempted 101 | /test/test-dumpevents 102 | /test/test-eof 103 | /test/test-closed 104 | /test/test-init 105 | /test/test-ratelim 106 | /test/test-script.sh 107 | /test/test-time 108 | /test/test-weof 109 | /test/test-changelist 110 | /test/test-fdleak 111 | 112 | 113 | # Files generated by cmake 114 | /CMakeCache.txt 115 | /CMakeFiles/ 116 | /CTestTestfile.cmake 117 | /DartConfiguration.tcl 118 | /LibeventConfig.cmake 119 | /LibeventConfigVersion.cmake 120 | /LibeventTargets.cmake 121 | /bin/ 122 | /cmake_install.cmake 123 | /include/evconfig-private.h 124 | /lib/ 125 | /tmp/ 126 | /verify_tests.sh 127 | /verify_tests.bat 128 | /event.dir 129 | /event_core.dir 130 | /event_extra.dir 131 | *.vcxproj 132 | *.sln 133 | *.filters 134 | 135 | # SlickEdit 136 | *.vpj 137 | *.vpw 138 | *.vpwhistu 139 | *.vtg 140 | *.vpwhist 141 | 142 | # Project exec 143 | obj/ 144 | Debug/ 145 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Language](https://img.shields.io/badge/Language-GCC-green.svg)](https://gcc.gnu.org/) 2 | [![Author](https://img.shields.io/badge/author-Nicol%20TAO-blue.svg)](https://taozj.org/) 3 | [![License](https://img.shields.io/badge/license-BSD-red.svg)](http://yanyiwu.mit-license.org) 4 | 5 | 6 | 基于外网服务器中继的内网传透的代理  7 | 8 | 使用教程: 9 | 10 | 1. 外网服务器运行 sshinner_server; 11 | 2. CLI-DAEMON端运行,记录打印的mach-uuid; 12 | 3. CLI-USR的settings.json修改远程的mach-uuid,并且添加自己需要映射的远程和本地端口; 13 | 14 | 20160608: 15 | 使用了线程池模型;实现了服务端conn之后先发数据的连接类型; 16 | 目前测试通过的服务有:FTP21 SSH22 MYSQL3306。SSH使用比较卡顿,终端不太正常,待修复。 17 | 18 | 20160614: 19 | 添加初始化加密传输,添加线程池初始化。 20 | 21 | 20160621: 22 | 添加SOCKETS5代理功能。 23 | 24 | 20160627: 25 | 添加DNS代理功能。 26 | 默认非root权限是不能绑定#53端口的,测试作用可以: 27 | Debug/dnscrypt-proxy -R cisco -a 127.0.0.1:8013 28 | nslookup -port=8013 taozj.org 127.0.0.1 29 | 本项目用sshinner_client -D启动,端口在配置文件中指明 30 | -------------------------------------------------------------------------------- /client/Makefile: -------------------------------------------------------------------------------- 1 | DEBUG ?= 1 2 | CC = gcc 3 | CCFLAGS = -g -O2 4 | CPPFLAGS = 5 | CXX = g++ 6 | CXXFLAGS = $(CCFLAGS) 7 | PACKAGE = sshinner_client 8 | PACKAGE_NAME = $(PACKAGE) 9 | PACKAGE_STRING = $(PACKAGE_NAME)1.0 10 | PACKAGE_VERSION = 1.0 11 | SHELL = /bin/sh 12 | VERSION = 1.0 13 | SUBDIRS = source 14 | COMMDIRS = ../common 15 | TESTDIR = test 16 | EXTRAFLAGS = -I./include -I../include -lpthread -lrt -lssl -lcrypto -levent -lsystemd -ljson-c -lz 17 | OBJDIR = obj 18 | 19 | vpath %.c $(SUBDIRS) 20 | vpath %.c $(COMMDIRS) 21 | vpath %.c $(TESTDIR) 22 | 23 | 24 | srcs = $(filter-out client.c, $(filter-out server.c, $(notdir $(wildcard $(SUBDIRS)/*.c)))) 25 | commons = $(filter-out main.c, $(notdir $(wildcard $(COMMDIRS)/*.c))) 26 | 27 | objs = $(srcs:%.c=$(OBJDIR)/%.o) 28 | common_objs = $(commons:%.c=$(OBJDIR)/%.o) 29 | 30 | test_srcs = $(notdir $(wildcard $(TESTDIR)/*.c)) 31 | test_objs = $(test_srcs:%.c=$(OBJDIR)/%.o) 32 | test_exec = $(test_srcs:%.c=%) 33 | 34 | ifeq ($(DEBUG),1) 35 | TARGET_DIR=Debug 36 | else 37 | TARGET_DIR=Release 38 | endif 39 | 40 | all : $(PACKAGE) 41 | .PHONY : all 42 | .PHONY : test 43 | 44 | $(PACKAGE) : $(objs) $(common_objs) 45 | $(CC) -c $(CCFLAGS) $(EXTRAFLAGS) $(SUBDIRS)/client.c -o $(OBJDIR)/client.o 46 | $(CC) $(CCFLAGS) $(objs) $(common_objs) $(OBJDIR)/client.o $(EXTRAFLAGS) -o $(TARGET_DIR)/$(PACKAGE) 47 | 48 | $(objs) : $(OBJDIR)/%.o: %.c 49 | @mkdir -p $(OBJDIR) 50 | $(CC) -MMD -c $(CCFLAGS) $(EXTRAFLAGS) $< -o $@ 51 | 52 | $(common_objs) : $(OBJDIR)/%.o: %.c 53 | $(CC) -MMD -c $(CCFLAGS) $(EXTRAFLAGS) $< -o $@ 54 | 55 | #check header for obj reconstruction 56 | -include $(OBJDIR)/*.d 57 | 58 | test : $(test_objs) 59 | $(foreach test_target, $(test_exec), $(CC) $(CCFLAGS) $(EXTRAFLAGS) $(objs) -o $(test_target) $(OBJDIR)/$(test_target).o ;) 60 | $(test_objs) : $(OBJDIR)/%.o: %.c 61 | $(CC) -c $(CCFLAGS) $(EXTRAFLAGS) $< -o $@ 62 | 63 | .PHONY : clean 64 | clean : 65 | -rm -fr $(OBJDIR)/* $(TARGET_DIR)/* 66 | -rm -fr $(test_exec) 67 | -------------------------------------------------------------------------------- /client/include/sshinner_c.h: -------------------------------------------------------------------------------- 1 | #ifndef _SSHINNER_C_H 2 | #define _SSHINNER_C_H 3 | 4 | #include 5 | 6 | #include 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | #include 19 | #include 20 | 21 | #include "sshinner.h" 22 | #include "st_others.h" 23 | #include "st_slist.h" 24 | 25 | #include "sshinner_crypt.h" 26 | 27 | enum CLT_TYPE { 28 | C_DAEMON, C_USR, 29 | }; 30 | 31 | 32 | /* A connection queue. */ 33 | typedef struct conn_item { 34 | SLIST_HEAD list; 35 | int socket; 36 | union { 37 | unsigned long dat; 38 | void* ptr; 39 | } arg; 40 | char buf[260]; 41 | }C_ITEM, *P_C_ITEM; 42 | 43 | struct event; 44 | typedef struct _thread_obj { 45 | pthread_t thread_id; /* unique ID of this thread */ 46 | struct event_base *base; /* libevent handle this thread uses */ 47 | struct event *p_notify_event; /* listen event for notify pipe */ 48 | int notify_receive_fd; /* receiving end of notify pipe */ 49 | int notify_send_fd; /* sending end of notify pipe */ 50 | 51 | pthread_mutex_t q_lock; 52 | SLIST_HEAD conn_queue; /* queue of new connections to handle */ 53 | } THREAD_OBJ, *P_THREAD_OBJ; 54 | 55 | extern RET_T sc_create_ss5_worker_threads(size_t thread_num, P_THREAD_OBJ threads); 56 | 57 | 58 | /** 59 | * 采用本地和服务器数据直接单独连接 60 | */ 61 | // 启动时候加载的端口映射 62 | typedef struct _portmap { 63 | unsigned short usrport; 64 | unsigned short daemonport; 65 | } PORTMAP, *P_PORTMAP; 66 | 67 | // 实际传输时候的端口和bufferevent,为动态创建,动态关闭的 68 | typedef struct _porttrans { 69 | SLIST_HEAD list; 70 | unsigned short l_port; //本地实际传输的端口 71 | struct bufferevent *local_bev; 72 | struct bufferevent *srv_bev; 73 | struct event* extra_ev; //对于DNS这种UDP的类型,不支持bufferevent模式 74 | 75 | int is_enc; 76 | ENCRYPT_CTX ctx_enc; 77 | ENCRYPT_CTX ctx_dec; 78 | 79 | } PORTTRANS, *P_PORTTRANS; 80 | 81 | // 目前硬编码了,实际在服务端是链表没有限制的 82 | #define MAX_PORT_NUM 10 83 | 84 | 85 | static const char* PUBLIC_KEY_FILE = "./ssl/public.key"; 86 | 87 | typedef struct _clt_opt 88 | { 89 | enum CLT_TYPE C_TYPE; //DAEMON/USR 90 | sd_id128_t mach_uuid; 91 | char hostname[128]; 92 | char username[128]; 93 | unsigned long userid; 94 | struct sockaddr_in srv; 95 | struct bufferevent* srv_bev; //主要是控制信息通信 96 | unsigned short ss5_port; // SS5代理只支持用DAEMON端启动,因为USR端没法单独启动 97 | unsigned short dns_port; // DNS代理是否启用,#53端口 98 | unsigned short *dns_transid_port_map; // 搜索得知结果发送到那个端口 99 | sd_id128_t session_uuid; 100 | 101 | unsigned char enc_key[RC4_MD5_IV_LEN]; 102 | 103 | PORTMAP maps[MAX_PORT_NUM]; 104 | 105 | pthread_t main_thread_id; 106 | int thread_num; 107 | P_THREAD_OBJ thread_objs; 108 | 109 | pthread_mutex_t trans_lock; 110 | SLIST_HEAD trans; 111 | }CLT_OPT, *P_CLT_OPT; 112 | 113 | 114 | extern struct event_base *base; 115 | extern CLT_OPT cltopt; 116 | 117 | /** 118 | * 通用类函数 119 | */ 120 | extern RET_T load_settings_client(P_CLT_OPT p_opt); 121 | extern void dump_clt_opts(P_CLT_OPT p_opt); 122 | 123 | 124 | /** 125 | * 客户端与USR/DAEMON通信类函数 126 | */ 127 | // 连接函数 128 | void bufferevent_cb(struct bufferevent *bev, short events, void *ptr); 129 | void accept_conn_cb(struct evconnlistener *listener, 130 | evutil_socket_t fd, struct sockaddr *address, int socklen, 131 | void *ctx); 132 | void accept_error_cb(struct evconnlistener *listener, void *ctx); 133 | // 数据处理类函数 134 | void bufferread_cb(struct bufferevent *bev, void *ptr); 135 | 136 | 137 | void ss5_accept_conn_cb(struct evconnlistener *listener, 138 | evutil_socket_t fd, struct sockaddr *address, int socklen, 139 | void *ctx); 140 | void ss5_bufferread_cb_enc(struct bufferevent *bev, void *ptr); 141 | void ss5_bufferevent_cb(struct bufferevent *bev, short events, void *ptr); 142 | 143 | /** 144 | * 客户端与SRV的通信 145 | */ 146 | RET_T sc_connect_srv(int srv_fd); 147 | RET_T sc_daemon_init_srv(int srv_fd); 148 | RET_T sc_usr_init_srv(int srv_fd); 149 | RET_T sc_daemon_ss5_init_srv(int srv_fd, const char* request, unsigned short l_port); 150 | 151 | RET_T sc_send_head_cmd(int cmd, unsigned long extra_param, 152 | unsigned short usrport, unsigned daemonport); 153 | 154 | void sc_set_eventcb_srv(int srv_fd, struct event_base *base); 155 | 156 | void srv_bufferread_cb(struct bufferevent *bev, void *ptr); 157 | void srv_bufferevent_cb(struct bufferevent *bev, short events, void *ptr); 158 | 159 | P_PORTMAP sc_find_usr_portmap(unsigned short usrport); 160 | P_PORTMAP sc_find_daemon_portmap(unsigned short daemonport, int createit); 161 | 162 | extern P_PORTTRANS sc_find_trans(unsigned short l_sock); 163 | extern P_PORTTRANS sc_create_trans(unsigned short l_sock); 164 | extern RET_T sc_free_trans(P_PORTTRANS p_trans); 165 | extern RET_T sc_free_all_trans(void); 166 | 167 | 168 | /** 169 | * DNS part 170 | */ 171 | 172 | RET_T sc_daemon_dns_init_srv(int srv_fd, unsigned short l_port, 173 | unsigned long salt); 174 | void dns_client_to_proxy_cb(evutil_socket_t socket_fd, short ev_flags, void * ptr); 175 | void dns_bufferread_cb_enc(struct bufferevent *bev, void *ptr); 176 | void dns_bufferevent_cb(struct bufferevent *bev, short events, void *ptr); 177 | 178 | /** 179 | * 线程池索引的映射 180 | */ 181 | static inline P_THREAD_OBJ sc_get_threadobj(unsigned long salt) 182 | { 183 | return (&cltopt.thread_objs[ (salt % cltopt.thread_num)] ); 184 | } 185 | 186 | #endif 187 | -------------------------------------------------------------------------------- /client/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "server": 3 | { 4 | //"ipaddr": "159.203.200.39", 5 | "ipaddr": "127.0.0.1", 6 | "port": 8900, 7 | }, 8 | "client": 9 | { 10 | "username": "taozj", 11 | "ss5_port": 1083, 12 | "dns_port": 8853, //实际使用需要53 13 | "userid": 1222, 14 | //"r_mach_uuid": "1777ea03b44048099aa93e7702662952", //fedora 15 | "r_mach_uuid": "f8421165626e3f61d630656c5647286a", //gentoo 16 | //"r_mach_uuid": "5230acdc7206812a85b2c741573f3d72", //remote 17 | "portmaps": [ 18 | {"usrport":8801, "daemonport":21 }, 19 | {"usrport":8802, "daemonport":22 }, 20 | {"usrport":8808, "daemonport":80 }, 21 | {"usrport":8806, "daemonport":3306 } 22 | ] 23 | }, 24 | } 25 | -------------------------------------------------------------------------------- /client/source/client.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | #include 14 | #include 15 | 16 | #include "st_others.h" 17 | #include "sshinner_c.h" 18 | 19 | 20 | static void usage(void) 21 | { 22 | fprintf(stderr, " *******************************************************************\n" ); 23 | fprintf(stderr, " USAGE: \n"); 24 | fprintf(stderr, " client [-D] [-h] \n"); 25 | fprintf(stderr, " -D 默认USER模式启动,会读取settings.json配置文件,该参数用DEMO模式启动 \n"); 26 | fprintf(stderr, " -h 帮助 \n"); 27 | fprintf(stderr, " *******************************************************************\n"); 28 | } 29 | 30 | struct event_base *base; 31 | CLT_OPT cltopt; 32 | 33 | int main(int argc, char* argv[]) 34 | { 35 | 36 | #if 1 37 | // For debug with segment fault 38 | struct sigaction sa; 39 | sa.sa_handler = backtrace_info; 40 | sigaction(SIGSEGV, &sa, NULL); 41 | 42 | // ignore SIGPIPE 43 | signal(SIGPIPE, SIG_IGN); 44 | signal(SIGCHLD, SIG_IGN); 45 | signal(SIGABRT, SIG_IGN); 46 | 47 | #endif 48 | 49 | int opt_g = 0; 50 | memset(&cltopt, 0, sizeof(CLT_OPT)); 51 | 52 | cltopt.C_TYPE = C_USR; 53 | while( (opt_g = getopt(argc, argv, "Dh")) != -1 ) 54 | { 55 | switch(opt_g) 56 | { 57 | case 'D': 58 | cltopt.C_TYPE = C_DAEMON; 59 | break; 60 | case 'h': 61 | default: 62 | usage(); 63 | exit(EXIT_SUCCESS); 64 | } 65 | } 66 | 67 | if(load_settings_client(&cltopt) == RET_NO) 68 | { 69 | st_d_error("加载配置文件settings.json出错!"); 70 | exit(EXIT_FAILURE); 71 | } 72 | 73 | OpenSSL_add_ssl_algorithms(); 74 | SSL_load_error_strings(); 75 | SSL_library_init(); //SSL_library_init() always returns "1" 76 | 77 | //int sd_id128_from_string(const char *s, sd_id128_t *ret); 78 | sd_id128_get_machine(&cltopt.mach_uuid); 79 | gethostname(cltopt.hostname, sizeof(cltopt.hostname)); 80 | st_d_print("CURRENT MACH_ID:%s, HOSTNAME:%s", SD_ID128_CONST_STR(cltopt.mach_uuid), 81 | cltopt.hostname); 82 | 83 | if (cltopt.C_TYPE == C_DAEMON) 84 | { 85 | cltopt.session_uuid = cltopt.mach_uuid; 86 | st_d_print("PLEASE REMEMEBER SET MACH_ID FOR USER TYPE!"); 87 | } 88 | 89 | dump_clt_opts(&cltopt); 90 | 91 | /*带配置产生event_base对象*/ 92 | struct event_config *cfg; 93 | cfg = event_config_new(); 94 | event_config_avoid_method(cfg, "select"); //避免使用select 95 | event_config_require_features(cfg, EV_FEATURE_ET); //使用边沿触发类型 96 | base = event_base_new_with_config(cfg); 97 | event_config_free(cfg); 98 | st_d_print("当前复用Event模式: %s", event_base_get_method(base)); // epoll 99 | 100 | /*连接服务器*/ 101 | int srv_fd = socket(AF_INET, SOCK_STREAM, 0); 102 | unsigned int optval = 1; 103 | setsockopt(srv_fd, IPPROTO_TCP, TCP_NODELAY, &optval, sizeof(optval));//禁用NAGLE算法 104 | 105 | if(sc_connect_srv(srv_fd) != RET_YES) 106 | { 107 | SYS_ABORT("连接服务器失败!"); 108 | } 109 | 110 | if(cltopt.C_TYPE == C_DAEMON) 111 | { 112 | if (sc_daemon_init_srv(srv_fd) != RET_YES) 113 | SYS_ABORT("(Daemon) 服务器返回错误!"); 114 | } 115 | else 116 | { 117 | if (sc_usr_init_srv(srv_fd) != RET_YES) 118 | SYS_ABORT("(Usr) 服务器返回错误!"); 119 | } 120 | 121 | st_d_print("客户端连接服务器OK!"); 122 | 123 | /** 124 | * USR 建立本地Listen侦听套接字 125 | */ 126 | 127 | if (cltopt.C_TYPE == C_USR) 128 | { 129 | int i = 0; 130 | for (i=0; iis_enc = 1; 255 | p_trans->l_port = cltopt.dns_port; 256 | encrypt_ctx_init(&p_trans->ctx_enc, p_trans->l_port, cltopt.enc_key, 1); 257 | encrypt_ctx_init(&p_trans->ctx_dec, p_trans->l_port, cltopt.enc_key, 0); 258 | // 建立DNS UDP事件侦听 259 | p_trans->extra_ev = event_new(base, dns_socket, EV_READ | EV_PERSIST, 260 | dns_client_to_proxy_cb, p_trans); 261 | 262 | 263 | int dns_srv_fd = socket(AF_INET, SOCK_STREAM, 0); 264 | if(sc_connect_srv(dns_srv_fd) != RET_YES) 265 | { 266 | SYS_ABORT("连接服务器失败!"); 267 | } 268 | 269 | sc_daemon_dns_init_srv(dns_srv_fd, p_trans->l_port, 12333); 270 | evutil_make_socket_nonblocking(dns_srv_fd); 271 | 272 | // later enabled 273 | //event_add(p_trans->extra_ev, NULL) != 0); 274 | 275 | p_trans->srv_bev = bufferevent_socket_new(base, dns_srv_fd, BEV_OPT_CLOSE_ON_FREE); 276 | bufferevent_setcb(p_trans->srv_bev, dns_bufferread_cb_enc, NULL, dns_bufferevent_cb, p_trans); 277 | 278 | st_d_print("[DAEMON]DNS代理创建侦听套接字OK %d", cltopt.dns_port); 279 | } 280 | 281 | sc_set_eventcb_srv(srv_fd, base); 282 | 283 | /** 284 | * Main Loop Here 285 | */ 286 | 287 | event_base_loop(base, 0); 288 | event_base_free(base); 289 | st_d_print("程序退出!!!!"); 290 | return 0; 291 | } 292 | 293 | 294 | -------------------------------------------------------------------------------- /client/source/sshinner_c_dns.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include 6 | 7 | #include "sshinner_c.h" 8 | 9 | 10 | void dns_client_to_proxy_cb(evutil_socket_t socket_fd, short ev_flags, void * ptr) 11 | { 12 | 13 | P_PORTTRANS p_trans = (P_PORTTRANS)ptr; 14 | ENC_FRAME from_f; 15 | ENC_FRAME to_f; 16 | 17 | struct sockaddr_in sin; 18 | memset(&sin, 0, sizeof(sin)); 19 | socklen_t len = sizeof(sin); 20 | 21 | /*这个len是输入输出参数,所以必须先初始化*/ 22 | int nread = recvfrom(socket_fd, (void *)from_f.dat, 4096, 23 | 0, (struct sockaddr *)&sin, &len); 24 | 25 | if (nread > 0) 26 | { 27 | unsigned short trans_id = from_f.dat[0]<<8 | from_f.dat[1]; 28 | cltopt.dns_transid_port_map[trans_id] = sin.sin_port; 29 | st_d_print("ADDING TRANSID-PORT: %u<->%u", trans_id, ntohs(sin.sin_port)); 30 | 31 | from_f.len = nread; 32 | encrypt(&p_trans->ctx_enc, &from_f, &to_f); 33 | bufferevent_write(p_trans->srv_bev, to_f.dat, to_f.len); 34 | } 35 | } 36 | 37 | 38 | void dns_bufferread_cb_enc(struct bufferevent *bev, void *ptr) 39 | { 40 | ENC_FRAME from_f; 41 | ENC_FRAME to_f; 42 | 43 | P_PORTTRANS p_trans = (P_PORTTRANS)ptr; 44 | 45 | struct evbuffer *input = bufferevent_get_input(bev); 46 | struct evbuffer *output = bufferevent_get_output(bev); 47 | 48 | if (bev == p_trans->srv_bev && !p_trans->local_bev) 49 | { 50 | //st_d_print("加密转发数据包SRV->LOCAL"); // 解密 51 | 52 | // 解密 53 | from_f.len = bufferevent_read(p_trans->srv_bev, from_f.dat, FRAME_SIZE); 54 | if (from_f.len > 0) 55 | { 56 | decrypt(&p_trans->ctx_dec, &from_f, &to_f); 57 | if (to_f.len > 0) 58 | { 59 | struct sockaddr_in sin; 60 | memset(&sin, 0, sizeof(sin)); 61 | 62 | unsigned short trans_id = to_f.dat[0]<<8 | to_f.dat[1]; 63 | sin.sin_addr.s_addr = inet_addr("127.0.0.1"); 64 | sin.sin_port = cltopt.dns_transid_port_map[trans_id]; 65 | st_d_print("RETRIVE TRANSID-PORT: %u<->%u", trans_id, ntohs(sin.sin_port)); 66 | 67 | sendto(event_get_fd(p_trans->extra_ev), to_f.dat, to_f.len, 68 | 0, (const struct sockaddr *)&sin, sizeof(sin)); 69 | 70 | } 71 | } 72 | else 73 | { 74 | st_d_error("读取数据出错!"); 75 | } 76 | } 77 | else 78 | { 79 | SYS_ABORT("WRRRRRR!"); 80 | } 81 | 82 | return; 83 | } 84 | 85 | void dns_bufferevent_cb(struct bufferevent *bev, short events, void *ptr) 86 | { 87 | P_PORTTRANS p_trans = (P_PORTTRANS)ptr; 88 | struct event_base *base = bufferevent_get_base(bev); 89 | 90 | //只有使用bufferevent_socket_connect进行的连接才会得到CONNECTED的事件 91 | if (events & BEV_EVENT_CONNECTED) 92 | { 93 | st_d_print("GOT BEV_EVENT_CONNECTED event! "); 94 | } 95 | else if (events & BEV_EVENT_ERROR) 96 | { 97 | st_d_error("GOT BEV_EVENT_ERROR event[%d]! ", p_trans->l_port); 98 | 99 | sc_free_trans(p_trans); 100 | } 101 | else if (events & BEV_EVENT_EOF) 102 | { 103 | st_d_error("GOT BEV_EVENT_EOF event[%d]! ", p_trans->l_port); 104 | sc_free_trans(p_trans); 105 | } 106 | else if (events & BEV_EVENT_TIMEOUT) 107 | { 108 | st_d_error("GOT BEV_EVENT_TIMEOUT event[%d]! ", p_trans->l_port); 109 | 110 | sc_free_trans(p_trans); 111 | } 112 | 113 | return; 114 | } 115 | -------------------------------------------------------------------------------- /client/source/sshinner_c_event.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include 6 | 7 | #include 8 | #include 9 | 10 | #include "sshinner_c.h" 11 | 12 | 13 | /** 14 | * 客户端和远程服务器的交互 15 | */ 16 | void srv_bufferread_cb(struct bufferevent *bev, void *ptr) 17 | { 18 | size_t n = 0; 19 | CTL_HEAD head; 20 | 21 | struct evbuffer *input = bufferevent_get_input(bev); 22 | struct evbuffer *output = bufferevent_get_output(bev); 23 | 24 | if ( evbuffer_remove(input, &head, CTL_HEAD_LEN) != CTL_HEAD_LEN) 25 | { 26 | st_d_print("读取数据包头%d错误!", CTL_HEAD_LEN); 27 | return; 28 | } 29 | 30 | if (!sd_id128_equal(head.mach_uuid, cltopt.session_uuid)) 31 | { 32 | SYS_ABORT("服务端返回UUID校验失败:%s-%s", 33 | SD_ID128_CONST_STR(head.mach_uuid), SD_ID128_CONST_STR(cltopt.session_uuid)); 34 | } 35 | 36 | if (head.cmd == HD_CMD_ERROR) 37 | { 38 | st_d_error("SERVER RETURNED ERROR!"); 39 | exit(EXIT_SUCCESS); 40 | } 41 | 42 | if (head.cmd == HD_CMD_CONN_ACT) 43 | { 44 | P_PORTTRANS p_trans = sc_find_trans(head.extra_param); 45 | if (!p_trans) 46 | { 47 | SYS_ABORT("本地未找到连接信息:%d", head.extra_param); 48 | } 49 | 50 | bufferevent_enable(p_trans->local_bev, EV_READ|EV_WRITE); 51 | bufferevent_enable(p_trans->srv_bev, EV_READ|EV_WRITE); 52 | 53 | st_d_print("开始传输数据:%d", head.extra_param); 54 | } 55 | if (head.cmd == HD_CMD_END_TRANS) 56 | { 57 | P_PORTTRANS p_trans = sc_find_trans(head.extra_param); 58 | if (p_trans) 59 | { 60 | st_d_print("EXTRA CLOSE TRANS: %d", head.extra_param); 61 | 62 | pthread_mutex_lock(&cltopt.trans_lock); 63 | if (p_trans->srv_bev) 64 | { 65 | bufferevent_free(p_trans->srv_bev); 66 | p_trans->srv_bev = NULL; 67 | } 68 | if (p_trans->local_bev) 69 | { 70 | bufferevent_free(p_trans->local_bev); 71 | p_trans->local_bev = NULL; 72 | } 73 | pthread_mutex_unlock(&cltopt.trans_lock); 74 | 75 | } 76 | else 77 | { 78 | st_d_error("本地未找到连接信息:%d", head.extra_param); 79 | } 80 | } 81 | if (head.cmd == HD_CMD_SS5_ACT) 82 | { 83 | // OK,返回给本地程序告知可以开始传输了 84 | // 这个绑定地址目前还没利用,主要是需要FTP这类需要带外传输另外连接端口的 85 | char ret_msg[10] = "\x05\x00\x00\x01\x00\x00\x00\x00\x10\x10"; 86 | 87 | P_PORTTRANS p_trans = sc_find_trans(head.extra_param); 88 | if (!p_trans) 89 | { 90 | // 也有可能先被释放了 91 | st_d_error("本地SS5未找到连接信息:%d", head.extra_param); 92 | return; 93 | } 94 | 95 | bufferevent_enable(p_trans->local_bev, EV_READ|EV_WRITE); 96 | bufferevent_enable(p_trans->srv_bev, EV_READ|EV_WRITE); 97 | 98 | bufferevent_write(p_trans->local_bev, ret_msg, sizeof(ret_msg)); 99 | st_d_print("SS5准备传输数据:%d", head.extra_param); 100 | 101 | return; 102 | } 103 | if (head.cmd == HD_CMD_DNS_ACT) 104 | { 105 | // OK,返回给本地程序告知可以开始传输了 106 | P_PORTTRANS p_trans = sc_find_trans(head.extra_param); 107 | 108 | assert(p_trans->local_bev == NULL); 109 | 110 | event_add(p_trans->extra_ev, NULL); 111 | bufferevent_enable(p_trans->srv_bev, EV_READ|EV_WRITE); 112 | 113 | st_d_print("DNS准备传输数据:%d", head.extra_param); 114 | 115 | return; 116 | } 117 | if (head.cmd == HD_CMD_CONN) 118 | { 119 | assert(cltopt.C_TYPE == C_DAEMON); 120 | if (cltopt.C_TYPE == C_DAEMON) 121 | { 122 | sc_find_daemon_portmap(head.daemonport, 1); 123 | P_PORTTRANS p_trans = sc_create_trans(head.extra_param); 124 | p_trans->is_enc = 0; 125 | 126 | if (!p_trans) 127 | { 128 | st_d_error("本地无空闲TRANS!"); 129 | return; 130 | } 131 | 132 | /*建立本地连接*/ 133 | int local_fd = socket(AF_INET, SOCK_STREAM, 0); 134 | unsigned int optval = 1; 135 | setsockopt(local_fd, IPPROTO_TCP, TCP_NODELAY, &optval, sizeof(optval));//禁用NAGLE算法 136 | 137 | int reuseaddr_on = 1; 138 | if (setsockopt(local_fd, SOL_SOCKET, SO_REUSEADDR, &reuseaddr_on, 139 | sizeof(reuseaddr_on)) == -1) 140 | { 141 | st_d_error("Reuse socket opt faile!\n"); 142 | return; 143 | } 144 | struct sockaddr_in local_srv; 145 | local_srv.sin_family = AF_INET; 146 | local_srv.sin_addr.s_addr = inet_addr("127.0.0.1"); 147 | local_srv.sin_port = htons(head.daemonport); 148 | 149 | if (connect(local_fd, (struct sockaddr *)&local_srv, sizeof(local_srv))) 150 | { 151 | st_d_error("连接本地端口%d失败!", head.daemonport); 152 | return; 153 | } 154 | else 155 | { 156 | st_d_print("连接本地端口%d OK!", head.daemonport); 157 | } 158 | 159 | 160 | /*建立服务器连接*/ 161 | int srv_fd = socket(AF_INET, SOCK_STREAM, 0); 162 | if(sc_connect_srv(srv_fd) != RET_YES) 163 | { 164 | st_d_error("连接服务器失败!"); 165 | return; 166 | } 167 | 168 | 169 | struct event_base *base = bufferevent_get_base(bev); 170 | 171 | evutil_make_socket_nonblocking(local_fd); 172 | struct bufferevent *local_bev = 173 | bufferevent_socket_new(base, local_fd, BEV_OPT_CLOSE_ON_FREE); 174 | bufferevent_setcb(local_bev, bufferread_cb, NULL, bufferevent_cb, p_trans); 175 | //bufferevent_enable(local_bev, EV_READ|EV_WRITE); 176 | 177 | evutil_make_socket_nonblocking(srv_fd); 178 | struct bufferevent *srv_bev = 179 | bufferevent_socket_new(base, srv_fd, BEV_OPT_CLOSE_ON_FREE); 180 | bufferevent_setcb(srv_bev, bufferread_cb, NULL, bufferevent_cb, p_trans); 181 | //bufferevent_enable(srv_bev, EV_READ|EV_WRITE); 182 | 183 | 184 | p_trans->l_port = head.extra_param; 185 | p_trans->local_bev = local_bev; 186 | p_trans->srv_bev = srv_bev; 187 | 188 | /* 向服务器报告连接请求 */ 189 | // 必须要发送CONN包,触发这个连接转移到线程池处理 190 | CTL_HEAD ret_head; 191 | memset(&ret_head, 0, CTL_HEAD_LEN); 192 | ret_head.cmd = HD_CMD_CONN; 193 | ret_head.extra_param = p_trans->l_port; 194 | ret_head.mach_uuid = cltopt.session_uuid; 195 | ret_head.direct = DAEMON_USR; 196 | 197 | bufferevent_write(srv_bev, &ret_head, CTL_HEAD_LEN); 198 | 199 | st_d_print("DAEMON端准备OK!"); 200 | } 201 | } 202 | 203 | } 204 | 205 | 206 | void srv_bufferevent_cb(struct bufferevent *bev, short events, void *ptr) 207 | { 208 | struct event_base *base = bufferevent_get_base(bev); 209 | int loop_terminate_flag = 0; 210 | 211 | //只有使用bufferevent_socket_connect进行的连接才会得到CONNECTED的事件 212 | if (events & BEV_EVENT_CONNECTED) 213 | { 214 | st_d_print("GOT BEV_EVENT_CONNECTED event! "); 215 | } 216 | else if (events & BEV_EVENT_ERROR) 217 | { 218 | st_d_error("GOT BEV_EVENT_ERROR event! "); 219 | loop_terminate_flag = 1; 220 | } 221 | else if (events & BEV_EVENT_EOF) 222 | { 223 | st_d_print("GOT BEV_EVENT_EOF event! "); 224 | 225 | // main_be连接断开,这时候:如果是DAEMON端主动断开,那么USR端也要断开 226 | // 否则,就让DAEMON进行重置(重新连接服务器) 227 | // 任何情况下,所有的服务都必须断开 228 | 229 | // BEV_OPT_CLOSE_ON_FREE already closed the socket 230 | if (cltopt.C_TYPE == C_USR) 231 | { 232 | st_d_print("DAEMON已经退出,本端挂起!"); 233 | exit(EXIT_SUCCESS); 234 | } 235 | else 236 | { 237 | sc_free_all_trans(); 238 | st_d_print("DAEMON端重连服务器!"); 239 | 240 | int srv_fd = socket(AF_INET, SOCK_STREAM, 0); 241 | if (sc_connect_srv(srv_fd) != RET_YES) 242 | { 243 | st_d_error("连接服务器失败!"); 244 | event_base_loopexit(base, NULL); 245 | } 246 | 247 | if (sc_daemon_init_srv(srv_fd) != RET_YES) 248 | { 249 | st_d_error("(DAEMON)服务端返回错误!"); 250 | event_base_loopexit(base, NULL); 251 | } 252 | 253 | sc_set_eventcb_srv(srv_fd, base); 254 | st_d_print("(DAEMON)重连OK!"); 255 | 256 | } 257 | 258 | } 259 | else if (events & BEV_EVENT_TIMEOUT) 260 | { 261 | st_d_print("GOT BEV_EVENT_TIMEOUT event! "); 262 | } 263 | 264 | if (loop_terminate_flag) 265 | { 266 | bufferevent_free(bev); 267 | event_base_loopexit(base, NULL); 268 | } 269 | 270 | return; 271 | } 272 | 273 | /** 274 | * 客户端处理本地USR/DAEMON的请求 275 | */ 276 | 277 | void bufferevent_cb(struct bufferevent *bev, short events, void *ptr) 278 | { 279 | P_PORTTRANS p_trans = (P_PORTTRANS)ptr; 280 | struct event_base *base = bufferevent_get_base(bev); 281 | 282 | //只有使用bufferevent_socket_connect进行的连接才会得到CONNECTED的事件 283 | if (events & BEV_EVENT_CONNECTED) 284 | { 285 | st_d_print("GOT BEV_EVENT_CONNECTED event! "); 286 | } 287 | else if (events & BEV_EVENT_ERROR) 288 | { 289 | st_d_error("GOT BEV_EVENT_ERROR event[%d]! ", p_trans->l_port); 290 | 291 | sc_free_trans(p_trans); 292 | } 293 | else if (events & BEV_EVENT_EOF) 294 | { 295 | st_d_error("GOT BEV_EVENT_EOF event[%d]! ", p_trans->l_port); 296 | 297 | sc_free_trans(p_trans); 298 | } 299 | else if (events & BEV_EVENT_TIMEOUT) 300 | { 301 | st_d_error("GOT BEV_EVENT_TIMEOUT event[%d]! ", p_trans->l_port); 302 | 303 | sc_free_trans(p_trans); 304 | } 305 | 306 | return; 307 | } 308 | 309 | 310 | /** 311 | * 客户端程序,USR/DAEMON都是从应用程序读取到数据了,然后推送到SRV进行转发到服务器 312 | */ 313 | void bufferread_cb(struct bufferevent *bev, void *ptr) 314 | { 315 | P_PORTTRANS p_trans = (P_PORTTRANS)ptr; 316 | 317 | struct evbuffer *input = bufferevent_get_input(bev); 318 | struct evbuffer *output = bufferevent_get_output(bev); 319 | 320 | if (bev == p_trans->local_bev && p_trans->srv_bev) 321 | { 322 | bufferevent_write_buffer(p_trans->srv_bev, bufferevent_get_input(bev)); 323 | } 324 | else if (bev == p_trans->srv_bev && p_trans->local_bev) 325 | { 326 | bufferevent_write_buffer(p_trans->local_bev, bufferevent_get_input(bev)); 327 | } 328 | else 329 | { 330 | SYS_ABORT("WRRRRRR!"); 331 | } 332 | 333 | return; 334 | } 335 | 336 | /** 337 | * 只会在USR端被调用 338 | */ 339 | void accept_conn_cb(struct evconnlistener *listener, 340 | evutil_socket_t fd, struct sockaddr *address, int socklen, 341 | void *ctx) 342 | { 343 | P_PORTMAP p_map = (P_PORTMAP)ctx; 344 | char hbuf[NI_MAXHOST], sbuf[NI_MAXSERV]; 345 | 346 | getnameinfo (address, socklen, 347 | hbuf, sizeof(hbuf),sbuf, sizeof(sbuf), 348 | NI_NUMERICHOST | NI_NUMERICSERV); 349 | 350 | st_print("WELCOME NEW CONNECT (HOST=%s, PORT=%s)\n", hbuf, sbuf); 351 | 352 | /* We got a new connection! Set up a bufferevent for it. */ 353 | struct event_base *base = evconnlistener_get_base(listener); 354 | 355 | int srv_fd = socket(AF_INET, SOCK_STREAM, 0); 356 | 357 | unsigned int optval = 1; 358 | setsockopt(srv_fd, IPPROTO_TCP, TCP_NODELAY, &optval, sizeof(optval));//禁用NAGLE算法 359 | if(sc_connect_srv(srv_fd) != RET_YES) 360 | { 361 | st_d_error("连接服务器失败!"); 362 | return; 363 | } 364 | 365 | P_PORTTRANS p_trans = sc_create_trans(atoi(sbuf)); 366 | 367 | if (!p_trans) 368 | { 369 | st_d_error("本地无空闲TRANS!"); 370 | return; 371 | } 372 | 373 | struct bufferevent *local_bev = 374 | bufferevent_socket_new(base, fd, BEV_OPT_CLOSE_ON_FREE); 375 | assert(local_bev); 376 | bufferevent_setcb(local_bev, bufferread_cb, NULL, bufferevent_cb, p_trans); 377 | //bufferevent_enable(local_bev, EV_READ|EV_WRITE); 378 | 379 | struct bufferevent *srv_bev = 380 | bufferevent_socket_new(base, srv_fd, BEV_OPT_CLOSE_ON_FREE); 381 | assert(srv_bev); 382 | bufferevent_setcb(srv_bev, bufferread_cb, NULL, bufferevent_cb, p_trans); 383 | //bufferevent_enable(srv_bev, EV_READ|EV_WRITE); 384 | 385 | p_trans->is_enc = 0; 386 | p_trans->l_port = atoi(sbuf); 387 | p_trans->local_bev = local_bev; 388 | p_trans->srv_bev = srv_bev; 389 | 390 | st_d_print("DDDDD: 当前活动连接数:[[[ %d ]]]", 391 | slist_count(&cltopt.trans)); 392 | 393 | /* 向服务器报告连接请求 */ 394 | CTL_HEAD ret_head; 395 | memset(&ret_head, 0, CTL_HEAD_LEN); 396 | ret_head.cmd = HD_CMD_CONN; 397 | ret_head.daemonport = p_map->daemonport; 398 | ret_head.usrport = p_map->usrport; 399 | ret_head.extra_param = atoi(sbuf); 400 | ret_head.mach_uuid = cltopt.session_uuid; 401 | ret_head.direct = USR_DAEMON; 402 | 403 | bufferevent_write(srv_bev, &ret_head, CTL_HEAD_LEN); 404 | 405 | st_d_print("客户端创建BEV OK!"); 406 | 407 | /** 408 | * 有些服务是conn连接之后,服务端先发消息,然后客户端再进行响应的,所以 409 | * 为了避免这种情况,客户端接收到conn消息之后,需要先向DAEMON端发送一个控制 410 | * 消息,打通DAEMON端的数据传输接口 411 | */ 412 | 413 | return; 414 | } 415 | 416 | void accept_error_cb(struct evconnlistener *listener, void *ctx) 417 | { 418 | struct event_base *base = evconnlistener_get_base(listener); 419 | int err = EVUTIL_SOCKET_ERROR(); 420 | 421 | st_d_error( "Got an error %d (%s) on the listener. " 422 | "Shutting down...\n", err, evutil_socket_error_to_string(err)); 423 | 424 | //event_base_loopexit(base, NULL); 425 | 426 | return; 427 | } 428 | -------------------------------------------------------------------------------- /client/source/sshinner_c_sockets.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include 6 | 7 | #include 8 | #include 9 | 10 | #include "sshinner_c.h" 11 | 12 | 13 | void ss5_bufferread_cb_enc(struct bufferevent *bev, void *ptr) 14 | { 15 | ENC_FRAME from_f; 16 | ENC_FRAME to_f; 17 | 18 | P_PORTTRANS p_trans = (P_PORTTRANS)ptr; 19 | 20 | struct evbuffer *input = bufferevent_get_input(bev); 21 | struct evbuffer *output = bufferevent_get_output(bev); 22 | 23 | if (bev == p_trans->local_bev && p_trans->srv_bev) 24 | { 25 | //st_d_print("加密转发数据包LOCAL->SRV"); // 解密 26 | 27 | // 加密 28 | from_f.len = bufferevent_read(p_trans->local_bev, from_f.dat, FRAME_SIZE); 29 | if (from_f.len > 0) 30 | { 31 | encrypt(&p_trans->ctx_enc, &from_f, &to_f); 32 | bufferevent_write(p_trans->srv_bev, to_f.dat, to_f.len); 33 | } 34 | else 35 | { 36 | st_d_error("读取数据出错!"); 37 | } 38 | } 39 | else if (bev == p_trans->srv_bev && p_trans->local_bev) 40 | { 41 | //st_d_print("加密转发数据包SRV->LOCAL"); // 解密 42 | 43 | // 解密 44 | from_f.len = bufferevent_read(p_trans->srv_bev, from_f.dat, FRAME_SIZE); 45 | if (from_f.len > 0) 46 | { 47 | decrypt(&p_trans->ctx_dec, &from_f, &to_f); 48 | bufferevent_write(p_trans->local_bev, to_f.dat, to_f.len); 49 | } 50 | else 51 | { 52 | st_d_error("读取数据出错!"); 53 | } 54 | } 55 | else 56 | { 57 | SYS_ABORT("WRRRRRR!"); 58 | } 59 | 60 | return; 61 | } 62 | 63 | void ss5_bufferevent_cb(struct bufferevent *bev, short events, void *ptr) 64 | { 65 | P_PORTTRANS p_trans = (P_PORTTRANS)ptr; 66 | struct event_base *base = bufferevent_get_base(bev); 67 | 68 | //只有使用bufferevent_socket_connect进行的连接才会得到CONNECTED的事件 69 | if (events & BEV_EVENT_CONNECTED) 70 | { 71 | st_d_print("GOT BEV_EVENT_CONNECTED event! "); 72 | } 73 | else if (events & BEV_EVENT_ERROR) 74 | { 75 | st_d_error("GOT BEV_EVENT_ERROR event[%d]! ", p_trans->l_port); 76 | 77 | sc_free_trans(p_trans); 78 | } 79 | else if (events & BEV_EVENT_EOF) 80 | { 81 | st_d_error("GOT BEV_EVENT_EOF event[%d]! ", p_trans->l_port); 82 | sc_free_trans(p_trans); 83 | } 84 | else if (events & BEV_EVENT_TIMEOUT) 85 | { 86 | st_d_error("GOT BEV_EVENT_TIMEOUT event[%d]! ", p_trans->l_port); 87 | 88 | sc_free_trans(p_trans); 89 | } 90 | 91 | return; 92 | } 93 | 94 | /** 95 | * 只会在DAEMON端调用 96 | */ 97 | void ss5_accept_conn_cb(struct evconnlistener *listener, 98 | evutil_socket_t fd, struct sockaddr *address, int socklen, 99 | void *ctx) 100 | { 101 | char hbuf[NI_MAXHOST], sbuf[NI_MAXSERV]; 102 | char buf[260]; 103 | 104 | getnameinfo (address, socklen, 105 | hbuf, sizeof(hbuf),sbuf, sizeof(sbuf), 106 | NI_NUMERICHOST | NI_NUMERICSERV); 107 | 108 | st_print("SS5 WELCOME NEW CONNECT (HOST=%s, PORT=%s)\n", hbuf, sbuf); 109 | 110 | /** 读取代理参数*/ 111 | // blocking socket here! 112 | memset(buf, 0, sizeof(buf)); 113 | 114 | unsigned int optval = 1; 115 | setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &optval, sizeof(optval));//禁用NAGLE算法 116 | 117 | read(fd, buf, sizeof(buf)); //actually 1+1+1~255 118 | if (buf[0] != 0x05) 119 | { 120 | st_d_error("ONLY SUPPORT SS5: %x!", buf[0]); 121 | close(fd); 122 | return; 123 | } 124 | 125 | write(fd, "\x05\x00", 2); // NO AUTHENTICATION REQUIRED 126 | 127 | // Fixed Head 128 | // VER CMD RSV ATYP 129 | memset(buf, 0, sizeof(buf)); 130 | read(fd, buf, sizeof(buf)); 131 | if (buf[0] != 0x05 || buf[1] != 0x01 /*CONNECT*/ || 132 | (buf[3] != 0x01 /*IP v4*/ && buf[3] != 0x03 /*DOMAINNAME*/ )) 133 | { 134 | st_d_error("FIX Request head check error!"); 135 | close(fd); 136 | return; 137 | } 138 | 139 | P_C_ITEM p_c = (P_C_ITEM)calloc(sizeof(C_ITEM), 1); 140 | if (!p_c) 141 | { 142 | st_d_error("申请内存[%d]失败!", sizeof(C_ITEM)); 143 | close(fd); 144 | return; 145 | } 146 | 147 | P_PORTTRANS p_trans = sc_create_trans(atoi(sbuf)); 148 | if (!p_trans) 149 | { 150 | st_d_error("本地无空闲TRANS!"); 151 | close(fd); 152 | return; 153 | } 154 | 155 | p_trans->is_enc = 1; 156 | p_trans->l_port = atoi(sbuf); //先占用 157 | 158 | P_THREAD_OBJ p_threadobj = sc_get_threadobj(p_trans->l_port); 159 | p_c->socket = fd; 160 | p_c->arg.ptr = p_trans; 161 | memcpy(p_c->buf, buf, sizeof(p_c->buf)); 162 | 163 | 164 | pthread_mutex_lock(&p_threadobj->q_lock); 165 | slist_add(&p_c->list, &p_threadobj->conn_queue); 166 | pthread_mutex_unlock(&p_threadobj->q_lock); 167 | 168 | write(p_threadobj->notify_send_fd, "Q", 1); 169 | 170 | return; 171 | } 172 | -------------------------------------------------------------------------------- /client/source/sshinner_c_threads.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include 6 | #include 7 | 8 | #include 9 | 10 | #include "sshinner_c.h" 11 | 12 | 13 | /* 14 | * Number of worker threads that have finished setting themselves up. 15 | */ 16 | static int init_count = 0; 17 | static pthread_mutex_t init_lock; 18 | static pthread_cond_t init_cond; 19 | 20 | 21 | static void *thread_run(void *arg); 22 | static void thread_process(int fd, short which, void *arg); 23 | 24 | static void wait_for_thread_registration(int nthreads) 25 | { 26 | while (init_count < nthreads) { 27 | pthread_cond_wait(&init_cond, &init_lock); 28 | } 29 | } 30 | 31 | static void register_thread_initialized(void) 32 | { 33 | pthread_mutex_lock(&init_lock); 34 | init_count++; 35 | st_d_print("线程数目[%d]OK!", init_count); 36 | pthread_cond_signal(&init_cond); 37 | pthread_mutex_unlock(&init_lock); 38 | } 39 | 40 | extern RET_T sc_create_ss5_worker_threads(size_t thread_num, P_THREAD_OBJ threads) 41 | { 42 | int i = 0; 43 | 44 | pthread_attr_t attr; 45 | int ret = 0; 46 | 47 | pthread_mutex_init(&init_lock, NULL); 48 | pthread_cond_init(&init_cond, NULL); 49 | 50 | for (i=0; i < thread_num; ++i) 51 | { 52 | int fds[2]; 53 | if (pipe(fds)) { 54 | SYS_ABORT("Can't create notify pipe"); 55 | } 56 | 57 | threads[i].notify_receive_fd = fds[0]; 58 | threads[i].notify_send_fd = fds[1]; 59 | 60 | threads[i].base = event_init(); 61 | if (! threads[i].base ){ 62 | SYS_ABORT("Can't allocate event base"); 63 | } 64 | threads[i].p_notify_event = event_new(threads[i].base, threads[i].notify_receive_fd, 65 | EV_READ | EV_PERSIST, thread_process, &threads[i]); 66 | 67 | if (! threads[i].p_notify_event ){ 68 | SYS_ABORT("Can't allocate new event"); 69 | } 70 | 71 | if (event_add(threads[i].p_notify_event, 0) == -1) { 72 | SYS_ABORT("Can't monitor libevent notify pipe"); 73 | } 74 | 75 | slist_init(&threads[i].conn_queue); 76 | pthread_mutex_init(&threads[i].q_lock, NULL); 77 | 78 | pthread_attr_init(&attr); 79 | if ((ret = pthread_create(&threads[i].thread_id, &attr, thread_run, (void*)(&threads[i]))) != 0) 80 | { 81 | SYS_ABORT("Cannot create worker thread %s", strerror(ret)); 82 | } 83 | } 84 | 85 | 86 | pthread_mutex_lock(&init_lock); 87 | wait_for_thread_registration(thread_num); 88 | pthread_mutex_unlock(&init_lock); 89 | 90 | } 91 | 92 | static void *thread_run(void *arg) 93 | { 94 | P_THREAD_OBJ me = (P_THREAD_OBJ)arg; 95 | 96 | register_thread_initialized(); 97 | 98 | event_base_loop(me->base, 0); 99 | 100 | return NULL; 101 | } 102 | 103 | 104 | /* 105 | * Processes an incoming "handle a new connection" item. This is called when 106 | * input arrives on the libevent wakeup pipe. 107 | */ 108 | static void thread_process(int fd, short which, void *arg) 109 | { 110 | P_THREAD_OBJ p_threadobj = (P_THREAD_OBJ)arg; 111 | 112 | P_SLIST_HEAD p_list = NULL; 113 | P_C_ITEM p_c_item = NULL; 114 | P_PORTTRANS p_trans = NULL; 115 | 116 | char buf[1]; 117 | CTL_HEAD head; 118 | 119 | if (read(fd, buf, 1) != 1) 120 | { 121 | st_d_error("Can't read from libevent pipe\n"); 122 | return; 123 | } 124 | 125 | switch (buf[0]) 126 | { 127 | case 'Q': 128 | pthread_mutex_lock(&p_threadobj->q_lock); 129 | p_list = slist_fetch(&p_threadobj->conn_queue); 130 | pthread_mutex_unlock(&p_threadobj->q_lock); 131 | if (!p_list) 132 | { 133 | st_d_error("无法从任务队列中获取任务!"); 134 | return; 135 | } 136 | 137 | p_c_item = list_entry(p_list, C_ITEM, list); 138 | p_trans = (P_PORTTRANS)p_c_item->arg.ptr; 139 | 140 | int srv_fd = socket(AF_INET, SOCK_STREAM, 0); 141 | if(sc_connect_srv(srv_fd) != RET_YES) 142 | { 143 | st_d_error("连接服务器失败!"); 144 | sc_free_trans(p_trans); 145 | free(p_c_item); 146 | return; 147 | } 148 | 149 | if (sc_daemon_ss5_init_srv(srv_fd, p_c_item->buf, p_trans->l_port) != RET_YES) 150 | { 151 | close(srv_fd); 152 | sc_free_trans(p_trans); 153 | free(p_c_item); 154 | st_d_error("服务器返回错误!"); 155 | return; 156 | } 157 | 158 | evutil_make_socket_nonblocking(p_c_item->socket); 159 | struct bufferevent *local_bev = 160 | bufferevent_socket_new(p_threadobj->base, p_c_item->socket, BEV_OPT_CLOSE_ON_FREE); 161 | assert(local_bev); 162 | bufferevent_setcb(local_bev, ss5_bufferread_cb_enc, NULL, ss5_bufferevent_cb, p_trans); 163 | //fferevent_enable(local_bev, EV_READ|EV_WRITE); 164 | 165 | evutil_make_socket_nonblocking(srv_fd); 166 | struct bufferevent *new_bev = 167 | bufferevent_socket_new(p_threadobj->base, srv_fd, BEV_OPT_CLOSE_ON_FREE); 168 | assert(new_bev); 169 | bufferevent_setcb(new_bev, ss5_bufferread_cb_enc, NULL, ss5_bufferevent_cb, p_trans); 170 | //bufferevent_enable(new_bev, EV_READ|EV_WRITE); 171 | 172 | assert(p_trans->is_enc); 173 | encrypt_ctx_init(&p_trans->ctx_enc, p_trans->l_port, cltopt.enc_key, 1); 174 | encrypt_ctx_init(&p_trans->ctx_dec, p_trans->l_port, cltopt.enc_key, 0); 175 | 176 | p_trans->local_bev = local_bev; 177 | p_trans->srv_bev = new_bev; 178 | 179 | st_d_print("THREAD FOR (%d) OK!", p_trans->l_port); 180 | 181 | st_d_print("DDDDD: 当前活动连接数:[[[ %d ]]], 已增加:[%d]", 182 | slist_count(&cltopt.trans), p_trans->l_port); 183 | 184 | free(p_c_item); 185 | 186 | break; 187 | 188 | default: 189 | SYS_ABORT("WHAT DO I GET: %c", buf[0]); 190 | break; 191 | } 192 | 193 | return; 194 | } 195 | 196 | -------------------------------------------------------------------------------- /client/source/sshinner_c_utils.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | 6 | #include 7 | #include 8 | 9 | #include "sshinner_c.h" 10 | 11 | static RET_T json_fetch_and_copy(struct json_object *p_obj, const char* key, char* store, int max_len) 12 | { 13 | json_object *p_store_obj = NULL; 14 | 15 | if (!p_obj || !key || !strlen(key) || !store) 16 | return RET_NO; 17 | 18 | if (json_object_object_get_ex(p_obj, key, &p_store_obj) && 19 | json_object_get_string_len(p_store_obj)) 20 | { 21 | strncpy(store, json_object_get_string(p_store_obj), max_len); 22 | return RET_YES; 23 | } 24 | 25 | return RET_NO; 26 | } 27 | 28 | extern RET_T load_settings_client(P_CLT_OPT p_opt) 29 | { 30 | json_object *p_obj = NULL; 31 | json_object *p_class = NULL; 32 | json_object *p_store_obj = NULL; 33 | char *ptr = NULL; 34 | 35 | if (!p_opt) 36 | return RET_NO; 37 | 38 | if( ! (p_obj = json_object_from_file("settings.json")) ) 39 | return RET_NO; 40 | 41 | slist_init(&p_opt->trans); 42 | 43 | if(json_object_object_get_ex(p_obj,"server",&p_class)) 44 | { 45 | st_d_print("handling server configuration...."); 46 | 47 | if (json_object_object_get_ex(p_class,"ipaddr",&p_store_obj)) 48 | { 49 | ptr = json_object_get_string(p_store_obj); 50 | p_opt->srv.sin_family = AF_INET; 51 | p_opt->srv.sin_addr.s_addr = inet_addr(ptr); 52 | } 53 | 54 | if (json_object_object_get_ex(p_class,"port",&p_store_obj)) 55 | p_opt->srv.sin_port = htons(json_object_get_int(p_store_obj)); 56 | } 57 | 58 | if(json_object_object_get_ex(p_obj,"client",&p_class)) 59 | { 60 | st_d_print("handling client configuration...."); 61 | 62 | json_fetch_and_copy(p_class, "username", p_opt->username, 128); 63 | 64 | if (json_object_object_get_ex(p_class,"userid",&p_store_obj)) 65 | p_opt->userid = json_object_get_int64(p_store_obj); 66 | 67 | if (json_object_object_get_ex(p_class,"ss5_port",&p_store_obj)) 68 | p_opt->ss5_port = json_object_get_int64(p_store_obj); 69 | else 70 | p_opt->ss5_port = 0; 71 | 72 | if (json_object_object_get_ex(p_class,"dns_port",&p_store_obj)) 73 | p_opt->dns_port = json_object_get_int64(p_store_obj); //#53 74 | else 75 | p_opt->dns_port = 0; 76 | 77 | if (p_opt->C_TYPE == C_DAEMON) 78 | { 79 | p_opt->session_uuid = p_opt->mach_uuid; 80 | } 81 | else 82 | { 83 | if (json_object_object_get_ex(p_class,"r_mach_uuid",&p_store_obj)) 84 | { 85 | ptr = json_object_get_string(p_store_obj); 86 | sd_id128_from_string(ptr, &p_opt->session_uuid); 87 | } 88 | 89 | if (json_object_object_get_ex(p_class,"portmaps",&p_store_obj)) 90 | { 91 | size_t len = json_object_array_length(p_store_obj); 92 | if (len > MAX_PORT_NUM) 93 | { 94 | st_d_error("只支持%d/%d", MAX_PORT_NUM, len); 95 | len = MAX_PORT_NUM; 96 | } 97 | size_t i = 0; 98 | int from, to; 99 | for (i=0; imaps[i].usrport = json_object_get_int( 103 | json_object_object_get(p_tmp, "usrport")); 104 | p_opt->maps[i].daemonport = json_object_get_int( 105 | json_object_object_get(p_tmp, "daemonport")); 106 | } 107 | } 108 | } 109 | 110 | } 111 | 112 | json_object_put(p_obj); 113 | return RET_YES; 114 | } 115 | 116 | extern void dump_clt_opts(P_CLT_OPT p_opt) 117 | { 118 | if (!p_opt) 119 | return; 120 | 121 | st_d_print("WORK MODE: %s", p_opt->C_TYPE==C_DAEMON ? 122 | "C_DAEMON":"C_USR"); 123 | 124 | st_d_print(""); 125 | st_d_print("USRNAME:%s", p_opt->username); 126 | st_d_print("USRID:%lu", p_opt->userid); 127 | st_d_print("HOSTNAME:%s", p_opt->hostname); 128 | st_d_print("HOSTMACHID:%s", SD_ID128_CONST_STR(p_opt->mach_uuid)); 129 | 130 | st_d_print(""); 131 | st_d_print("SERVERIP:%s", inet_ntoa(p_opt->srv.sin_addr)); 132 | st_d_print("SERVERPORT:%d", ntohs(p_opt->srv.sin_port)); 133 | 134 | st_d_print(""); 135 | st_d_print("SESSION_UUID: %s", SD_ID128_CONST_STR(p_opt->session_uuid)); 136 | 137 | st_d_print(""); 138 | st_d_print("SOCKET5 PROXY: %d", p_opt->ss5_port); 139 | st_d_print("DNS PROXY: %d", p_opt->dns_port); 140 | 141 | if (p_opt->C_TYPE == C_USR) 142 | { 143 | int i = 0; 144 | for (i = 0; i < MAX_PORT_NUM; i++) 145 | { 146 | if (p_opt->maps[i].usrport) 147 | { 148 | st_d_print("FROM:%d, TO:%d", p_opt->maps[i].usrport, 149 | p_opt->maps[i].daemonport); 150 | } 151 | else 152 | break; 153 | } 154 | } 155 | 156 | return; 157 | } 158 | 159 | 160 | // used from DAEMON SIDE 161 | P_PORTMAP sc_find_daemon_portmap(unsigned short daemonport, int createit) 162 | { 163 | P_PORTMAP p_map = NULL; 164 | int i = 0; 165 | 166 | for (i = 0; i < MAX_PORT_NUM; i++) 167 | { 168 | if (cltopt.maps[i].daemonport == daemonport) 169 | { 170 | p_map = &cltopt.maps[i]; 171 | return p_map; 172 | } 173 | } 174 | 175 | if (! createit) 176 | return NULL; 177 | 178 | for (i = 0; i < MAX_PORT_NUM; i++) 179 | { 180 | if (cltopt.maps[i].daemonport == 0) 181 | { 182 | p_map = &cltopt.maps[i]; 183 | p_map->daemonport = daemonport; 184 | break; 185 | } 186 | } 187 | 188 | return p_map; 189 | } 190 | 191 | extern P_PORTTRANS sc_find_trans(unsigned short l_sock) 192 | { 193 | P_PORTTRANS p_trans = NULL; 194 | 195 | if (slist_empty(&cltopt.trans)) 196 | return NULL; 197 | 198 | slist_for_each_entry(p_trans, &cltopt.trans, list) 199 | { 200 | if (p_trans->l_port == l_sock) 201 | { 202 | return p_trans; 203 | } 204 | } 205 | 206 | return NULL; 207 | } 208 | 209 | extern P_PORTTRANS sc_create_trans(unsigned short l_sock) 210 | { 211 | P_PORTTRANS p_trans = NULL; 212 | 213 | if (sc_find_trans(l_sock)) 214 | { 215 | st_d_error("TRANS已经存在:%d", l_sock); 216 | return NULL; 217 | } 218 | 219 | p_trans = (P_PORTTRANS)calloc(sizeof(PORTTRANS), 1); 220 | if (!p_trans) 221 | { 222 | st_d_error("TRANS申请内存失败!"); 223 | return NULL; 224 | } 225 | 226 | p_trans->l_port = l_sock; 227 | p_trans->local_bev = NULL; 228 | p_trans->srv_bev = NULL; 229 | 230 | pthread_mutex_lock(&cltopt.trans_lock); 231 | slist_add(&p_trans->list, &cltopt.trans); 232 | pthread_mutex_unlock(&cltopt.trans_lock); 233 | 234 | return p_trans; 235 | } 236 | 237 | 238 | extern RET_T sc_free_trans(P_PORTTRANS p_trans) 239 | { 240 | if (!p_trans || !p_trans->l_port) 241 | { 242 | st_d_error("Free参数失败!"); 243 | return RET_NO; 244 | } 245 | 246 | pthread_mutex_lock(&cltopt.trans_lock); 247 | slist_remove(&p_trans->list, &cltopt.trans); 248 | st_d_print("DDDDD: 当前活动连接数:[[[ %d ]]], 释放:[%d]", 249 | slist_count(&cltopt.trans), p_trans->l_port); 250 | p_trans->l_port = 0; 251 | pthread_mutex_unlock(&cltopt.trans_lock); 252 | 253 | if (p_trans->srv_bev) 254 | { 255 | bufferevent_free(p_trans->srv_bev); 256 | p_trans->srv_bev = NULL; 257 | } 258 | if (p_trans->local_bev) 259 | { 260 | bufferevent_free(p_trans->local_bev); 261 | p_trans->local_bev = NULL; 262 | } 263 | 264 | if (p_trans->is_enc) 265 | { 266 | encrypt_ctx_free(&p_trans->ctx_enc); 267 | encrypt_ctx_free(&p_trans->ctx_enc); 268 | } 269 | 270 | free(p_trans); 271 | 272 | return RET_YES; 273 | } 274 | 275 | extern RET_T sc_free_all_trans(void) 276 | { 277 | P_PORTTRANS p_trans = NULL; 278 | P_SLIST_HEAD pos = NULL, n = NULL; 279 | 280 | pthread_mutex_lock(&cltopt.trans_lock); 281 | 282 | if (slist_empty(&cltopt.trans)) 283 | { 284 | 285 | pthread_mutex_unlock(&cltopt.trans_lock); 286 | return RET_YES; 287 | } 288 | 289 | slist_for_each_safe(pos, n, &cltopt.trans) 290 | { 291 | p_trans = list_entry(pos, PORTTRANS, list); 292 | st_d_print("释放:%d", p_trans->l_port); 293 | 294 | if (p_trans->srv_bev) 295 | bufferevent_free(p_trans->srv_bev); 296 | if (p_trans->local_bev) 297 | bufferevent_free(p_trans->local_bev); 298 | 299 | if (p_trans->is_enc) 300 | { 301 | encrypt_ctx_free(&p_trans->ctx_enc); 302 | encrypt_ctx_free(&p_trans->ctx_enc); 303 | } 304 | 305 | slist_remove(&p_trans->list, &cltopt.trans); 306 | free(p_trans); 307 | } 308 | pthread_mutex_unlock(&cltopt.trans_lock); 309 | 310 | return RET_YES; 311 | } 312 | 313 | RET_T sc_daemon_init_srv(int srv_fd) 314 | { 315 | char buff[4096]; 316 | P_CTL_HEAD p_head = NULL; 317 | RSA* p_rsa = NULL; 318 | 319 | /*加载SSL公钥*/ 320 | FILE* fp = fopen(PUBLIC_KEY_FILE, "r"); 321 | if (!fp) 322 | { 323 | st_d_error("CLIENT读取公钥文件%s失败!", PUBLIC_KEY_FILE); 324 | exit(EXIT_FAILURE); 325 | } 326 | p_rsa = RSA_new(); 327 | 328 | if(PEM_read_RSA_PUBKEY(fp, &p_rsa, 0, 0) == NULL) 329 | { 330 | st_d_error("CLIENT USR加载公钥失败!"); 331 | fclose(fp); 332 | RSA_free(p_rsa); 333 | exit(EXIT_FAILURE); 334 | } 335 | fclose(fp); 336 | 337 | memset(buff, 0, sizeof(buff)); 338 | p_head = GET_CTL_HEAD(buff); 339 | 340 | p_head->direct = DAEMON_USR; 341 | p_head->cmd = HD_CMD_INIT; 342 | p_head->mach_uuid = cltopt.mach_uuid; 343 | 344 | /*发送DAEMON的配置信息*/ 345 | json_object* ajgResponse = json_object_new_object(); 346 | json_object_object_add (ajgResponse, "hostname", 347 | json_object_new_string(cltopt.hostname)); 348 | json_object_object_add (ajgResponse, "username", 349 | json_object_new_string(cltopt.username)); 350 | json_object_object_add (ajgResponse, "userid", 351 | json_object_new_int64(cltopt.userid)); 352 | 353 | const char* ret_str = json_object_to_json_string (ajgResponse); 354 | 355 | if (strlen(ret_str) + 1 > (RSA_size(p_rsa) - 11 ) ) 356 | { 357 | st_d_error("消息体太长:%d", strlen(ret_str)+1 ); 358 | json_object_put(ajgResponse); 359 | RSA_free(p_rsa); 360 | return RET_NO; 361 | } 362 | 363 | int len = RSA_public_encrypt(strlen(ret_str)+1, ret_str, GET_CTL_BODY(buff), 364 | p_rsa, RSA_PKCS1_PADDING); 365 | 366 | if (len < 0 ) 367 | { 368 | st_d_error("公钥加密失败:%d", len); 369 | ERR_print_errors_fp(stderr); 370 | json_object_put(ajgResponse); 371 | RSA_free(p_rsa); 372 | return RET_NO; 373 | } 374 | 375 | RSA_free(p_rsa); 376 | 377 | p_head->dat_len = len; 378 | p_head->crc = crc32(0L, GET_CTL_BODY(buff), len); 379 | 380 | write(srv_fd, buff, CTL_HEAD_LEN + p_head->dat_len); 381 | 382 | json_object_put(ajgResponse); 383 | 384 | CTL_HEAD ret_head; 385 | read(srv_fd, &ret_head, CTL_HEAD_LEN); 386 | if (ret_head.direct == USR_DAEMON && ret_head.cmd == HD_CMD_OK) 387 | { 388 | return RET_YES; 389 | } 390 | else 391 | { 392 | return RET_NO; 393 | } 394 | 395 | } 396 | 397 | RET_T sc_usr_init_srv(int srv_fd) 398 | { 399 | char buff[4096]; 400 | P_CTL_HEAD p_head = NULL; 401 | RSA* p_rsa = NULL; 402 | 403 | /*加载SSL公钥*/ 404 | FILE* fp = fopen(PUBLIC_KEY_FILE, "r"); 405 | if (!fp) 406 | { 407 | st_d_error("CLIENT读取公钥文件%s失败!", PUBLIC_KEY_FILE); 408 | exit(EXIT_FAILURE); 409 | } 410 | p_rsa = RSA_new(); 411 | 412 | if(PEM_read_RSA_PUBKEY(fp, &p_rsa, 0, 0) == NULL) 413 | { 414 | st_d_error("CLIENT USR加载公钥失败!"); 415 | fclose(fp); 416 | RSA_free(p_rsa); 417 | return RET_NO; 418 | } 419 | 420 | fclose(fp); 421 | 422 | memset(buff, 0, sizeof(buff)); 423 | p_head = GET_CTL_HEAD(buff); 424 | 425 | p_head->direct = USR_DAEMON; 426 | p_head->cmd = HD_CMD_INIT; 427 | p_head->mach_uuid = cltopt.mach_uuid; 428 | 429 | 430 | /*发送DAEMON的配置信息*/ 431 | json_object* ajgResponse = json_object_new_object(); 432 | json_object_object_add (ajgResponse, "hostname", 433 | json_object_new_string(cltopt.hostname)); 434 | json_object_object_add (ajgResponse, "username", 435 | json_object_new_string(cltopt.username)); 436 | json_object_object_add (ajgResponse, "userid", 437 | json_object_new_int64(cltopt.userid)); 438 | json_object_object_add (ajgResponse, "r_mach_uuid", 439 | json_object_new_string(SD_ID128_CONST_STR(cltopt.session_uuid))); 440 | 441 | 442 | const char* ret_str = json_object_to_json_string (ajgResponse); 443 | 444 | if (strlen(ret_str) + 1 > (RSA_size(p_rsa) - 11 ) ) 445 | { 446 | st_d_error("消息体太长:%d", strlen(ret_str)+1 ); 447 | ERR_print_errors_fp(stderr); 448 | json_object_put(ajgResponse); 449 | RSA_free(p_rsa); 450 | return RET_NO; 451 | } 452 | 453 | int len = RSA_public_encrypt(strlen(ret_str)+1, ret_str, GET_CTL_BODY(buff), 454 | p_rsa, RSA_PKCS1_PADDING); 455 | 456 | RSA_free(p_rsa); 457 | 458 | if (len < 0 ) 459 | { 460 | st_d_error("公钥加密失败:%d", len); 461 | json_object_put(ajgResponse); 462 | return RET_NO; 463 | } 464 | 465 | p_head->dat_len = len; 466 | p_head->crc = crc32(0L, GET_CTL_BODY(buff), len); 467 | 468 | write(srv_fd, buff, CTL_HEAD_LEN + p_head->dat_len); 469 | 470 | json_object_put(ajgResponse); 471 | 472 | CTL_HEAD ret_head; 473 | read(srv_fd, &ret_head, CTL_HEAD_LEN); 474 | if (ret_head.direct == DAEMON_USR && ret_head.cmd == HD_CMD_OK) 475 | { 476 | return RET_YES; 477 | } 478 | else 479 | { 480 | return RET_NO; 481 | } 482 | 483 | } 484 | 485 | RET_T sc_daemon_ss5_init_srv(int srv_fd, const char* request, unsigned short l_port) 486 | { 487 | char buff[4096]; 488 | P_CTL_HEAD p_head = NULL; 489 | RSA* p_rsa = NULL; 490 | 491 | /*加载SSL公钥*/ 492 | FILE* fp = fopen(PUBLIC_KEY_FILE, "r"); 493 | if (!fp) 494 | { 495 | st_d_error("CLIENT读取公钥文件%s失败!", PUBLIC_KEY_FILE); 496 | exit(EXIT_FAILURE); 497 | } 498 | p_rsa = RSA_new(); 499 | 500 | if(PEM_read_RSA_PUBKEY(fp, &p_rsa, 0, 0) == NULL) 501 | { 502 | st_d_error("CLIENT USR加载公钥失败!"); 503 | fclose(fp); 504 | RSA_free(p_rsa); 505 | exit(EXIT_FAILURE); 506 | } 507 | fclose(fp); 508 | 509 | memset(buff, 0, sizeof(buff)); 510 | p_head = GET_CTL_HEAD(buff); 511 | 512 | p_head->direct = DAEMON_USR; 513 | p_head->cmd = HD_CMD_SS5; 514 | p_head->extra_param = l_port; 515 | p_head->mach_uuid = cltopt.mach_uuid; 516 | 517 | int dat_len = 0; 518 | if (request[3] == 0x01) 519 | { 520 | dat_len = 4 + 4 + 2; 521 | } 522 | else 523 | { 524 | dat_len = 4 + 1 + request[4] + 2; 525 | } 526 | 527 | if (dat_len + 1 > (RSA_size(p_rsa) - 11 ) ) 528 | { 529 | st_d_error("消息体太长!" ); 530 | RSA_free(p_rsa); 531 | return RET_NO; 532 | } 533 | 534 | int len = RSA_public_encrypt(dat_len, request, GET_CTL_BODY(buff), 535 | p_rsa, RSA_PKCS1_PADDING); 536 | 537 | if (len < 0 ) 538 | { 539 | st_d_error("公钥加密失败:%d", len); 540 | ERR_print_errors_fp(stderr); 541 | RSA_free(p_rsa); 542 | return RET_NO; 543 | } 544 | 545 | RSA_free(p_rsa); 546 | 547 | p_head->dat_len = len; 548 | p_head->crc = crc32(0L, GET_CTL_BODY(buff), len); 549 | 550 | write(srv_fd, buff, CTL_HEAD_LEN + p_head->dat_len); 551 | 552 | return RET_YES; 553 | } 554 | 555 | RET_T sc_daemon_dns_init_srv(int srv_fd, unsigned short l_port, 556 | unsigned long salt) 557 | { 558 | char buff[4096]; 559 | P_CTL_HEAD p_head = NULL; 560 | RSA* p_rsa = NULL; 561 | 562 | /*加载SSL公钥*/ 563 | FILE* fp = fopen(PUBLIC_KEY_FILE, "r"); 564 | if (!fp) 565 | { 566 | st_d_error("CLIENT读取公钥文件%s失败!", PUBLIC_KEY_FILE); 567 | exit(EXIT_FAILURE); 568 | } 569 | p_rsa = RSA_new(); 570 | 571 | if(PEM_read_RSA_PUBKEY(fp, &p_rsa, 0, 0) == NULL) 572 | { 573 | st_d_error("CLIENT USR加载公钥失败!"); 574 | fclose(fp); 575 | RSA_free(p_rsa); 576 | exit(EXIT_FAILURE); 577 | } 578 | fclose(fp); 579 | 580 | memset(buff, 0, sizeof(buff)); 581 | p_head = GET_CTL_HEAD(buff); 582 | 583 | p_head->direct = DAEMON_USR; 584 | p_head->cmd = HD_CMD_DNS; 585 | p_head->extra_param = l_port; 586 | p_head->mach_uuid = cltopt.mach_uuid; 587 | 588 | char salt_buf[128]; 589 | sprintf(salt_buf,"--%luxxx", salt); 590 | 591 | int len = RSA_public_encrypt(strlen(salt_buf)+1, salt_buf, GET_CTL_BODY(buff), 592 | p_rsa, RSA_PKCS1_PADDING); 593 | 594 | if (len < 0 ) 595 | { 596 | st_d_error("公钥加密失败:%d", len); 597 | ERR_print_errors_fp(stderr); 598 | RSA_free(p_rsa); 599 | return RET_NO; 600 | } 601 | 602 | RSA_free(p_rsa); 603 | 604 | p_head->dat_len = len; 605 | p_head->crc = crc32(0L, GET_CTL_BODY(buff), len); 606 | 607 | write(srv_fd, buff, CTL_HEAD_LEN + p_head->dat_len); 608 | 609 | return RET_YES; 610 | } 611 | 612 | 613 | /** 614 | * 没有消息负载的发送 615 | */ 616 | RET_T sc_send_head_cmd(int cmd, unsigned long extra_param, 617 | unsigned short usrport, unsigned daemonport) 618 | { 619 | CTL_HEAD head; 620 | memset(&head, 0, CTL_HEAD_LEN); 621 | 622 | if (cltopt.srv_bev == NULL) 623 | { 624 | st_d_error("cltopt.srv_bev == NULL"); 625 | return RET_NO; 626 | } 627 | 628 | head.direct = (cltopt.C_TYPE == C_USR ? USR_DAEMON : DAEMON_USR); 629 | head.cmd = cmd; 630 | head.extra_param = extra_param; 631 | head.mach_uuid = cltopt.session_uuid; 632 | head.usrport = usrport; 633 | head.daemonport = daemonport; 634 | 635 | bufferevent_write(cltopt.srv_bev, &head, CTL_HEAD_LEN); 636 | 637 | return RET_YES; 638 | } 639 | 640 | 641 | RET_T sc_connect_srv(int srv_fd) 642 | { 643 | int reuseaddr_on = 1; 644 | 645 | unsigned int optval = 1; 646 | setsockopt(srv_fd, IPPROTO_TCP, TCP_NODELAY, &optval, sizeof(optval));//禁用NAGLE算法 647 | 648 | if (setsockopt(srv_fd, SOL_SOCKET, SO_REUSEADDR, &reuseaddr_on, 649 | sizeof(reuseaddr_on)) == -1) 650 | { 651 | st_d_print("Reuse socket opt faile!\n"); 652 | return RET_NO; 653 | } 654 | if (connect(srv_fd, (struct sockaddr *)&cltopt.srv, sizeof(cltopt.srv))) 655 | { 656 | st_d_error("Connect to server failed!\n"); 657 | return RET_NO; 658 | } 659 | 660 | return RET_YES; 661 | } 662 | 663 | void sc_set_eventcb_srv(int srv_fd, struct event_base *base) 664 | { 665 | struct bufferevent *srv_bev = NULL; 666 | 667 | evutil_make_socket_nonblocking(srv_fd); 668 | srv_bev = bufferevent_socket_new(base, srv_fd, BEV_OPT_CLOSE_ON_FREE); 669 | bufferevent_setcb(srv_bev, srv_bufferread_cb, NULL, srv_bufferevent_cb, NULL); 670 | cltopt.srv_bev = srv_bev; 671 | bufferevent_enable(srv_bev, EV_READ|EV_WRITE); 672 | 673 | return; 674 | } 675 | 676 | -------------------------------------------------------------------------------- /client/ssl/public.key: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyC/9iLFjrSc6Tvui2OyL 3 | 5PLpTuPB+UVfmQKS4Jgv/ICwN/YT086oTbXkR6wEBqFuuB8kN6Z73o8QMaaNZHNZ 4 | mOEfuz4Rjkd991OvJcHAGt8cnrk1UVuSonh/puRGkjZRtkc23v0b5TthjAXNDgSG 5 | rHtTR+j0E4c6lg0mOTnG0oYmGgObdb1t3ZqDO+N4VaQ1CIPtH1V0JLXbveEkKYJx 6 | Z87yTAnBITikGyhLPUP6D8OMKSMufsHwf1itpYGmS8o4n+OF0CfGMFSs1Av1JJZ1 7 | THrTLSE0/qYIlXc7kyFrOCPRK+F2bphbFUZu/VXoQYMbwwdy4kUw5OPCPJCnwCJS 8 | 0wIDAQAB 9 | -----END PUBLIC KEY----- 10 | -------------------------------------------------------------------------------- /common/sshinner_crypt.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "sshinner_crypt.h" 5 | #include "st_others.h" 6 | 7 | 8 | RET_T encrypt_init(const char* passwd, char store_key[]) 9 | { 10 | 11 | /** EVP_BytesToKey() derives a key and IV from various parameters. 12 | * 用来产生最初始的key&iv 13 | * iv后面是要不断切换的 14 | */ 15 | 16 | unsigned char iv[RC4_MD5_IV_LEN]; 17 | 18 | EVP_CIPHER * cipher = (EVP_CIPHER *)EVP_get_cipherbyname("rc4"); 19 | const EVP_MD *md = EVP_get_digestbyname("MD5"); 20 | 21 | if (! EVP_BytesToKey(cipher, md, NULL, passwd, strlen(passwd), 10, store_key, iv)) 22 | { 23 | st_d_error("Generate key & iv failed!"); 24 | return RET_NO; 25 | } 26 | 27 | st_d_print("初始化OK: %s", passwd); 28 | 29 | return RET_YES; 30 | } 31 | 32 | 33 | RET_T encrypt_ctx_init(P_ENCRYPT_CTX p_ctx, unsigned long salt, const char* enc_key, int enc) 34 | { 35 | EVP_CIPHER_CTX_init(&p_ctx->ctx); 36 | 37 | if (!EVP_CipherInit_ex(&p_ctx->ctx, EVP_rc4(), NULL, NULL, NULL, enc)) 38 | { 39 | st_d_error("Cannot initialize cipher"); 40 | return RET_NO; 41 | } 42 | 43 | if (!EVP_CIPHER_CTX_set_key_length(&p_ctx->ctx, RC4_MD5_KEY_LEN)) 44 | { 45 | EVP_CIPHER_CTX_cleanup(&p_ctx->ctx); 46 | st_d_error("Invalid key length: %d", RC4_MD5_KEY_LEN); 47 | return RET_NO; 48 | } 49 | 50 | //OPENSSL_assert(EVP_CIPHER_CTX_key_length(&p_ctx->ctx) == 16); 51 | //OPENSSL_assert(EVP_CIPHER_CTX_iv_length(&p_ctx->ctx) == 16); 52 | 53 | memcpy(p_ctx->enc_key, enc_key, RC4_MD5_KEY_LEN); 54 | 55 | char buf[128]; 56 | char md5_buf[128]; 57 | sprintf(buf, "-XX%dXX-", salt); 58 | MD5(buf, strlen(buf), md5_buf); 59 | 60 | memcpy(p_ctx->iv, md5_buf, RC4_MD5_IV_LEN); 61 | 62 | p_ctx->is_init = 0; 63 | 64 | return RET_YES; 65 | } 66 | 67 | int encrypt_ctx_free(P_ENCRYPT_CTX p_ctx) 68 | { 69 | if (p_ctx) 70 | EVP_CIPHER_CTX_cleanup(&p_ctx->ctx); 71 | 72 | p_ctx->is_init = 0; 73 | 74 | return 0; 75 | } 76 | 77 | RET_T encrypt(P_ENCRYPT_CTX p_ctx, 78 | const P_ENC_FRAME p_plain, P_ENC_FRAME p_store) 79 | { 80 | memset(p_store, 0, FRAME_SIZE); 81 | 82 | if (!p_ctx->is_init) 83 | { 84 | unsigned char key_iv[32]; 85 | memcpy(key_iv, p_ctx->enc_key, 16); 86 | memcpy(key_iv + 16, p_ctx->iv, 16); 87 | const unsigned char *true_key = 88 | MD5(key_iv, 32, NULL); 89 | 90 | if (!EVP_CipherInit_ex(&p_ctx->ctx, NULL, NULL, true_key, p_ctx->iv, 1)) 91 | { 92 | st_d_error("Cannot set key and IV\n"); 93 | return RET_NO; 94 | } 95 | 96 | p_ctx->is_init = 1; 97 | } 98 | 99 | if (! EVP_CipherUpdate(&p_ctx->ctx, p_store->dat, &p_store->len, 100 | p_plain->dat, p_plain->len) ) 101 | { 102 | st_d_error("Encrypt error!"); 103 | return RET_NO; 104 | } 105 | 106 | return RET_YES; 107 | } 108 | 109 | 110 | RET_T decrypt(P_ENCRYPT_CTX p_ctx, 111 | const P_ENC_FRAME p_cipher, P_ENC_FRAME p_store) 112 | { 113 | memset(p_store, 0, FRAME_SIZE); 114 | 115 | if (!p_ctx->is_init) 116 | { 117 | unsigned char key_iv[32]; 118 | memcpy(key_iv, p_ctx->enc_key, 16); 119 | memcpy(key_iv + 16, p_ctx->iv, 16); 120 | const unsigned char *true_key = 121 | MD5(key_iv, 32, NULL); 122 | 123 | if (!EVP_CipherInit_ex(&p_ctx->ctx, NULL, NULL, true_key, p_ctx->iv, 0)) 124 | { 125 | st_d_error("Cannot set key and IV\n"); 126 | return RET_NO; 127 | } 128 | 129 | p_ctx->is_init = 1; 130 | } 131 | 132 | 133 | if(! EVP_CipherUpdate(&p_ctx->ctx, p_store->dat, &p_store->len, 134 | p_cipher->dat, p_cipher->len)) 135 | { 136 | st_d_error("Decrypt error!"); 137 | return RET_NO; 138 | } 139 | 140 | return RET_YES; 141 | } 142 | 143 | #if 0 144 | int enc_test(void) 145 | { 146 | ENCRYPT_CTX enc; 147 | ENCRYPT_CTX dec; 148 | 149 | encrypt_init(); 150 | 151 | encrypt_ctx_init(&enc, 1); 152 | encrypt_ctx_init(&dec, 0); 153 | 154 | char* msg = "桃子啊 aaaaaasdfaedddd!"; 155 | 156 | ENC_FRAME org; 157 | ENC_FRAME enced; 158 | ENC_FRAME deced; 159 | 160 | memset(&org, 0, FRAME_SIZE); 161 | strncpy(org.dat, msg, strlen(msg+1)); 162 | org.len = strlen(msg)+1; 163 | encrypt(&enc, &org, &enced); 164 | 165 | decrypt(&dec, &enced, &deced); 166 | 167 | printf((char *)deced.dat); 168 | 169 | printf("\n"); 170 | 171 | } 172 | 173 | #endif 174 | -------------------------------------------------------------------------------- /include/rbtree.h: -------------------------------------------------------------------------------- 1 | /* 2 | Red Black Trees 3 | (C) 1999 Andrea Arcangeli 4 | 5 | This program is free software; you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation; either version 2 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program; if not, write to the Free Software 17 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | 19 | linux/include/linux/rbtree.h 20 | 21 | To use rbtrees you'll have to implement your own insert and search cores. 22 | This will avoid us to use callbacks and to drop drammatically performances. 23 | I know it's not the cleaner way, but in C (not in C++) to get 24 | performances and genericity... 25 | 26 | See Documentation/rbtree.txt for documentation and samples. 27 | */ 28 | 29 | #ifndef __TOOLS_LINUX_PERF_RBTREE_H 30 | #define __TOOLS_LINUX_PERF_RBTREE_H 31 | 32 | #include 33 | #include 34 | 35 | #ifndef NULL 36 | #define NULL ((void *)0) 37 | #endif 38 | 39 | struct rb_node { 40 | unsigned long __rb_parent_color; 41 | struct rb_node *rb_right; 42 | struct rb_node *rb_left; 43 | } __attribute__((aligned(sizeof(long)))); 44 | /* The alignment might seem pointless, but allegedly CRIS needs it */ 45 | 46 | struct rb_root { 47 | struct rb_node *rb_node; 48 | }; 49 | 50 | 51 | #define rb_parent(r) ((struct rb_node *)((r)->__rb_parent_color & ~3)) 52 | 53 | #define RB_ROOT (struct rb_root) { NULL, } 54 | #define rb_entry(ptr, type, member) container_of(ptr, type, member) 55 | 56 | #define RB_EMPTY_ROOT(root) ((root)->rb_node == NULL) 57 | 58 | /* 'empty' nodes are nodes that are known not to be inserted in an rbtree */ 59 | #define RB_EMPTY_NODE(node) \ 60 | ((node)->__rb_parent_color == (unsigned long)(node)) 61 | #define RB_CLEAR_NODE(node) \ 62 | ((node)->__rb_parent_color = (unsigned long)(node)) 63 | 64 | 65 | extern void rb_insert_color(struct rb_node *, struct rb_root *); 66 | extern void rb_erase(struct rb_node *, struct rb_root *); 67 | 68 | 69 | /* Find logical next and previous nodes in a tree */ 70 | extern struct rb_node *rb_next(const struct rb_node *); 71 | extern struct rb_node *rb_prev(const struct rb_node *); 72 | extern struct rb_node *rb_first(const struct rb_root *); 73 | extern struct rb_node *rb_last(const struct rb_root *); 74 | 75 | /* Postorder iteration - always visit the parent after its children */ 76 | extern struct rb_node *rb_first_postorder(const struct rb_root *); 77 | extern struct rb_node *rb_next_postorder(const struct rb_node *); 78 | 79 | /* Fast replacement of a single node without remove/rebalance/add/rebalance */ 80 | extern void rb_replace_node(struct rb_node *victim, struct rb_node *new, 81 | struct rb_root *root); 82 | 83 | static inline void rb_link_node(struct rb_node *node, struct rb_node *parent, 84 | struct rb_node **rb_link) 85 | { 86 | node->__rb_parent_color = (unsigned long)parent; 87 | node->rb_left = node->rb_right = NULL; 88 | 89 | *rb_link = node; 90 | } 91 | 92 | #define rb_entry_safe(ptr, type, member) \ 93 | ({ typeof(ptr) ____ptr = (ptr); \ 94 | ____ptr ? rb_entry(____ptr, type, member) : NULL; \ 95 | }) 96 | 97 | 98 | /* 99 | * Handy for checking that we are not deleting an entry that is 100 | * already in a list, found in block/{blk-throttle,cfq-iosched}.c, 101 | * probably should be moved to lib/rbtree.c... 102 | */ 103 | static inline void rb_erase_init(struct rb_node *n, struct rb_root *root) 104 | { 105 | rb_erase(n, root); 106 | RB_CLEAR_NODE(n); 107 | } 108 | #endif /* __TOOLS_LINUX_PERF_RBTREE_H */ 109 | -------------------------------------------------------------------------------- /include/rbtree_augmented.h: -------------------------------------------------------------------------------- 1 | /* 2 | Red Black Trees 3 | (C) 1999 Andrea Arcangeli 4 | (C) 2002 David Woodhouse 5 | (C) 2012 Michel Lespinasse 6 | 7 | This program is free software; you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation; either version 2 of the License, or 10 | (at your option) any later version. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program; if not, write to the Free Software 19 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 | 21 | tools/linux/include/linux/rbtree_augmented.h 22 | 23 | Copied from: 24 | linux/include/linux/rbtree_augmented.h 25 | */ 26 | 27 | #ifndef _TOOLS_LINUX_RBTREE_AUGMENTED_H 28 | #define _TOOLS_LINUX_RBTREE_AUGMENTED_H 29 | 30 | #include "rbtree.h" 31 | 32 | /* 33 | * Please note - only struct rb_augment_callbacks and the prototypes for 34 | * rb_insert_augmented() and rb_erase_augmented() are intended to be public. 35 | * The rest are implementation details you are not expected to depend on. 36 | * 37 | * See Documentation/rbtree.txt for documentation and samples. 38 | */ 39 | 40 | struct rb_augment_callbacks { 41 | void (*propagate)(struct rb_node *node, struct rb_node *stop); 42 | void (*copy)(struct rb_node *old, struct rb_node *new); 43 | void (*rotate)(struct rb_node *old, struct rb_node *new); 44 | }; 45 | 46 | extern void __rb_insert_augmented(struct rb_node *node, struct rb_root *root, 47 | void (*augment_rotate)(struct rb_node *old, struct rb_node *new)); 48 | /* 49 | * Fixup the rbtree and update the augmented information when rebalancing. 50 | * 51 | * On insertion, the user must update the augmented information on the path 52 | * leading to the inserted node, then call rb_link_node() as usual and 53 | * rb_augment_inserted() instead of the usual rb_insert_color() call. 54 | * If rb_augment_inserted() rebalances the rbtree, it will callback into 55 | * a user provided function to update the augmented information on the 56 | * affected subtrees. 57 | */ 58 | static inline void 59 | rb_insert_augmented(struct rb_node *node, struct rb_root *root, 60 | const struct rb_augment_callbacks *augment) 61 | { 62 | __rb_insert_augmented(node, root, augment->rotate); 63 | } 64 | 65 | #define RB_DECLARE_CALLBACKS(rbstatic, rbname, rbstruct, rbfield, \ 66 | rbtype, rbaugmented, rbcompute) \ 67 | static inline void \ 68 | rbname ## _propagate(struct rb_node *rb, struct rb_node *stop) \ 69 | { \ 70 | while (rb != stop) { \ 71 | rbstruct *node = rb_entry(rb, rbstruct, rbfield); \ 72 | rbtype augmented = rbcompute(node); \ 73 | if (node->rbaugmented == augmented) \ 74 | break; \ 75 | node->rbaugmented = augmented; \ 76 | rb = rb_parent(&node->rbfield); \ 77 | } \ 78 | } \ 79 | static inline void \ 80 | rbname ## _copy(struct rb_node *rb_old, struct rb_node *rb_new) \ 81 | { \ 82 | rbstruct *old = rb_entry(rb_old, rbstruct, rbfield); \ 83 | rbstruct *new = rb_entry(rb_new, rbstruct, rbfield); \ 84 | new->rbaugmented = old->rbaugmented; \ 85 | } \ 86 | static void \ 87 | rbname ## _rotate(struct rb_node *rb_old, struct rb_node *rb_new) \ 88 | { \ 89 | rbstruct *old = rb_entry(rb_old, rbstruct, rbfield); \ 90 | rbstruct *new = rb_entry(rb_new, rbstruct, rbfield); \ 91 | new->rbaugmented = old->rbaugmented; \ 92 | old->rbaugmented = rbcompute(old); \ 93 | } \ 94 | rbstatic const struct rb_augment_callbacks rbname = { \ 95 | rbname ## _propagate, rbname ## _copy, rbname ## _rotate \ 96 | }; 97 | 98 | 99 | #define RB_RED 0 100 | #define RB_BLACK 1 101 | 102 | #define __rb_parent(pc) ((struct rb_node *)(pc & ~3)) 103 | 104 | #define __rb_color(pc) ((pc) & 1) 105 | #define __rb_is_black(pc) __rb_color(pc) 106 | #define __rb_is_red(pc) (!__rb_color(pc)) 107 | #define rb_color(rb) __rb_color((rb)->__rb_parent_color) 108 | #define rb_is_red(rb) __rb_is_red((rb)->__rb_parent_color) 109 | #define rb_is_black(rb) __rb_is_black((rb)->__rb_parent_color) 110 | 111 | static inline void rb_set_parent(struct rb_node *rb, struct rb_node *p) 112 | { 113 | rb->__rb_parent_color = rb_color(rb) | (unsigned long)p; 114 | } 115 | 116 | static inline void rb_set_parent_color(struct rb_node *rb, 117 | struct rb_node *p, int color) 118 | { 119 | rb->__rb_parent_color = (unsigned long)p | color; 120 | } 121 | 122 | static inline void 123 | __rb_change_child(struct rb_node *old, struct rb_node *new, 124 | struct rb_node *parent, struct rb_root *root) 125 | { 126 | if (parent) { 127 | if (parent->rb_left == old) 128 | parent->rb_left = new; 129 | else 130 | parent->rb_right = new; 131 | } else 132 | root->rb_node = new; 133 | } 134 | 135 | extern void __rb_erase_color(struct rb_node *parent, struct rb_root *root, 136 | void (*augment_rotate)(struct rb_node *old, struct rb_node *new)); 137 | 138 | static inline struct rb_node * 139 | __rb_erase_augmented(struct rb_node *node, struct rb_root *root, 140 | const struct rb_augment_callbacks *augment) 141 | { 142 | struct rb_node *child = node->rb_right, *tmp = node->rb_left; 143 | struct rb_node *parent, *rebalance; 144 | unsigned long pc; 145 | 146 | if (!tmp) { 147 | /* 148 | * Case 1: node to erase has no more than 1 child (easy!) 149 | * 150 | * Note that if there is one child it must be red due to 5) 151 | * and node must be black due to 4). We adjust colors locally 152 | * so as to bypass __rb_erase_color() later on. 153 | */ 154 | pc = node->__rb_parent_color; 155 | parent = __rb_parent(pc); 156 | __rb_change_child(node, child, parent, root); 157 | if (child) { 158 | child->__rb_parent_color = pc; 159 | rebalance = NULL; 160 | } else 161 | rebalance = __rb_is_black(pc) ? parent : NULL; 162 | tmp = parent; 163 | } else if (!child) { 164 | /* Still case 1, but this time the child is node->rb_left */ 165 | tmp->__rb_parent_color = pc = node->__rb_parent_color; 166 | parent = __rb_parent(pc); 167 | __rb_change_child(node, tmp, parent, root); 168 | rebalance = NULL; 169 | tmp = parent; 170 | } else { 171 | struct rb_node *successor = child, *child2; 172 | tmp = child->rb_left; 173 | if (!tmp) { 174 | /* 175 | * Case 2: node's successor is its right child 176 | * 177 | * (n) (s) 178 | * / \ / \ 179 | * (x) (s) -> (x) (c) 180 | * \ 181 | * (c) 182 | */ 183 | parent = successor; 184 | child2 = successor->rb_right; 185 | augment->copy(node, successor); 186 | } else { 187 | /* 188 | * Case 3: node's successor is leftmost under 189 | * node's right child subtree 190 | * 191 | * (n) (s) 192 | * / \ / \ 193 | * (x) (y) -> (x) (y) 194 | * / / 195 | * (p) (p) 196 | * / / 197 | * (s) (c) 198 | * \ 199 | * (c) 200 | */ 201 | do { 202 | parent = successor; 203 | successor = tmp; 204 | tmp = tmp->rb_left; 205 | } while (tmp); 206 | parent->rb_left = child2 = successor->rb_right; 207 | successor->rb_right = child; 208 | rb_set_parent(child, successor); 209 | augment->copy(node, successor); 210 | augment->propagate(parent, successor); 211 | } 212 | 213 | successor->rb_left = tmp = node->rb_left; 214 | rb_set_parent(tmp, successor); 215 | 216 | pc = node->__rb_parent_color; 217 | tmp = __rb_parent(pc); 218 | __rb_change_child(node, successor, tmp, root); 219 | if (child2) { 220 | successor->__rb_parent_color = pc; 221 | rb_set_parent_color(child2, parent, RB_BLACK); 222 | rebalance = NULL; 223 | } else { 224 | unsigned long pc2 = successor->__rb_parent_color; 225 | successor->__rb_parent_color = pc; 226 | rebalance = __rb_is_black(pc2) ? parent : NULL; 227 | } 228 | tmp = successor; 229 | } 230 | 231 | augment->propagate(tmp, NULL); 232 | return rebalance; 233 | } 234 | 235 | static inline void 236 | rb_erase_augmented(struct rb_node *node, struct rb_root *root, 237 | const struct rb_augment_callbacks *augment) 238 | { 239 | struct rb_node *rebalance = __rb_erase_augmented(node, root, augment); 240 | if (rebalance) 241 | __rb_erase_color(rebalance, root, augment->rotate); 242 | } 243 | 244 | #endif /* _TOOLS_LINUX_RBTREE_AUGMENTED_H */ 245 | -------------------------------------------------------------------------------- /include/sshinner.h: -------------------------------------------------------------------------------- 1 | #ifndef _SSHINNER_H 2 | #define _SSHINNER_H 3 | 4 | #include 5 | 6 | #include 7 | #include // for TCP_NODELAY 8 | 9 | #define FRAME_SIZE 4096 10 | #define LOAD_SIZE (FRAME_SIZE-RC4_MD5_IV_LEN) 11 | 12 | /** 13 | * 规定客户端和服务器端通信的数据包格式: 14 | */ 15 | 16 | enum DIREC { USR_DAEMON=1, DAEMON_USR=2, 17 | }; 18 | 19 | #define HD_CMD_INIT 'I' /* 最初认证时候,包含数据体*/ 20 | #define HD_CMD_CONN 'C' /* 客户端USR请求连接 */ 21 | #define HD_CMD_CONN_ACT 'A' // 负载传输激活 22 | 23 | #define HD_CMD_SS5 'S' // ss5代理 24 | #define HD_CMD_SS5_ACT 'T' 25 | 26 | #define HD_CMD_DNS 'D' // DNS代理 27 | #define HD_CMD_DNS_ACT 'J' // DNS代理激活 28 | 29 | #define HD_CMD_END_TRANS 'X' //用以拆除TRANS连接 30 | 31 | #define HD_CMD_OK 'O' 32 | #define HD_CMD_ERROR 'E' 33 | 34 | /** 35 | * 简单数据类型,可以直接赋值或者拷贝 36 | */ 37 | typedef struct _ctl_head { 38 | enum DIREC direct; // 1: USR->DAEMON, 2: DAEMON->USR 39 | char cmd; // HD_CMD 40 | ulong extra_param; // 额外的参数 41 | sd_id128_t mach_uuid; 42 | unsigned short daemonport; 43 | unsigned short usrport; 44 | ulong crc; //数据负载,如果dat_len=0就为0 45 | unsigned int dat_len; //可选择项目,如果没有数据就为0 46 | } CTL_HEAD, *P_CTL_HEAD; 47 | static const int CTL_HEAD_LEN = sizeof(CTL_HEAD); 48 | #define GET_CTL_HEAD(buf) ((P_CTL_HEAD)buf) 49 | #define GET_CTL_BODY(buf) ((void*)((char*)buf)+CTL_HEAD_LEN) 50 | 51 | 52 | #include 53 | static const int MACH_UUID_LEN = sizeof(sd_id128_t); 54 | 55 | 56 | #endif /*_SSHINNER_H*/ 57 | -------------------------------------------------------------------------------- /include/sshinner_crypt.h: -------------------------------------------------------------------------------- 1 | #ifndef _SSHINNER_CRYPT_H 2 | #define _SSHINNER_CRYPT_H 3 | 4 | #include "st_others.h" 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #define RC4_MD5_KEY_LEN 16 12 | #define RC4_MD5_IV_LEN 16 13 | 14 | #define FRAME_SIZE 4096 15 | 16 | /*简单起见,不进行iv的传输,iv的计算根据每次连接信息计算出来*/ 17 | 18 | typedef struct _enc_frame { 19 | char dat[FRAME_SIZE]; 20 | int len; 21 | } ENC_FRAME, *P_ENC_FRAME; 22 | 23 | 24 | typedef struct _encrypt_ctx{ 25 | EVP_CIPHER_CTX ctx; 26 | int is_init; 27 | unsigned char enc_key[RC4_MD5_KEY_LEN]; 28 | unsigned char iv[RC4_MD5_KEY_LEN]; //random everytime RAND_bytes(output, len); 29 | } ENCRYPT_CTX, *P_ENCRYPT_CTX; 30 | 31 | RET_T encrypt_init(const char* passwd, char store_key[]); 32 | RET_T encrypt_ctx_init(P_ENCRYPT_CTX p_ctx, unsigned long salt, 33 | const char* enc_key, int enc); 34 | int encrypt_ctx_free(P_ENCRYPT_CTX p_ctx); 35 | 36 | RET_T encrypt(P_ENCRYPT_CTX p_ctx, 37 | const P_ENC_FRAME p_plain, P_ENC_FRAME p_store); 38 | RET_T decrypt(P_ENCRYPT_CTX p_ctx, 39 | const P_ENC_FRAME p_cipher, P_ENC_FRAME p_store); 40 | 41 | #endif 42 | -------------------------------------------------------------------------------- /include/st_others.h: -------------------------------------------------------------------------------- 1 | #ifndef __ST_OTHERS_H 2 | #define __ST_OTHERS_H 3 | 4 | #define DEBUG 5 | 6 | #ifdef __cplusplus 7 | extern "C" { 8 | #endif //__cplusplus 9 | 10 | #include 11 | #include 12 | #include 13 | 14 | #include 15 | 16 | typedef unsigned long ulong; 17 | typedef unsigned int uint; 18 | typedef unsigned char uchar; 19 | typedef unsigned short ushort; 20 | 21 | 22 | #ifndef NULL 23 | #define NULL ((void *)0) 24 | #endif 25 | 26 | /** 27 | * 统一一下函数的返回类型,不要自己都搞晕了 28 | * 29 | * 如果函数的返回值只是表示成功或者失败,就用下面的类型 30 | */ 31 | typedef enum RET_TYPE { 32 | RET_YES = 1, 33 | RET_NO = 0, 34 | } RET_T; 35 | 36 | #ifdef DEBUG 37 | 38 | #define st_d_print(...) \ 39 | do{ fprintf( stderr, "DEBUG:%s|%s<%d>:",__FILE__, __FUNCTION__,__LINE__); \ 40 | fprintf( stderr, __VA_ARGS__ ); \ 41 | fprintf( stderr, "\n"); fflush(stderr);\ 42 | }while(0) 43 | #else 44 | #define st_d_print(...) \ 45 | do {} while(0) 46 | #endif 47 | 48 | #define st_print(...) \ 49 | do{ fprintf( stderr , __VA_ARGS__ ); \ 50 | fflush(stderr);\ 51 | }while(0) 52 | 53 | #define st_d_error(...) \ 54 | do{ perror("ERROR:"); \ 55 | fprintf( stderr, "ERROR:%s|%s<%d>:",__FILE__, __FUNCTION__,__LINE__); \ 56 | fprintf( stderr, __VA_ARGS__ ); \ 57 | fprintf( stderr, "\n"); fflush(stderr);\ 58 | }while(0) 59 | 60 | typedef struct _st_small_obj { 61 | char data[4096]; 62 | size_t len; 63 | } ST_SMALL_OBJ, *P_ST_SMALL_OBJ; 64 | 65 | typedef struct _st_small_pobj { 66 | char* data; 67 | size_t len; 68 | } ST_SMALL_POBJ, *P_ST_SMALL_POBJ; 69 | 70 | #define WAIT_FOR_ENTER fprintf( stderr, "Press ENTER\n" );getchar() 71 | 72 | 73 | #define EXIT_IF_TRUE(x) if (x) \ 74 | do { \ 75 | fprintf(stderr, "!!!%s:%d ASSERT '%s' IS TRUE\n", \ 76 | __FILE__, __LINE__, #x); \ 77 | SYS_ABORT(#x); \ 78 | }while(0) 79 | 80 | #define RET_NULL_IF_TRUE(x) if (x) \ 81 | do { \ 82 | fprintf(stderr, "!!!%s:%d ASSERT '%s' IS TRUE\n", \ 83 | __FILE__, __LINE__, #x); \ 84 | return NULL; \ 85 | }while(0) 86 | 87 | #define GOTO_IF_TRUE(x, flag) if (x) \ 88 | do { \ 89 | fprintf(stderr, "!!!%s:%d ASSERT '%s' IS TRUE\n", \ 90 | __FILE__, __LINE__, #x); \ 91 | goto flag; \ 92 | }while(0) 93 | 94 | static inline void backtrace_info(int param) 95 | { 96 | int j, nptrs; 97 | #define BT_SIZE 100 98 | char **strings; 99 | void *buffer[BT_SIZE]; 100 | 101 | nptrs = backtrace(buffer, BT_SIZE); 102 | fprintf(stderr, "backtrace() returned %d addresses\n", nptrs); 103 | 104 | strings = backtrace_symbols(buffer, nptrs); 105 | if (strings == NULL) 106 | { 107 | perror("backtrace_symbols"); 108 | exit(EXIT_FAILURE); 109 | } 110 | 111 | for (j = 0; j < nptrs; j++) 112 | fprintf(stderr, "%s\n", strings[j]); 113 | 114 | free(strings); 115 | 116 | exit(EXIT_FAILURE); 117 | } 118 | 119 | #define SYS_ABORT(...) \ 120 | do{ fprintf( stderr,"!!!DIE:%s|%s<%d>\n",__FILE__, __FUNCTION__,__LINE__); \ 121 | fprintf( stderr , __VA_ARGS__ ); \ 122 | backtrace_info(0); abort(); \ 123 | }while(0) 124 | 125 | 126 | 127 | #ifdef __cplusplus 128 | } 129 | #endif //__cplusplus 130 | 131 | #endif //__ST_OTHERS_H 132 | -------------------------------------------------------------------------------- /include/st_slist.h: -------------------------------------------------------------------------------- 1 | #ifndef __ST_SLIST_H 2 | #define __ST_SLIST_H 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif //__cplusplus 7 | 8 | #include 9 | #include 10 | 11 | #include "st_others.h" 12 | 13 | //根据list_head简化得到的单向NULL结尾链表 14 | typedef struct _slist_head { 15 | struct _slist_head *next; 16 | } SLIST_HEAD, *P_SLIST_HEAD; 17 | 18 | static inline void slist_init(P_SLIST_HEAD head) 19 | { 20 | head->next = NULL; 21 | } 22 | 23 | // replaced of container_of 24 | #define container_of(ptr, type, member) \ 25 | ((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member))) 26 | 27 | #define list_entry(ptr, type, member) \ 28 | ((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member))) 29 | 30 | #define slist_for_each(pos, head) \ 31 | for (pos = (head)->next; pos != NULL; pos = pos->next) 32 | 33 | // 可以删除元素,安全链表 34 | #define slist_for_each_safe(pos, n, head) \ 35 | for (pos = (head)->next, n = pos->next; pos && ({ n = pos->next; 1; }); pos = n) 36 | 37 | #define slist_for_each_entry(pos, head, member)\ 38 | for (pos = list_entry((head)->next, typeof(*pos), member); \ 39 | &pos->member != NULL; \ 40 | pos = list_entry(pos->member.next, typeof(*pos), member)) 41 | 42 | 43 | #define byte_offset(base, offset) \ 44 | ((char *)(base) + (offset)) 45 | 46 | static inline void slist_add(P_SLIST_HEAD new_item, P_SLIST_HEAD head) 47 | { 48 | P_SLIST_HEAD ptr = head; 49 | while(ptr->next) 50 | ptr = ptr->next; 51 | ptr->next = new_item; 52 | new_item->next = NULL; 53 | 54 | //new_item->next = head->next; 55 | //head->next = new_item; 56 | } 57 | 58 | static inline int slist_empty(const P_SLIST_HEAD head) 59 | { 60 | return head->next == NULL; 61 | } 62 | 63 | static inline void slist_remove(P_SLIST_HEAD del_item, P_SLIST_HEAD head) 64 | { 65 | P_SLIST_HEAD pos = NULL; 66 | 67 | if (!head || !del_item || slist_empty(head)) 68 | return; 69 | 70 | if ( head->next == del_item) 71 | { 72 | head->next = head->next->next; 73 | return; 74 | } 75 | 76 | slist_for_each(pos, head) 77 | { 78 | if ( pos->next == del_item) 79 | { 80 | pos->next = pos->next->next; 81 | return; 82 | } 83 | } 84 | } 85 | 86 | static inline unsigned int slist_count (const P_SLIST_HEAD head) 87 | { 88 | int count = 0; 89 | P_SLIST_HEAD pos = NULL; 90 | 91 | if(!head) 92 | return -1; 93 | 94 | slist_for_each(pos, head) 95 | count ++; 96 | 97 | return count; 98 | } 99 | 100 | // 先进先出的队列 101 | static inline P_SLIST_HEAD slist_fetch(P_SLIST_HEAD head) 102 | { 103 | P_SLIST_HEAD ret = NULL; 104 | 105 | if (!head || slist_empty(head)) 106 | { 107 | //cout << "EMPTY_LIST" << endl; 108 | return NULL; 109 | } 110 | 111 | ret = head->next; 112 | head->next = head->next->next; //may also be null 113 | 114 | return ret; 115 | } 116 | 117 | // 返回链表最后一个LIST_HEAD 118 | static inline P_SLIST_HEAD slist_last(P_SLIST_HEAD head) 119 | { 120 | P_SLIST_HEAD ret = head; 121 | 122 | if (!head || slist_empty(head)) 123 | { 124 | return NULL; 125 | } 126 | 127 | while ( ret->next->next != NULL) 128 | ret = ret->next; 129 | 130 | return ret->next; 131 | } 132 | 133 | static inline int slist_u_test(void) 134 | { 135 | typedef struct _test_struct 136 | { 137 | SLIST_HEAD list; 138 | int data; 139 | } TEST_STRUCT, *P_TEST_STRUCT; 140 | 141 | int tmp = 0; 142 | 143 | SLIST_HEAD test_head = {0}; 144 | P_SLIST_HEAD p_test_head = &test_head; 145 | P_SLIST_HEAD pos = NULL; 146 | 147 | tmp = slist_empty(p_test_head); 148 | if(!tmp) 149 | { 150 | fprintf(stderr,"slist_empty test FAILED!\n"); 151 | return 0; 152 | } 153 | else 154 | fprintf(stderr,"slist_empty test PASS!\n"); 155 | 156 | tmp = slist_count(p_test_head); 157 | if(tmp != 0 ) 158 | { 159 | fprintf(stderr,"slist_count test FAILED!\n"); 160 | return 0; 161 | } 162 | 163 | int i = 1, data; 164 | for(i = 1; i <= 10; i++) 165 | { 166 | data = (11 - i) * 10; //data 167 | 168 | P_TEST_STRUCT p_node = (P_TEST_STRUCT)malloc(sizeof(TEST_STRUCT)); 169 | p_node->data = data; 170 | slist_add(&p_node->list, p_test_head); 171 | 172 | tmp = slist_count(p_test_head); 173 | if(tmp != i) 174 | { 175 | fprintf(stderr,"slist_count test FAIL!\n"); 176 | return 0; 177 | } 178 | } 179 | 180 | fprintf(stderr,"slist_count test PASS!\n"); 181 | 182 | i = 10; 183 | slist_for_each(pos, p_test_head) 184 | { 185 | P_TEST_STRUCT p_node = list_entry(pos, TEST_STRUCT, list); 186 | tmp = i-- * 10; 187 | if(tmp != p_node->data) 188 | { 189 | fprintf(stderr,"list_entry test FAIL!\n"); 190 | fprintf(stderr,"%d <-> %d \n", tmp, p_node->data); 191 | return 0; 192 | } 193 | } 194 | 195 | fprintf(stderr,"list_entry test PASS!\n"); 196 | 197 | P_TEST_STRUCT p_node = NULL; 198 | 199 | slist_for_each_entry(p_node, p_test_head, list) 200 | st_print("%d\n", p_node->data); 201 | 202 | //pos = slist_fetch(p_test_head); 203 | //pos = slist_fetch(p_test_head); 204 | pos = slist_fetch(p_test_head); 205 | p_node = list_entry(pos, TEST_STRUCT, list); 206 | if (p_node->data != 100) 207 | { 208 | fprintf(stderr,"list_fetch test FAIL!\n"); 209 | fprintf(stderr,"%d \n", p_node->data); 210 | return 0; 211 | } 212 | free(p_node); 213 | 214 | //测试,不关心内存泄漏 215 | pos = slist_fetch(p_test_head); //90 216 | pos = slist_fetch(p_test_head); //80 217 | pos = slist_fetch(p_test_head); //70 218 | pos = slist_fetch(p_test_head); //60 219 | p_node = list_entry(pos, TEST_STRUCT, list); 220 | if (p_node->data != 60) 221 | { 222 | fprintf(stderr,"list_fetch test FAIL!\n"); 223 | fprintf(stderr,"%d \n", p_node->data); 224 | return 0; 225 | } 226 | free(p_node); 227 | 228 | fprintf(stderr,"STAGE-PA\n"); 229 | slist_for_each_entry(p_node, p_test_head, list) 230 | st_print("%d\n", p_node->data); 231 | 232 | slist_for_each_entry(p_node, p_test_head, list) 233 | { 234 | if(p_node->data == 20 || p_node->data == 50) 235 | { 236 | slist_remove(&p_node->list, p_test_head); 237 | } 238 | } 239 | 240 | fprintf(stderr,"STAGE-PB\n"); 241 | slist_for_each_entry(p_node, p_test_head, list) 242 | st_print("%d\n", p_node->data); 243 | 244 | //pos = slist_fetch(p_test_head); //50 245 | pos = slist_fetch(p_test_head); //40 246 | pos = slist_fetch(p_test_head); //30 247 | //pos = slist_fetch(p_test_head); //20 248 | pos = slist_fetch(p_test_head); //10 249 | p_node = list_entry(pos, TEST_STRUCT, list); 250 | if (p_node->data != 10) 251 | { 252 | fprintf(stderr,"list_fetch test FAIL!\n"); 253 | fprintf(stderr,"%d \n", p_node->data); 254 | return 0; 255 | } 256 | free(p_node); 257 | 258 | slist_for_each_entry(p_node, p_test_head, list) 259 | st_print("%d\n", p_node->data); 260 | 261 | if (slist_fetch(p_test_head) != NULL) 262 | { 263 | fprintf(stderr,"list_fetch test FAIL!\n"); 264 | return 0; 265 | } 266 | fprintf(stderr,"list_fetch test PASS!\n"); 267 | 268 | fprintf(stderr,"slist unit test PASS!"); 269 | } 270 | 271 | 272 | 273 | #ifdef __cplusplus 274 | } 275 | #endif //__cplusplus 276 | 277 | #endif //ST_SLIST_H -------------------------------------------------------------------------------- /server/Makefile: -------------------------------------------------------------------------------- 1 | DEBUG ?= 1 2 | CC = gcc 3 | CCFLAGS = -g -O2 4 | CPPFLAGS = 5 | CXX = g++ 6 | CXXFLAGS = $(CCFLAGS) 7 | PACKAGE = sshinner_server 8 | PACKAGE_NAME = $(PACKAGE) 9 | PACKAGE_STRING = $(PACKAGE_NAME)1.0 10 | PACKAGE_VERSION = 1.0 11 | SHELL = /bin/sh 12 | VERSION = 1.0 13 | SUBDIRS = source 14 | COMMDIRS = ../common 15 | TESTDIR = test 16 | EXTRAFLAGS = -I./include -I../include -lpthread -lrt -lssl -lcrypto -levent -lsystemd -ljson-c -lz 17 | OBJDIR = obj 18 | 19 | vpath %.c $(SUBDIRS) 20 | vpath %.c $(COMMDIRS) 21 | vpath %.c $(TESTDIR) 22 | 23 | 24 | srcs = $(filter-out client.c, $(filter-out server.c, $(notdir $(wildcard $(SUBDIRS)/*.c)))) 25 | commons = $(filter-out main.c, $(notdir $(wildcard $(COMMDIRS)/*.c))) 26 | 27 | objs = $(srcs:%.c=$(OBJDIR)/%.o) 28 | common_objs = $(commons:%.c=$(OBJDIR)/%.o) 29 | 30 | test_srcs = $(notdir $(wildcard $(TESTDIR)/*.c)) 31 | test_objs = $(test_srcs:%.c=$(OBJDIR)/%.o) 32 | test_exec = $(test_srcs:%.c=%) 33 | 34 | ifeq ($(DEBUG),1) 35 | TARGET_DIR=Debug 36 | else 37 | TARGET_DIR=Release 38 | endif 39 | 40 | all : $(PACKAGE) 41 | .PHONY : all 42 | .PHONY : test 43 | 44 | $(PACKAGE) : $(objs) $(common_objs) 45 | $(CC) -c $(CCFLAGS) $(EXTRAFLAGS) $(SUBDIRS)/server.c -o $(OBJDIR)/server.o 46 | $(CC) $(CCFLAGS) $(objs) $(common_objs) $(OBJDIR)/server.o $(EXTRAFLAGS) -o $(TARGET_DIR)/$(PACKAGE) 47 | 48 | $(objs) : $(OBJDIR)/%.o: %.c 49 | @mkdir -p $(OBJDIR) 50 | $(CC) -MMD -c $(CCFLAGS) $(EXTRAFLAGS) $< -o $@ 51 | 52 | $(common_objs) : $(OBJDIR)/%.o: %.c 53 | $(CC) -MMD -c $(CCFLAGS) $(EXTRAFLAGS) $< -o $@ 54 | 55 | #check header for obj reconstruction 56 | -include $(OBJDIR)/*.d 57 | 58 | test : $(test_objs) 59 | $(foreach test_target, $(test_exec), $(CC) $(CCFLAGS) $(EXTRAFLAGS) $(objs) -o $(test_target) $(OBJDIR)/$(test_target).o ;) 60 | $(test_objs) : $(OBJDIR)/%.o: %.c 61 | $(CC) -c $(CCFLAGS) $(EXTRAFLAGS) $< -o $@ 62 | 63 | .PHONY : clean 64 | clean : 65 | -rm -fr $(OBJDIR)/* $(TARGET_DIR)/* 66 | -rm -fr $(test_exec) 67 | -------------------------------------------------------------------------------- /server/include/sshinner_s.h: -------------------------------------------------------------------------------- 1 | #ifndef _SSHINNER_S_H 2 | #define _SSHINNER_S_H 3 | 4 | #include 5 | #include 6 | 7 | #include 8 | 9 | #include 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | 21 | #include 22 | #include 23 | 24 | #include "rbtree.h" 25 | 26 | #include "st_others.h" 27 | #include "st_slist.h" 28 | #include "sshinner.h" 29 | 30 | #include "sshinner_crypt.h" 31 | 32 | 33 | struct _activ_item; 34 | typedef struct _trans_item { 35 | SLIST_HEAD list; 36 | struct _activ_item* p_activ_item; 37 | unsigned short usr_lport; //USR本地连接的端口,作为标示 38 | // RC4_MD5 加密模块 39 | int is_enc; 40 | ENCRYPT_CTX ctx_enc; 41 | ENCRYPT_CTX ctx_dec; 42 | struct bufferevent *bev_u; 43 | struct bufferevent *bev_d; 44 | struct event* extra_ev; 45 | void* dat; 46 | } TRANS_ITEM, *P_TRANS_ITEM; 47 | 48 | struct _acct_item; 49 | typedef struct _activ_item { 50 | struct rb_node node; //这里 51 | struct _acct_item* p_acct; 52 | SLIST_HEAD list; 53 | struct event_base *base; 54 | sd_id128_t mach_uuid; // DEAMON机器的会话ID 55 | struct bufferevent *bev_daemon; // 控制信息传输通道 56 | struct bufferevent *bev_usr; 57 | unsigned char enc_key[RC4_MD5_KEY_LEN]; 58 | pthread_mutex_t trans_lock; 59 | SLIST_HEAD trans; 60 | unsigned long pkg_cnt; // 转发的数据包计数 61 | 62 | } ACTIV_ITEM, *P_ACTIV_ITEM; 63 | 64 | typedef struct _acct_item { 65 | char username [128]; // 66 | unsigned long userid; 67 | SLIST_HEAD list; //自身链表 68 | SLIST_HEAD items; // activ_item 69 | } ACCT_ITEM, *P_ACCT_ITEM; 70 | 71 | /* A connection queue. */ 72 | typedef struct conn_item { 73 | SLIST_HEAD list; 74 | int socket; 75 | union { 76 | unsigned long dat; 77 | void* ptr; 78 | } arg; 79 | }C_ITEM, *P_C_ITEM; 80 | 81 | struct event; 82 | typedef struct _thread_obj { 83 | pthread_t thread_id; /* unique ID of this thread */ 84 | struct event_base *base; /* libevent handle this thread uses */ 85 | struct event *p_notify_event; /* listen event for notify pipe */ 86 | int notify_receive_fd; /* receiving end of notify pipe */ 87 | int notify_send_fd; /* sending end of notify pipe */ 88 | pthread_mutex_t q_lock; 89 | SLIST_HEAD conn_queue; /* queue of new connections to handle */ 90 | } THREAD_OBJ, *P_THREAD_OBJ; 91 | 92 | 93 | static const char* PRIVATE_KEY_FILE = "./ssl/private.key"; 94 | 95 | typedef struct _srv_opt 96 | { 97 | pthread_t main_thread_id; 98 | unsigned short port; 99 | RSA * p_prikey; //服务器用的解密私钥 100 | struct event_base* main_base; 101 | struct event_base* evdns_base; 102 | 103 | pthread_mutex_t acct_lock; 104 | SLIST_HEAD acct_items; 105 | 106 | struct rb_root uuid_tree; 107 | 108 | int thread_num; 109 | P_THREAD_OBJ thread_objs; 110 | }SRV_OPT, *P_SRV_OPT; 111 | 112 | 113 | /** 114 | * 工具类函数 115 | */ 116 | extern RET_T load_settings_server(P_SRV_OPT p_opt); 117 | extern void dump_srv_opts(P_SRV_OPT p_opt); 118 | 119 | /** 120 | * 处理连接请求类函数 121 | */ 122 | void accept_conn_cb(struct evconnlistener *listener, 123 | evutil_socket_t fd, struct sockaddr *address, int socklen, 124 | void *ctx); 125 | void accept_error_cb(struct evconnlistener *listener, void *ctx); 126 | void bufferevent_cb(struct bufferevent *bev, short events, void *ptr); 127 | 128 | void main_bufferread_cb(struct bufferevent *bev, void *ptr); 129 | void main_bufferevent_cb(struct bufferevent *bev, short events, void *ptr); 130 | static RET_T ss_main_handle_init(struct bufferevent *bev, 131 | P_CTL_HEAD p_head, char* dat); 132 | static RET_T ss_main_handle_ss5(struct bufferevent *bev, 133 | P_CTL_HEAD p_head, void* dat); 134 | static RET_T ss_main_handle_dns(struct bufferevent *bev, 135 | P_CTL_HEAD p_head, void* dat); 136 | static RET_T ss_main_handle_ctl(struct bufferevent *bev, P_CTL_HEAD p_head); 137 | RET_T ss_send_head_cmd(struct bufferevent *bev, P_CTL_HEAD p_head, 138 | int cmd, enum DIREC direct, unsigned long extra_param); 139 | 140 | /** 141 | * 数据转发和处理类函数 142 | */ 143 | extern RET_T ss_create_worker_threads(size_t thread_num, P_THREAD_OBJ threads); 144 | extern void thread_bufferevent_cb(struct bufferevent *bev, short events, void *ptr); 145 | extern void thread_bufferread_cb(struct bufferevent *bev, void *ptr); 146 | 147 | extern void thread_bufferread_cb_enc(struct bufferevent *bev, void *ptr); 148 | 149 | /* 简易从服务器发送控制信息 */ 150 | 151 | 152 | extern void ss_ret_cmd_ok(struct bufferevent *bev, 153 | sd_id128_t uuid, enum DIREC direct); 154 | extern void ss_ret_cmd_err(struct bufferevent *bev, 155 | sd_id128_t uuid, enum DIREC direct); 156 | extern void ss_cmd_end_trans(P_TRANS_ITEM p_trans); 157 | 158 | extern SRV_OPT srvopt; 159 | 160 | /** 161 | * UUID到线程池索引的映射 162 | */ 163 | static inline P_THREAD_OBJ ss_get_threadobj(unsigned long salt) 164 | { 165 | return (&srvopt.thread_objs[ (salt % srvopt.thread_num)] ); 166 | } 167 | 168 | extern RET_T ss_acct_remove(P_SRV_OPT p_srvopt, P_ACCT_ITEM p_item); 169 | extern RET_T ss_activ_item_remove(P_SRV_OPT p_srvopt, P_ACTIV_ITEM p_item); 170 | 171 | extern P_TRANS_ITEM ss_find_trans(P_ACTIV_ITEM p_activ_item, 172 | unsigned short l_sock); 173 | extern P_TRANS_ITEM ss_create_trans(P_ACTIV_ITEM p_activ_item, 174 | unsigned short l_sock); 175 | extern RET_T ss_free_trans(P_ACTIV_ITEM p_activ_item, P_TRANS_ITEM p_trans); 176 | extern RET_T ss_free_all_trans(P_ACTIV_ITEM p_activ_item); 177 | 178 | 179 | // DNS 异步查询 180 | typedef struct _dns_struct { 181 | char hostname [128]; // abitriay 182 | ev_uint16_t port; 183 | P_THREAD_OBJ p_threadobj; 184 | P_C_ITEM p_c_item; 185 | P_TRANS_ITEM p_trans; 186 | } DNS_STRUCT, *P_DNS_STRUCT; 187 | 188 | void dns_query_cb(int errcode, struct evutil_addrinfo *addr, void *ptr); 189 | 190 | #endif 191 | -------------------------------------------------------------------------------- /server/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "server": 3 | { 4 | "thread_num": 20, 5 | "port": 8900, 6 | }, 7 | } 8 | -------------------------------------------------------------------------------- /server/source/rbtree.c: -------------------------------------------------------------------------------- 1 | /* 2 | Red Black Trees 3 | (C) 1999 Andrea Arcangeli 4 | (C) 2002 David Woodhouse 5 | (C) 2012 Michel Lespinasse 6 | 7 | This program is free software; you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation; either version 2 of the License, or 10 | (at your option) any later version. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program; if not, write to the Free Software 19 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 | 21 | linux/lib/rbtree.c 22 | */ 23 | 24 | #include "rbtree_augmented.h" 25 | 26 | /* 27 | * red-black trees properties: http://en.wikipedia.org/wiki/Rbtree 28 | * 29 | * 1) A node is either red or black 30 | * 2) The root is black 31 | * 3) All leaves (NULL) are black 32 | * 4) Both children of every red node are black 33 | * 5) Every simple path from root to leaves contains the same number 34 | * of black nodes. 35 | * 36 | * 4 and 5 give the O(log n) guarantee, since 4 implies you cannot have two 37 | * consecutive red nodes in a path and every red node is therefore followed by 38 | * a black. So if B is the number of black nodes on every simple path (as per 39 | * 5), then the longest possible path due to 4 is 2B. 40 | * 41 | * We shall indicate color with case, where black nodes are uppercase and red 42 | * nodes will be lowercase. Unknown color nodes shall be drawn as red within 43 | * parentheses and have some accompanying text comment. 44 | */ 45 | 46 | 47 | enum _bool { false = 0, true = 1 }; 48 | 49 | static inline void rb_set_black(struct rb_node *rb) 50 | { 51 | rb->__rb_parent_color |= RB_BLACK; 52 | } 53 | 54 | static inline struct rb_node *rb_red_parent(struct rb_node *red) 55 | { 56 | return (struct rb_node *)red->__rb_parent_color; 57 | } 58 | 59 | /* 60 | * Helper function for rotations: 61 | * - old's parent and color get assigned to new 62 | * - old gets assigned new as a parent and 'color' as a color. 63 | */ 64 | static inline void 65 | __rb_rotate_set_parents(struct rb_node *old, struct rb_node *new, 66 | struct rb_root *root, int color) 67 | { 68 | struct rb_node *parent = rb_parent(old); 69 | new->__rb_parent_color = old->__rb_parent_color; 70 | rb_set_parent_color(old, new, color); 71 | __rb_change_child(old, new, parent, root); 72 | } 73 | 74 | static inline void 75 | __rb_insert(struct rb_node *node, struct rb_root *root, 76 | void (*augment_rotate)(struct rb_node *old, struct rb_node *new)) 77 | { 78 | struct rb_node *parent = rb_red_parent(node), *gparent, *tmp; 79 | 80 | while (true) { 81 | /* 82 | * Loop invariant: node is red 83 | * 84 | * If there is a black parent, we are done. 85 | * Otherwise, take some corrective action as we don't 86 | * want a red root or two consecutive red nodes. 87 | */ 88 | if (!parent) { 89 | rb_set_parent_color(node, NULL, RB_BLACK); 90 | break; 91 | } else if (rb_is_black(parent)) 92 | break; 93 | 94 | gparent = rb_red_parent(parent); 95 | 96 | tmp = gparent->rb_right; 97 | if (parent != tmp) { /* parent == gparent->rb_left */ 98 | if (tmp && rb_is_red(tmp)) { 99 | /* 100 | * Case 1 - color flips 101 | * 102 | * G g 103 | * / \ / \ 104 | * p u --> P U 105 | * / / 106 | * n n 107 | * 108 | * However, since g's parent might be red, and 109 | * 4) does not allow this, we need to recurse 110 | * at g. 111 | */ 112 | rb_set_parent_color(tmp, gparent, RB_BLACK); 113 | rb_set_parent_color(parent, gparent, RB_BLACK); 114 | node = gparent; 115 | parent = rb_parent(node); 116 | rb_set_parent_color(node, parent, RB_RED); 117 | continue; 118 | } 119 | 120 | tmp = parent->rb_right; 121 | if (node == tmp) { 122 | /* 123 | * Case 2 - left rotate at parent 124 | * 125 | * G G 126 | * / \ / \ 127 | * p U --> n U 128 | * \ / 129 | * n p 130 | * 131 | * This still leaves us in violation of 4), the 132 | * continuation into Case 3 will fix that. 133 | */ 134 | parent->rb_right = tmp = node->rb_left; 135 | node->rb_left = parent; 136 | if (tmp) 137 | rb_set_parent_color(tmp, parent, 138 | RB_BLACK); 139 | rb_set_parent_color(parent, node, RB_RED); 140 | augment_rotate(parent, node); 141 | parent = node; 142 | tmp = node->rb_right; 143 | } 144 | 145 | /* 146 | * Case 3 - right rotate at gparent 147 | * 148 | * G P 149 | * / \ / \ 150 | * p U --> n g 151 | * / \ 152 | * n U 153 | */ 154 | gparent->rb_left = tmp; /* == parent->rb_right */ 155 | parent->rb_right = gparent; 156 | if (tmp) 157 | rb_set_parent_color(tmp, gparent, RB_BLACK); 158 | __rb_rotate_set_parents(gparent, parent, root, RB_RED); 159 | augment_rotate(gparent, parent); 160 | break; 161 | } else { 162 | tmp = gparent->rb_left; 163 | if (tmp && rb_is_red(tmp)) { 164 | /* Case 1 - color flips */ 165 | rb_set_parent_color(tmp, gparent, RB_BLACK); 166 | rb_set_parent_color(parent, gparent, RB_BLACK); 167 | node = gparent; 168 | parent = rb_parent(node); 169 | rb_set_parent_color(node, parent, RB_RED); 170 | continue; 171 | } 172 | 173 | tmp = parent->rb_left; 174 | if (node == tmp) { 175 | /* Case 2 - right rotate at parent */ 176 | parent->rb_left = tmp = node->rb_right; 177 | node->rb_right = parent; 178 | if (tmp) 179 | rb_set_parent_color(tmp, parent, 180 | RB_BLACK); 181 | rb_set_parent_color(parent, node, RB_RED); 182 | augment_rotate(parent, node); 183 | parent = node; 184 | tmp = node->rb_left; 185 | } 186 | 187 | /* Case 3 - left rotate at gparent */ 188 | gparent->rb_right = tmp; /* == parent->rb_left */ 189 | parent->rb_left = gparent; 190 | if (tmp) 191 | rb_set_parent_color(tmp, gparent, RB_BLACK); 192 | __rb_rotate_set_parents(gparent, parent, root, RB_RED); 193 | augment_rotate(gparent, parent); 194 | break; 195 | } 196 | } 197 | } 198 | 199 | /* 200 | * Inline version for rb_erase() use - we want to be able to inline 201 | * and eliminate the dummy_rotate callback there 202 | */ 203 | static inline void 204 | ____rb_erase_color(struct rb_node *parent, struct rb_root *root, 205 | void (*augment_rotate)(struct rb_node *old, struct rb_node *new)) 206 | { 207 | struct rb_node *node = NULL, *sibling, *tmp1, *tmp2; 208 | 209 | while (true) { 210 | /* 211 | * Loop invariants: 212 | * - node is black (or NULL on first iteration) 213 | * - node is not the root (parent is not NULL) 214 | * - All leaf paths going through parent and node have a 215 | * black node count that is 1 lower than other leaf paths. 216 | */ 217 | sibling = parent->rb_right; 218 | if (node != sibling) { /* node == parent->rb_left */ 219 | if (rb_is_red(sibling)) { 220 | /* 221 | * Case 1 - left rotate at parent 222 | * 223 | * P S 224 | * / \ / \ 225 | * N s --> p Sr 226 | * / \ / \ 227 | * Sl Sr N Sl 228 | */ 229 | parent->rb_right = tmp1 = sibling->rb_left; 230 | sibling->rb_left = parent; 231 | rb_set_parent_color(tmp1, parent, RB_BLACK); 232 | __rb_rotate_set_parents(parent, sibling, root, 233 | RB_RED); 234 | augment_rotate(parent, sibling); 235 | sibling = tmp1; 236 | } 237 | tmp1 = sibling->rb_right; 238 | if (!tmp1 || rb_is_black(tmp1)) { 239 | tmp2 = sibling->rb_left; 240 | if (!tmp2 || rb_is_black(tmp2)) { 241 | /* 242 | * Case 2 - sibling color flip 243 | * (p could be either color here) 244 | * 245 | * (p) (p) 246 | * / \ / \ 247 | * N S --> N s 248 | * / \ / \ 249 | * Sl Sr Sl Sr 250 | * 251 | * This leaves us violating 5) which 252 | * can be fixed by flipping p to black 253 | * if it was red, or by recursing at p. 254 | * p is red when coming from Case 1. 255 | */ 256 | rb_set_parent_color(sibling, parent, 257 | RB_RED); 258 | if (rb_is_red(parent)) 259 | rb_set_black(parent); 260 | else { 261 | node = parent; 262 | parent = rb_parent(node); 263 | if (parent) 264 | continue; 265 | } 266 | break; 267 | } 268 | /* 269 | * Case 3 - right rotate at sibling 270 | * (p could be either color here) 271 | * 272 | * (p) (p) 273 | * / \ / \ 274 | * N S --> N Sl 275 | * / \ \ 276 | * sl Sr s 277 | * \ 278 | * Sr 279 | */ 280 | sibling->rb_left = tmp1 = tmp2->rb_right; 281 | tmp2->rb_right = sibling; 282 | parent->rb_right = tmp2; 283 | if (tmp1) 284 | rb_set_parent_color(tmp1, sibling, 285 | RB_BLACK); 286 | augment_rotate(sibling, tmp2); 287 | tmp1 = sibling; 288 | sibling = tmp2; 289 | } 290 | /* 291 | * Case 4 - left rotate at parent + color flips 292 | * (p and sl could be either color here. 293 | * After rotation, p becomes black, s acquires 294 | * p's color, and sl keeps its color) 295 | * 296 | * (p) (s) 297 | * / \ / \ 298 | * N S --> P Sr 299 | * / \ / \ 300 | * (sl) sr N (sl) 301 | */ 302 | parent->rb_right = tmp2 = sibling->rb_left; 303 | sibling->rb_left = parent; 304 | rb_set_parent_color(tmp1, sibling, RB_BLACK); 305 | if (tmp2) 306 | rb_set_parent(tmp2, parent); 307 | __rb_rotate_set_parents(parent, sibling, root, 308 | RB_BLACK); 309 | augment_rotate(parent, sibling); 310 | break; 311 | } else { 312 | sibling = parent->rb_left; 313 | if (rb_is_red(sibling)) { 314 | /* Case 1 - right rotate at parent */ 315 | parent->rb_left = tmp1 = sibling->rb_right; 316 | sibling->rb_right = parent; 317 | rb_set_parent_color(tmp1, parent, RB_BLACK); 318 | __rb_rotate_set_parents(parent, sibling, root, 319 | RB_RED); 320 | augment_rotate(parent, sibling); 321 | sibling = tmp1; 322 | } 323 | tmp1 = sibling->rb_left; 324 | if (!tmp1 || rb_is_black(tmp1)) { 325 | tmp2 = sibling->rb_right; 326 | if (!tmp2 || rb_is_black(tmp2)) { 327 | /* Case 2 - sibling color flip */ 328 | rb_set_parent_color(sibling, parent, 329 | RB_RED); 330 | if (rb_is_red(parent)) 331 | rb_set_black(parent); 332 | else { 333 | node = parent; 334 | parent = rb_parent(node); 335 | if (parent) 336 | continue; 337 | } 338 | break; 339 | } 340 | /* Case 3 - right rotate at sibling */ 341 | sibling->rb_right = tmp1 = tmp2->rb_left; 342 | tmp2->rb_left = sibling; 343 | parent->rb_left = tmp2; 344 | if (tmp1) 345 | rb_set_parent_color(tmp1, sibling, 346 | RB_BLACK); 347 | augment_rotate(sibling, tmp2); 348 | tmp1 = sibling; 349 | sibling = tmp2; 350 | } 351 | /* Case 4 - left rotate at parent + color flips */ 352 | parent->rb_left = tmp2 = sibling->rb_right; 353 | sibling->rb_right = parent; 354 | rb_set_parent_color(tmp1, sibling, RB_BLACK); 355 | if (tmp2) 356 | rb_set_parent(tmp2, parent); 357 | __rb_rotate_set_parents(parent, sibling, root, 358 | RB_BLACK); 359 | augment_rotate(parent, sibling); 360 | break; 361 | } 362 | } 363 | } 364 | 365 | /* Non-inline version for rb_erase_augmented() use */ 366 | void __rb_erase_color(struct rb_node *parent, struct rb_root *root, 367 | void (*augment_rotate)(struct rb_node *old, struct rb_node *new)) 368 | { 369 | ____rb_erase_color(parent, root, augment_rotate); 370 | } 371 | 372 | /* 373 | * Non-augmented rbtree manipulation functions. 374 | * 375 | * We use dummy augmented callbacks here, and have the compiler optimize them 376 | * out of the rb_insert_color() and rb_erase() function definitions. 377 | */ 378 | 379 | static inline void dummy_propagate(struct rb_node *node, struct rb_node *stop) {} 380 | static inline void dummy_copy(struct rb_node *old, struct rb_node *new) {} 381 | static inline void dummy_rotate(struct rb_node *old, struct rb_node *new) {} 382 | 383 | static const struct rb_augment_callbacks dummy_callbacks = { 384 | dummy_propagate, dummy_copy, dummy_rotate 385 | }; 386 | 387 | void rb_insert_color(struct rb_node *node, struct rb_root *root) 388 | { 389 | __rb_insert(node, root, dummy_rotate); 390 | } 391 | 392 | void rb_erase(struct rb_node *node, struct rb_root *root) 393 | { 394 | struct rb_node *rebalance; 395 | rebalance = __rb_erase_augmented(node, root, &dummy_callbacks); 396 | if (rebalance) 397 | ____rb_erase_color(rebalance, root, dummy_rotate); 398 | } 399 | 400 | /* 401 | * Augmented rbtree manipulation functions. 402 | * 403 | * This instantiates the same inline functions as in the non-augmented 404 | * case, but this time with user-defined callbacks. 405 | */ 406 | 407 | void __rb_insert_augmented(struct rb_node *node, struct rb_root *root, 408 | void (*augment_rotate)(struct rb_node *old, struct rb_node *new)) 409 | { 410 | __rb_insert(node, root, augment_rotate); 411 | } 412 | 413 | /* 414 | * This function returns the first node (in sort order) of the tree. 415 | */ 416 | struct rb_node *rb_first(const struct rb_root *root) 417 | { 418 | struct rb_node *n; 419 | 420 | n = root->rb_node; 421 | if (!n) 422 | return NULL; 423 | while (n->rb_left) 424 | n = n->rb_left; 425 | return n; 426 | } 427 | 428 | struct rb_node *rb_last(const struct rb_root *root) 429 | { 430 | struct rb_node *n; 431 | 432 | n = root->rb_node; 433 | if (!n) 434 | return NULL; 435 | while (n->rb_right) 436 | n = n->rb_right; 437 | return n; 438 | } 439 | 440 | struct rb_node *rb_next(const struct rb_node *node) 441 | { 442 | struct rb_node *parent; 443 | 444 | if (RB_EMPTY_NODE(node)) 445 | return NULL; 446 | 447 | /* 448 | * If we have a right-hand child, go down and then left as far 449 | * as we can. 450 | */ 451 | if (node->rb_right) { 452 | node = node->rb_right; 453 | while (node->rb_left) 454 | node=node->rb_left; 455 | return (struct rb_node *)node; 456 | } 457 | 458 | /* 459 | * No right-hand children. Everything down and left is smaller than us, 460 | * so any 'next' node must be in the general direction of our parent. 461 | * Go up the tree; any time the ancestor is a right-hand child of its 462 | * parent, keep going up. First time it's a left-hand child of its 463 | * parent, said parent is our 'next' node. 464 | */ 465 | while ((parent = rb_parent(node)) && node == parent->rb_right) 466 | node = parent; 467 | 468 | return parent; 469 | } 470 | 471 | struct rb_node *rb_prev(const struct rb_node *node) 472 | { 473 | struct rb_node *parent; 474 | 475 | if (RB_EMPTY_NODE(node)) 476 | return NULL; 477 | 478 | /* 479 | * If we have a left-hand child, go down and then right as far 480 | * as we can. 481 | */ 482 | if (node->rb_left) { 483 | node = node->rb_left; 484 | while (node->rb_right) 485 | node=node->rb_right; 486 | return (struct rb_node *)node; 487 | } 488 | 489 | /* 490 | * No left-hand children. Go up till we find an ancestor which 491 | * is a right-hand child of its parent. 492 | */ 493 | while ((parent = rb_parent(node)) && node == parent->rb_left) 494 | node = parent; 495 | 496 | return parent; 497 | } 498 | 499 | void rb_replace_node(struct rb_node *victim, struct rb_node *new, 500 | struct rb_root *root) 501 | { 502 | struct rb_node *parent = rb_parent(victim); 503 | 504 | /* Set the surrounding nodes to point to the replacement */ 505 | __rb_change_child(victim, new, parent, root); 506 | if (victim->rb_left) 507 | rb_set_parent(victim->rb_left, new); 508 | if (victim->rb_right) 509 | rb_set_parent(victim->rb_right, new); 510 | 511 | /* Copy the pointers/colour from the victim to the replacement */ 512 | *new = *victim; 513 | } 514 | 515 | static struct rb_node *rb_left_deepest_node(const struct rb_node *node) 516 | { 517 | for (;;) { 518 | if (node->rb_left) 519 | node = node->rb_left; 520 | else if (node->rb_right) 521 | node = node->rb_right; 522 | else 523 | return (struct rb_node *)node; 524 | } 525 | } 526 | 527 | struct rb_node *rb_next_postorder(const struct rb_node *node) 528 | { 529 | const struct rb_node *parent; 530 | if (!node) 531 | return NULL; 532 | parent = rb_parent(node); 533 | 534 | /* If we're sitting on node, we've already seen our children */ 535 | if (parent && node == parent->rb_left && parent->rb_right) { 536 | /* If we are the parent's left node, go to the parent's right 537 | * node then all the way down to the left */ 538 | return rb_left_deepest_node(parent->rb_right); 539 | } else 540 | /* Otherwise we are the parent's right node, and the parent 541 | * should be next */ 542 | return (struct rb_node *)parent; 543 | } 544 | 545 | struct rb_node *rb_first_postorder(const struct rb_root *root) 546 | { 547 | if (!root->rb_node) 548 | return NULL; 549 | 550 | return rb_left_deepest_node(root->rb_node); 551 | } 552 | -------------------------------------------------------------------------------- /server/source/server.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include 7 | #include 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #include "st_others.h" 16 | #include "sshinner_s.h" 17 | #include "rbtree.h" 18 | 19 | /** 20 | * This program aim on the server side of libevent 21 | */ 22 | 23 | 24 | SRV_OPT srvopt; 25 | 26 | int main(int argc, char* argv[]) 27 | { 28 | 29 | #if 1 30 | // For debug with segment fault 31 | struct sigaction sa; 32 | sa.sa_handler = backtrace_info; 33 | sigaction(SIGSEGV, &sa, NULL); 34 | 35 | // ignore SIGPIPE 36 | signal(SIGPIPE, SIG_IGN); 37 | signal(SIGCHLD, SIG_IGN); 38 | signal(SIGABRT, SIG_IGN); 39 | 40 | #endif 41 | 42 | memset(&srvopt, 0, sizeof(SRV_OPT)); 43 | 44 | if(load_settings_server(&srvopt) == RET_NO) 45 | { 46 | st_d_error("加载settings.js配置文件出错!"); 47 | exit(EXIT_FAILURE); 48 | } 49 | 50 | dump_srv_opts(&srvopt); 51 | 52 | OpenSSL_add_ssl_algorithms(); 53 | SSL_load_error_strings(); 54 | SSL_library_init(); //SSL_library_init() always returns "1" 55 | 56 | /*加载SSL私钥*/ 57 | FILE *fp = fopen(PRIVATE_KEY_FILE, "r"); 58 | if (!fp) 59 | { 60 | st_d_error("SERVER读取私钥文件%s失败!", PRIVATE_KEY_FILE); 61 | exit(EXIT_FAILURE); 62 | } 63 | 64 | srvopt.uuid_tree = RB_ROOT; 65 | 66 | srvopt.p_prikey = RSA_new(); 67 | 68 | if(PEM_read_RSAPrivateKey(fp, &srvopt.p_prikey, 0, 0) == NULL) 69 | { 70 | st_d_error("SERVER加载私钥失败!"); 71 | fclose(fp); 72 | RSA_free(srvopt.p_prikey); 73 | exit(EXIT_FAILURE); 74 | } 75 | fclose(fp); 76 | 77 | srvopt.main_thread_id = pthread_self(); 78 | srvopt.thread_objs = (P_THREAD_OBJ)calloc(sizeof(THREAD_OBJ), srvopt.thread_num); 79 | if (!srvopt.thread_objs) 80 | { 81 | SYS_ABORT("申请THREAD_OBJ出错"); 82 | } 83 | 84 | ss_create_worker_threads(srvopt.thread_num, srvopt.thread_objs); 85 | 86 | /*带配置产生event_base对象*/ 87 | struct event_config *cfg; 88 | cfg = event_config_new(); 89 | event_config_avoid_method(cfg, "select"); //避免使用select 90 | event_config_require_features(cfg, EV_FEATURE_ET); //使用边沿触发类型 91 | srvopt.main_base = event_base_new_with_config(cfg); 92 | event_config_free(cfg); 93 | 94 | srvopt.evdns_base = evdns_base_new(srvopt.main_base, 1); 95 | //evdns_base_nameserver_ip_add(srvopt.evdns_base, "8.8.8.8"); 96 | //evdns_base_nameserver_ip_add(srvopt.evdns_base, "8.8.4.4"); 97 | //evdns_base_nameserver_ip_add(srvopt.evdns_base, "10.0.0.1"); 98 | 99 | st_d_print("当前复用Event模式: %s", event_base_get_method(srvopt.main_base)); // epoll 100 | 101 | 102 | /** 103 | * 建立Listen侦听套接字 104 | */ 105 | struct evconnlistener *listener; 106 | struct sockaddr_in sin; 107 | memset(&sin, 0, sizeof(sin)); 108 | sin.sin_family = AF_INET; 109 | sin.sin_addr.s_addr = htonl(0); 110 | sin.sin_port = htons(srvopt.port); /* Port Num */ 111 | 112 | listener = evconnlistener_new_bind(srvopt.main_base, accept_conn_cb, NULL, 113 | LEV_OPT_CLOSE_ON_FREE|LEV_OPT_REUSEABLE, -1/*backlog*/, 114 | (struct sockaddr*)&sin, sizeof(sin)); 115 | 116 | if (!listener) 117 | { 118 | st_d_error("创建侦听套接字出错!"); 119 | return -1; 120 | } 121 | evconnlistener_set_error_cb(listener, accept_error_cb); 122 | 123 | /** 124 | * Main Loop Here 125 | */ 126 | event_base_loop(srvopt.main_base, 0); 127 | 128 | if (srvopt.p_prikey) 129 | RSA_free(srvopt.p_prikey); 130 | 131 | evconnlistener_free(listener); 132 | 133 | evdns_base_free(srvopt.evdns_base, 0); 134 | event_base_free(srvopt.main_base); 135 | 136 | st_d_print("Program terminated!"); 137 | return 0; 138 | } 139 | 140 | -------------------------------------------------------------------------------- /server/source/sshinner_s_data.c: -------------------------------------------------------------------------------- 1 | #include "rbtree.h" 2 | #include "sshinner_s.h" 3 | 4 | #include 5 | 6 | extern P_ACCT_ITEM ss_find_acct_item(P_SRV_OPT p_srvopt, 7 | const char* username, unsigned long userid) 8 | { 9 | if (!p_srvopt || !username || slist_empty(&p_srvopt->acct_items)) 10 | return NULL; 11 | 12 | P_ACCT_ITEM p_acct_item = NULL; 13 | 14 | slist_for_each_entry(p_acct_item, &p_srvopt->acct_items, list) 15 | { 16 | if (!strncasecmp(username, p_acct_item->username, strlen(p_acct_item->username)) 17 | && userid == p_acct_item->userid) 18 | { 19 | return p_acct_item; 20 | } 21 | } 22 | 23 | return NULL; 24 | } 25 | 26 | extern P_ACTIV_ITEM ss_uuid_search(struct rb_root *root, sd_id128_t uuid) 27 | { 28 | struct rb_node *node = root->rb_node; 29 | P_ACTIV_ITEM p_active_item = NULL; 30 | 31 | while (node) 32 | { 33 | p_active_item = container_of(node, ACTIV_ITEM, node); 34 | 35 | if (memcmp(&uuid, &p_active_item->mach_uuid, MACH_UUID_LEN) < 0) 36 | { 37 | node = node->rb_left; 38 | } 39 | else if (memcmp(&uuid, &p_active_item->mach_uuid, MACH_UUID_LEN) > 0) 40 | { 41 | node = node->rb_right; 42 | } 43 | else 44 | return p_active_item; 45 | } 46 | 47 | return NULL; 48 | } 49 | 50 | extern RET_T ss_uuid_insert(struct rb_root *root, P_ACTIV_ITEM data) 51 | { 52 | struct rb_node **new = &(root->rb_node), *parent = NULL; 53 | 54 | /* Figure out where to put new node */ 55 | while (*new) 56 | { 57 | P_ACTIV_ITEM this = container_of(*new, ACTIV_ITEM, node); 58 | 59 | parent = *new; 60 | if (memcmp(&data->mach_uuid, &this->mach_uuid, MACH_UUID_LEN) < 0) 61 | new = &((*new)->rb_left); 62 | else if (memcmp(&data->mach_uuid, &this->mach_uuid, MACH_UUID_LEN) > 0) 63 | new = &((*new)->rb_right); 64 | else 65 | return RET_NO; 66 | } 67 | 68 | /* Add new node and rebalance tree. */ 69 | rb_link_node(&data->node, parent, new); 70 | rb_insert_color(&data->node, root); 71 | 72 | return RET_YES; 73 | } 74 | 75 | 76 | extern void ss_uuid_erase(P_ACTIV_ITEM data, struct rb_root *tree) 77 | { 78 | if (!data || ! tree) 79 | return; 80 | 81 | return rb_erase(&data->node, tree); 82 | } 83 | 84 | extern RET_T ss_activ_item_remove(P_SRV_OPT p_srvopt, P_ACTIV_ITEM p_item) 85 | { 86 | P_ACCT_ITEM p_acct_item = NULL; 87 | P_ACTIV_ITEM p_activ_item = NULL; 88 | 89 | p_activ_item = ss_uuid_search(&p_srvopt->uuid_tree, p_item->mach_uuid); 90 | if (!p_activ_item) 91 | { 92 | st_d_error("MACH_UUID: %s not fould!", SD_ID128_CONST_STR(p_activ_item->mach_uuid)); 93 | return RET_NO; 94 | } 95 | 96 | p_acct_item = p_activ_item->p_acct; 97 | st_d_print("删除对话:%s:%lu UUID %s!", p_acct_item->username, 98 | p_acct_item->userid, SD_ID128_CONST_STR(p_activ_item->mach_uuid)); 99 | 100 | ss_free_all_trans(p_activ_item); 101 | 102 | ss_uuid_erase(p_activ_item, &srvopt.uuid_tree); 103 | slist_remove(&p_activ_item->list, &p_acct_item->items); 104 | free(p_activ_item); 105 | 106 | if (slist_empty(&p_acct_item->items)) 107 | { 108 | ss_acct_remove(p_srvopt, p_acct_item); 109 | } 110 | 111 | return RET_YES; 112 | } 113 | 114 | 115 | extern RET_T ss_acct_remove(P_SRV_OPT p_srvopt, P_ACCT_ITEM p_item) 116 | { 117 | P_SLIST_HEAD p_pos = NULL; 118 | P_SLIST_HEAD p_n = NULL; 119 | P_ACCT_ITEM p_acct_item = NULL; 120 | 121 | RET_T ret = RET_NO; 122 | 123 | if (!slist_empty(&p_item->items)) 124 | { 125 | st_d_error("账户 %s:%lu 对话不为空,无法删除!", p_item->username, 126 | p_item->userid); 127 | return RET_NO; 128 | } 129 | 130 | slist_for_each_safe(p_pos, p_n/*internel use*/, &p_srvopt->acct_items) 131 | { 132 | p_acct_item = list_entry(p_pos, ACCT_ITEM, list); 133 | if (p_acct_item == p_item) 134 | { 135 | st_d_print("释放账号%s:%lu", p_item->username, p_item->userid); 136 | // free this block 137 | slist_remove(&p_item->list, &p_srvopt->acct_items); 138 | free(p_acct_item); 139 | ret = RET_YES; 140 | break; 141 | } 142 | } 143 | 144 | return ret; 145 | } 146 | 147 | 148 | 149 | extern P_TRANS_ITEM ss_find_trans(P_ACTIV_ITEM p_activ_item, 150 | unsigned short l_sock) 151 | { 152 | P_TRANS_ITEM p_trans = NULL; 153 | 154 | if (!p_activ_item || slist_empty(&p_activ_item->trans)) 155 | return NULL; 156 | 157 | slist_for_each_entry(p_trans, &p_activ_item->trans, list) 158 | { 159 | if (p_trans->usr_lport == l_sock) 160 | { 161 | return p_trans; 162 | } 163 | } 164 | 165 | return NULL; 166 | } 167 | 168 | extern P_TRANS_ITEM ss_create_trans(P_ACTIV_ITEM p_activ_item, 169 | unsigned short l_sock) 170 | { 171 | P_TRANS_ITEM p_trans = NULL; 172 | 173 | if (!p_activ_item) 174 | { 175 | st_d_error("参数不合法!"); 176 | return NULL; 177 | } 178 | 179 | if (ss_find_trans(p_activ_item, l_sock)) 180 | { 181 | st_d_error("TRANS已经存在:%d", l_sock); 182 | return NULL; 183 | } 184 | 185 | p_trans = (P_TRANS_ITEM)calloc(sizeof(TRANS_ITEM), 1); 186 | if (!p_trans) 187 | { 188 | st_d_error("TRANS申请内存失败!"); 189 | return NULL; 190 | } 191 | 192 | p_trans->usr_lport = l_sock; 193 | 194 | pthread_mutex_lock(&p_activ_item->trans_lock); 195 | slist_add(&p_trans->list, &p_activ_item->trans); 196 | pthread_mutex_unlock(&p_activ_item->trans_lock); 197 | 198 | return p_trans; 199 | } 200 | 201 | 202 | extern RET_T ss_free_trans(P_ACTIV_ITEM p_activ_item, P_TRANS_ITEM p_trans) 203 | { 204 | if (!p_activ_item || slist_empty(&p_activ_item->trans) 205 | || !p_trans || !p_trans->usr_lport) 206 | { 207 | st_d_error("Free参数失败!"); 208 | return RET_NO; 209 | } 210 | 211 | CTL_HEAD head; 212 | memset(&head, 0, CTL_HEAD_LEN); 213 | 214 | head.direct = USR_DAEMON; 215 | head.cmd = HD_CMD_END_TRANS; 216 | head.extra_param = p_trans->usr_lport; 217 | head.mach_uuid = p_trans->p_activ_item->mach_uuid; 218 | 219 | pthread_mutex_lock(&p_activ_item->trans_lock); 220 | slist_remove(&p_trans->list, &p_activ_item->trans); 221 | 222 | st_d_print("DDDDD: 当前活动连接数:[[[ %d ]]], 释放:[%d]", 223 | slist_count(&p_activ_item->trans), p_trans->usr_lport); 224 | 225 | p_trans->usr_lport = 0; 226 | pthread_mutex_unlock(&p_activ_item->trans_lock); 227 | 228 | 229 | if (p_trans->bev_d) 230 | { 231 | bufferevent_free(p_trans->bev_d); 232 | p_trans->bev_d = NULL; 233 | } 234 | 235 | if (p_trans->bev_u) 236 | { 237 | bufferevent_free(p_trans->bev_u); 238 | p_trans->bev_u = NULL; 239 | } 240 | 241 | 242 | if (p_trans->is_enc) 243 | { 244 | encrypt_ctx_free(&p_trans->ctx_enc); 245 | encrypt_ctx_free(&p_trans->ctx_dec); 246 | } 247 | 248 | assert(p_trans->p_activ_item->bev_daemon); 249 | //bufferevent_write(p_trans->p_activ_item->bev_daemon, &head, CTL_HEAD_LEN); 250 | 251 | free(p_trans); 252 | 253 | return RET_YES; 254 | } 255 | 256 | 257 | extern RET_T ss_free_all_trans(P_ACTIV_ITEM p_activ_item) 258 | { 259 | P_TRANS_ITEM p_trans = NULL; 260 | P_SLIST_HEAD pos = NULL, n = NULL; 261 | 262 | pthread_mutex_lock(&p_activ_item->trans_lock); 263 | 264 | if (!p_activ_item || slist_empty(&p_activ_item->trans)) 265 | { 266 | pthread_mutex_unlock(&p_activ_item->trans_lock); 267 | return RET_YES; 268 | } 269 | 270 | slist_for_each_safe(pos, n, &p_activ_item->trans) 271 | { 272 | p_trans = list_entry(pos, TRANS_ITEM, list); 273 | st_d_print("释放:%d", p_trans->usr_lport); 274 | 275 | if (p_trans->is_enc) 276 | { 277 | encrypt_ctx_free(&p_trans->ctx_enc); 278 | encrypt_ctx_free(&p_trans->ctx_dec); 279 | } 280 | 281 | if (p_trans->bev_d) 282 | bufferevent_free(p_trans->bev_d); 283 | if (p_trans->bev_u) 284 | bufferevent_free(p_trans->bev_u); 285 | slist_remove(&p_trans->list, &p_activ_item->trans); 286 | free(p_trans); 287 | } 288 | 289 | pthread_mutex_unlock(&p_activ_item->trans_lock); 290 | 291 | return RET_YES; 292 | } 293 | -------------------------------------------------------------------------------- /server/source/sshinner_s_event.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include 6 | #include 7 | 8 | #include 9 | 10 | #include "sshinner_s.h" 11 | 12 | 13 | void main_bufferevent_cb(struct bufferevent *bev, short events, void *ptr) 14 | { 15 | P_ACTIV_ITEM p_item = (P_ACTIV_ITEM)ptr; 16 | 17 | struct event_base *base = bufferevent_get_base(bev); 18 | int loop_terminate_flag = 0; 19 | 20 | //只有使用bufferevent_socket_connect进行的连接才会得到CONNECTED的事件 21 | if (events & BEV_EVENT_CONNECTED) 22 | { 23 | st_d_print("GOT BEV_EVENT_CONNECTED event! "); 24 | } 25 | else if (events & BEV_EVENT_ERROR) 26 | { 27 | st_d_error("GOT BEV_EVENT_ERROR event! "); 28 | } 29 | else if (events & BEV_EVENT_EOF) 30 | { 31 | st_d_print("GOT BEV_EVENT_EOF event! "); 32 | 33 | // 对于任何一端断开了main_bev,那么服务端会拆除这个activ, 34 | // 以及其下面的所有的活动,然后CLT自己选择重新连接 35 | 36 | if (p_item) 37 | { 38 | if (p_item->bev_daemon == bev) 39 | { 40 | if (p_item->bev_usr) 41 | { 42 | int l_fd = bufferevent_getfd(p_item->bev_usr); 43 | bufferevent_free(p_item->bev_usr); 44 | close(l_fd); 45 | } 46 | } 47 | else if (p_item->bev_usr == bev) 48 | { 49 | if (p_item->bev_daemon) 50 | { 51 | int l_fd = bufferevent_getfd(p_item->bev_daemon); 52 | bufferevent_free(p_item->bev_daemon); 53 | close(l_fd); 54 | } 55 | } 56 | else 57 | { 58 | SYS_ABORT("BEV检测失败@@@@@"); 59 | } 60 | 61 | st_d_print("释放连接:%s", SD_ID128_CONST_STR(p_item->mach_uuid)); 62 | 63 | ss_activ_item_remove(&srvopt, p_item); 64 | 65 | } 66 | } 67 | else if (events & BEV_EVENT_TIMEOUT) 68 | { 69 | st_d_print("GOT BEV_EVENT_TIMEOUT event! "); 70 | } 71 | 72 | if (loop_terminate_flag) 73 | { 74 | bufferevent_free(bev); 75 | event_base_loopexit(base, NULL); 76 | } 77 | 78 | return; 79 | } 80 | 81 | 82 | /** 83 | * 监听套接字响应事件 84 | * 85 | * 这里需要接受客户端的一次数据,然后决定将这个客户端分配到 86 | * 哪个线程去处理,所以这里只进行一次call_back 87 | */ 88 | void accept_conn_cb(struct evconnlistener *listener, 89 | evutil_socket_t fd, struct sockaddr *address, int socklen, 90 | void *ctx) 91 | { 92 | char hbuf[NI_MAXHOST], sbuf[NI_MAXSERV]; 93 | 94 | getnameinfo (address, socklen, 95 | hbuf, sizeof(hbuf),sbuf, sizeof(sbuf), 96 | NI_NUMERICHOST | NI_NUMERICSERV); 97 | st_print("侦测到客户端连接请求 (HOST=%s, PORT=%s)\n", hbuf, sbuf); 98 | 99 | /* We got a new connection! Set up a bufferevent for it. */ 100 | struct event_base *base = evconnlistener_get_base(listener); 101 | struct bufferevent *bev = 102 | bufferevent_socket_new(base, fd, 0 /*BEV_OPT_CLOSE_ON_FREE*/); 103 | 104 | unsigned int optval = 1; 105 | setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &optval, sizeof(optval));//禁用NAGLE算法 106 | 107 | /** 108 | * 对于服务端,一般都是阻塞在读,而如果要写,一般在read_cb中写回就可以了 109 | */ 110 | bufferevent_setcb(bev, main_bufferread_cb, NULL, main_bufferevent_cb, NULL); 111 | bufferevent_enable(bev, EV_READ|EV_WRITE); 112 | 113 | st_d_print("侦听套接字创建侦听事件OK ..."); 114 | 115 | return; 116 | } 117 | 118 | void accept_error_cb(struct evconnlistener *listener, void *ctx) 119 | { 120 | struct event_base *base = evconnlistener_get_base(listener); 121 | int err = EVUTIL_SOCKET_ERROR(); 122 | 123 | st_d_error( "侦听套接字错误:%s", evutil_socket_error_to_string(err)); 124 | // event_base_loopexit(base, NULL); 125 | return; 126 | } 127 | 128 | 129 | /** 130 | * 读取事件,主要进行数据转发 131 | * 132 | * 这里命令字段和数据字段分开处理,命令是自己解析,而数据需要转发,需要 133 | * 为数据流程进行优化 134 | */ 135 | void main_bufferread_cb(struct bufferevent *bev, void *ptr) 136 | { 137 | size_t n = 0; 138 | CTL_HEAD head; 139 | RET_T ret; 140 | void *dat = NULL; 141 | 142 | struct evbuffer *input = bufferevent_get_input(bev); 143 | struct evbuffer *output = bufferevent_get_output(bev); 144 | 145 | if ( evbuffer_remove(input, &head, CTL_HEAD_LEN) != CTL_HEAD_LEN) 146 | { 147 | st_d_error("读取数据包头%d错误!", CTL_HEAD_LEN); 148 | return; 149 | } 150 | 151 | if (head.cmd == HD_CMD_SS5 || head.cmd == HD_CMD_DNS) 152 | { 153 | assert(head.dat_len > 0); 154 | 155 | if (head.dat_len > 0) 156 | { 157 | if (!(dat = malloc(head.dat_len)) ) 158 | { 159 | st_d_error("分配内存[%d]失败!", head.dat_len); 160 | return; 161 | } 162 | 163 | memset(dat, 0, head.dat_len); 164 | size_t offset = 0; 165 | while ((n = evbuffer_remove(input, dat+offset, head.dat_len-offset)) > 0) 166 | { 167 | if (n < (head.dat_len-offset)) 168 | { 169 | offset += n; 170 | continue; 171 | } 172 | else 173 | break; 174 | } 175 | 176 | ulong crc = crc32(0L, dat, head.dat_len); 177 | if (crc != head.crc) 178 | { 179 | st_d_error("数据包校验失败: %lu-%lu", crc, head.crc); 180 | st_d_print("=>%s", (char*) dat); //呵呵,已经加密了 181 | free(dat); 182 | return; 183 | } 184 | } 185 | if (head.cmd == HD_CMD_SS5) 186 | { 187 | ret = ss_main_handle_ss5(bev, &head, (char *)dat); 188 | } 189 | else if (head.cmd == HD_CMD_DNS) 190 | { 191 | ret = ss_main_handle_dns(bev, &head, (char *)dat); 192 | } 193 | if (ret == RET_NO) 194 | { 195 | ss_ret_cmd_err(bev, head.mach_uuid, 196 | head.direct == USR_DAEMON? DAEMON_USR: USR_DAEMON); 197 | /* 成功的时候会在thread线程池处理之后释放,失败在此释放*/ 198 | free(dat); 199 | } 200 | } 201 | else if (head.cmd == HD_CMD_INIT) 202 | { 203 | assert(head.dat_len > 0); 204 | 205 | if (head.dat_len > 0) 206 | { 207 | if (!(dat = malloc(head.dat_len)) ) 208 | { 209 | st_d_error("分配内存[%d]失败!", head.dat_len); 210 | return; 211 | } 212 | 213 | memset(dat, 0, head.dat_len); 214 | size_t offset = 0; 215 | while ((n = evbuffer_remove(input, dat+offset, head.dat_len-offset)) > 0) 216 | { 217 | if (n < (head.dat_len-offset)) 218 | { 219 | offset += n; 220 | continue; 221 | } 222 | else 223 | break; 224 | } 225 | 226 | ulong crc = crc32(0L, dat, head.dat_len); 227 | if (crc != head.crc) 228 | { 229 | st_d_error("数据包校验失败: %lu-%lu", crc, head.crc); 230 | st_d_print("=>%s", (char*) dat); //呵呵,已经加密了 231 | free(dat); 232 | return; 233 | } 234 | } 235 | ret = ss_main_handle_init(bev, &head, (char *)dat); 236 | if (ret == RET_NO) 237 | ss_ret_cmd_err(bev, head.mach_uuid, 238 | head.direct == USR_DAEMON? DAEMON_USR: USR_DAEMON); 239 | free(dat); 240 | } 241 | else 242 | { 243 | ret = ss_main_handle_ctl(bev, &head); 244 | if (ret == RET_NO) 245 | ss_ret_cmd_err(bev, head.mach_uuid, 246 | head.direct == USR_DAEMON? DAEMON_USR: USR_DAEMON); 247 | } 248 | 249 | return; 250 | } 251 | 252 | 253 | static RET_T ss_main_handle_init(struct bufferevent *bev, 254 | P_CTL_HEAD p_head, char* dat) 255 | { 256 | json_object *new_obj = NULL; 257 | json_object *p_store_obj = NULL; 258 | 259 | P_THREAD_OBJ p_threadobj = NULL; 260 | P_ACCT_ITEM p_acct_item = NULL; 261 | P_ACTIV_ITEM p_activ_item = NULL; 262 | 263 | char username [128]; 264 | unsigned long userid; 265 | char uuid_s [33]; 266 | sd_id128_t mach_uuid; 267 | char dec_buf [4096]; 268 | 269 | if (p_head->cmd != HD_CMD_INIT || dat == NULL) 270 | { 271 | st_d_print("HD_CMD_INIT SHOULD CONTAIN BODY!"); 272 | return RET_NO; 273 | } 274 | 275 | 276 | /*服务器私钥解密数据*/ 277 | memset(dec_buf, 0, sizeof(dec_buf)); 278 | int len = RSA_private_decrypt(p_head->dat_len, dat, dec_buf, 279 | srvopt.p_prikey, RSA_PKCS1_PADDING); 280 | if (len < 0 ) 281 | { 282 | st_d_error("服务端私钥解密数据%d出错!", len); 283 | return RET_NO; 284 | } 285 | 286 | new_obj = json_tokener_parse(dec_buf); 287 | 288 | if (!new_obj) 289 | { 290 | st_d_error("Json parse error: %s", dec_buf); 291 | return RET_NO; 292 | } 293 | 294 | json_fetch_and_copy(new_obj, "username", username, sizeof(username)); 295 | userid = json_object_get_int(json_object_object_get(new_obj,"userid")); 296 | 297 | /* 其实只是检测 */ 298 | if (p_head->direct == USR_DAEMON) 299 | { 300 | json_fetch_and_copy(new_obj, "r_mach_uuid", uuid_s, sizeof(uuid_s)); 301 | if (sd_id128_from_string(uuid_s, &mach_uuid) != 0) 302 | { 303 | st_d_error("UUID转换失败:%s!", uuid_s); 304 | goto error_ret; 305 | } 306 | 307 | p_acct_item = ss_find_acct_item(&srvopt, username, userid); 308 | if (!p_acct_item) 309 | { 310 | st_d_print("账户 %s:%lu 不存在!", username, userid); 311 | goto error_ret; 312 | } 313 | 314 | p_activ_item = ss_uuid_search(&srvopt.uuid_tree, mach_uuid); 315 | 316 | if (!p_activ_item) 317 | { 318 | st_d_print("会话 %s:%lu %s 不存在!", username, userid, 319 | SD_ID128_CONST_STR(mach_uuid)); 320 | goto error_ret; 321 | } 322 | 323 | p_activ_item->bev_usr = bev; 324 | 325 | /** 326 | * 向客户端返回OK 327 | */ 328 | st_d_print("检查会话OK: %s", SD_ID128_CONST_STR(p_head->mach_uuid)); 329 | sc_send_head_cmd(bev, p_head, HD_CMD_OK, DAEMON_USR, p_head->extra_param); 330 | 331 | /** 332 | * 这里重新进行一个callback绑定,为的是设定callback的参数 333 | */ 334 | bufferevent_setcb(bev, main_bufferread_cb, NULL, main_bufferevent_cb, p_activ_item); 335 | bufferevent_enable(bev, EV_READ|EV_WRITE); 336 | 337 | json_object_put(new_obj); 338 | return RET_YES; 339 | } 340 | else if (p_head->direct == DAEMON_USR) 341 | { 342 | p_acct_item = ss_find_acct_item(&srvopt, username, userid); 343 | 344 | if (!p_acct_item) 345 | { 346 | st_d_print("%s:%lu 用户尚未存在,创建之...", username, userid); 347 | 348 | p_acct_item = (P_ACCT_ITEM)malloc(sizeof(ACCT_ITEM)); 349 | if (!p_acct_item) 350 | { 351 | st_d_print("申请内存[%d]失败!", sizeof(ACCT_ITEM)); 352 | goto error_ret; 353 | } 354 | 355 | memset(p_acct_item, 0, sizeof(ACCT_ITEM)); 356 | strncpy(p_acct_item->username, username, sizeof(p_acct_item->username)); 357 | p_acct_item->userid = userid; 358 | 359 | slist_init(&p_acct_item->items); 360 | slist_add(&p_acct_item->list, &srvopt.acct_items); 361 | } 362 | 363 | if (ss_uuid_search(&srvopt.uuid_tree, p_head->mach_uuid)) 364 | { 365 | st_d_print("会话 %s:%lu %s 已经存在!", username, userid, 366 | SD_ID128_CONST_STR(p_head->mach_uuid)); 367 | goto error_ret; 368 | } 369 | 370 | p_activ_item = (P_ACTIV_ITEM)calloc(sizeof(ACTIV_ITEM), 1); 371 | if (!p_activ_item) 372 | { 373 | st_d_print("申请内存[%d]失败!", sizeof(ACTIV_ITEM)); 374 | goto error_ret; 375 | } 376 | 377 | p_activ_item->p_acct = p_acct_item; 378 | p_activ_item->base = srvopt.main_base; 379 | p_activ_item->mach_uuid = p_head->mach_uuid; 380 | pthread_mutex_init(&p_activ_item->trans_lock); 381 | 382 | encrypt_init(SD_ID128_CONST_STR(p_activ_item->mach_uuid), p_activ_item->enc_key); 383 | 384 | slist_add(&p_activ_item->list, &p_acct_item->items); 385 | ss_uuid_insert(&srvopt.uuid_tree, p_activ_item); 386 | 387 | p_activ_item->bev_daemon = bev; 388 | 389 | st_d_print("创建会话OK: %s", SD_ID128_CONST_STR(p_head->mach_uuid)); 390 | sc_send_head_cmd(bev, p_head, HD_CMD_OK, USR_DAEMON, p_head->extra_param); 391 | 392 | /** 393 | * 这里重新进行一个callback绑定,为的是设定callback的参数 394 | */ 395 | bufferevent_setcb(bev, main_bufferread_cb, NULL, main_bufferevent_cb, p_activ_item); 396 | bufferevent_enable(bev, EV_READ|EV_WRITE); 397 | 398 | json_object_put(new_obj); 399 | return RET_YES; 400 | } 401 | 402 | error_ret: 403 | json_object_put(new_obj); 404 | return RET_NO; 405 | } 406 | 407 | 408 | static RET_T ss_main_handle_ctl(struct bufferevent *bev, 409 | P_CTL_HEAD p_head) 410 | { 411 | P_THREAD_OBJ p_threadobj = NULL; 412 | P_ACTIV_ITEM p_activ_item = NULL; 413 | P_TRANS_ITEM p_trans = NULL; 414 | 415 | p_activ_item = ss_uuid_search(&srvopt.uuid_tree, p_head->mach_uuid); 416 | 417 | assert(p_head->cmd == HD_CMD_CONN); 418 | 419 | if (!p_activ_item) 420 | { 421 | st_d_print("会话 %s 不存在!", SD_ID128_CONST_STR(p_head->mach_uuid)); 422 | goto error_ret; 423 | } 424 | 425 | if (p_head->cmd == HD_CMD_CONN) 426 | { 427 | /** 428 | * 从main中删除event侦听,添加到线程池中 429 | */ 430 | st_d_print("从main中删除bufferevent事件!"); 431 | bufferevent_free(bev); 432 | 433 | p_trans = NULL; 434 | 435 | if (p_head->direct == USR_DAEMON) //寻找空余trans 436 | { 437 | p_trans = ss_create_trans(p_activ_item, p_head->extra_param); 438 | 439 | if (!p_trans) 440 | { 441 | st_d_error("TRANS队列已满!"); 442 | return RET_NO; 443 | } 444 | 445 | p_trans->is_enc = 0; 446 | p_trans->p_activ_item = p_activ_item; 447 | p_trans->usr_lport = p_head->extra_param; 448 | 449 | /** 450 | * 转发包到DAEMON,促发另外一边的连接 451 | */ 452 | st_d_print("触发DAEMON端事件!"); 453 | bufferevent_write(p_activ_item->bev_daemon, p_head, CTL_HEAD_LEN); 454 | 455 | } 456 | else 457 | { 458 | p_trans = ss_find_trans(p_activ_item, p_head->extra_param); 459 | 460 | if (!p_trans) 461 | { 462 | st_d_error("TRANS->%d未找到!", p_head->extra_param); 463 | return RET_NO; 464 | } 465 | } 466 | 467 | } 468 | 469 | P_C_ITEM p_c = (P_C_ITEM)calloc(sizeof(C_ITEM), 1); 470 | if (!p_c) 471 | { 472 | st_d_error("申请内存[%d]失败!", sizeof(C_ITEM)); 473 | goto error_ret; 474 | } 475 | 476 | p_threadobj = ss_get_threadobj(p_head->extra_param); 477 | 478 | p_c->socket = bufferevent_getfd(bev); 479 | p_c->arg.ptr = p_trans; 480 | 481 | slist_add(&p_c->list, &p_threadobj->conn_queue); 482 | 483 | if (p_head->direct == USR_DAEMON) 484 | write(p_threadobj->notify_send_fd, "U", 1); 485 | else 486 | write(p_threadobj->notify_send_fd, "D", 1); 487 | 488 | st_d_print("已将%d CONN %s加入线程[%lu]处理队列!", p_trans->usr_lport, 489 | SD_ID128_CONST_STR(p_activ_item->mach_uuid), p_threadobj->thread_id); 490 | 491 | return RET_YES; 492 | 493 | error_ret: 494 | return RET_NO; 495 | } 496 | 497 | 498 | static RET_T ss_main_handle_ss5(struct bufferevent *bev, 499 | P_CTL_HEAD p_head, void* dat) 500 | { 501 | P_ACTIV_ITEM p_activ_item = NULL; 502 | P_TRANS_ITEM p_trans = NULL; 503 | char dec_buf [4096]; 504 | 505 | if (p_head->cmd != HD_CMD_SS5 || !dat || p_head->direct == USR_DAEMON) 506 | { 507 | st_d_error("参数检查错误!"); 508 | return RET_NO; 509 | } 510 | 511 | /*服务器私钥解密数据*/ 512 | memset(dec_buf, 0, sizeof(dec_buf)); 513 | int len = RSA_private_decrypt(p_head->dat_len, dat, dec_buf, 514 | srvopt.p_prikey, RSA_PKCS1_PADDING); 515 | if (len < 0 ) 516 | { 517 | st_d_error("服务端私钥解密数据%d出错!", len); 518 | return RET_NO; 519 | } 520 | 521 | // 解密后的数据肯定比加密的要短 522 | memcpy(dat, dec_buf, p_head->dat_len); 523 | 524 | p_activ_item = ss_uuid_search(&srvopt.uuid_tree, p_head->mach_uuid); 525 | if (!p_activ_item) 526 | { 527 | st_d_print("会话 %s 不存在!", SD_ID128_CONST_STR(p_head->mach_uuid)); 528 | return RET_NO; 529 | } 530 | 531 | p_trans = ss_create_trans(p_activ_item, p_head->extra_param); 532 | 533 | if (!p_trans) 534 | { 535 | st_d_error("TRANS队列已满!"); 536 | return RET_NO; 537 | } 538 | 539 | p_trans->is_enc = 1; 540 | p_trans->p_activ_item = p_activ_item; 541 | p_trans->usr_lport = p_head->extra_param; 542 | p_trans->bev_d = bev; // ATTENTION: should be freeed later! 543 | p_trans->bev_u = NULL; 544 | p_trans->dat = dat; 545 | 546 | P_C_ITEM p_c = (P_C_ITEM)calloc(sizeof(C_ITEM), 1); 547 | if (!p_c) 548 | { 549 | st_d_error("申请内存[%d]失败!", sizeof(C_ITEM)); 550 | return RET_NO; 551 | } 552 | 553 | /** 554 | * 从main中删除event侦听,添加到线程池中 555 | */ 556 | bufferevent_free(bev); 557 | 558 | p_c->socket = bufferevent_getfd(bev); 559 | p_c->arg.ptr = (void*) p_trans; 560 | P_THREAD_OBJ p_threadobj = ss_get_threadobj(p_head->extra_param); 561 | slist_add(&p_c->list, &p_threadobj->conn_queue); 562 | 563 | write(p_threadobj->notify_send_fd, "S", 1); 564 | 565 | st_d_print("已将SS:%d CONN %s加入线程[%lu]处理队列!", p_trans->usr_lport, 566 | SD_ID128_CONST_STR(p_activ_item->mach_uuid), p_threadobj->thread_id); 567 | 568 | return RET_YES; 569 | } 570 | 571 | 572 | static RET_T ss_main_handle_dns(struct bufferevent *bev, 573 | P_CTL_HEAD p_head, void* dat) 574 | { 575 | P_ACTIV_ITEM p_activ_item = NULL; 576 | P_TRANS_ITEM p_trans = NULL; 577 | char dec_buf [4096]; 578 | 579 | if (p_head->cmd != HD_CMD_DNS || !dat || p_head->direct == USR_DAEMON) 580 | { 581 | st_d_error("参数检查错误!"); 582 | return RET_NO; 583 | } 584 | 585 | /*服务器私钥解密数据*/ 586 | memset(dec_buf, 0, sizeof(dec_buf)); 587 | int len = RSA_private_decrypt(p_head->dat_len, dat, dec_buf, 588 | srvopt.p_prikey, RSA_PKCS1_PADDING); 589 | if (len < 0 ) 590 | { 591 | st_d_error("服务端私钥解密数据%d出错!", len); 592 | return RET_NO; 593 | } 594 | 595 | // 解密后的数据肯定比加密的要短 596 | memcpy(dat, dec_buf, p_head->dat_len); 597 | 598 | p_activ_item = ss_uuid_search(&srvopt.uuid_tree, p_head->mach_uuid); 599 | if (!p_activ_item) 600 | { 601 | st_d_print("会话 %s 不存在!", SD_ID128_CONST_STR(p_head->mach_uuid)); 602 | return RET_NO; 603 | } 604 | 605 | p_trans = ss_create_trans(p_activ_item, p_head->extra_param); 606 | 607 | if (!p_trans) 608 | { 609 | st_d_error("TRANS队列已满!"); 610 | return RET_NO; 611 | } 612 | 613 | p_trans->is_enc = 1; 614 | p_trans->p_activ_item = p_activ_item; 615 | p_trans->usr_lport = p_head->extra_param; 616 | p_trans->bev_d = bev; // ATTENTION: should be freeed later! 617 | p_trans->bev_u = NULL; 618 | p_trans->dat = dat; 619 | 620 | P_C_ITEM p_c = (P_C_ITEM)calloc(sizeof(C_ITEM), 1); 621 | if (!p_c) 622 | { 623 | st_d_error("申请内存[%d]失败!", sizeof(C_ITEM)); 624 | return RET_NO; 625 | } 626 | 627 | /** 628 | * 从main中删除event侦听,添加到线程池中 629 | */ 630 | bufferevent_free(bev); 631 | 632 | p_c->socket = bufferevent_getfd(bev); 633 | p_c->arg.ptr = (void*) p_trans; 634 | P_THREAD_OBJ p_threadobj = ss_get_threadobj(p_head->extra_param); 635 | slist_add(&p_c->list, &p_threadobj->conn_queue); 636 | 637 | write(p_threadobj->notify_send_fd, "N", 1); 638 | 639 | st_d_print("已将DNS:%d CONN %s加入线程[%lu]处理队列!", p_trans->usr_lport, 640 | SD_ID128_CONST_STR(p_activ_item->mach_uuid), p_threadobj->thread_id); 641 | 642 | return RET_YES; 643 | } 644 | 645 | 646 | -------------------------------------------------------------------------------- /server/source/sshinner_s_threads.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include 6 | #include 7 | 8 | #include 9 | 10 | #include "sshinner_s.h" 11 | 12 | 13 | /* 14 | * Number of worker threads that have finished setting themselves up. 15 | */ 16 | static int init_count = 0; 17 | static pthread_mutex_t init_lock; 18 | static pthread_cond_t init_cond; 19 | 20 | 21 | 22 | void dns_remote_cb(evutil_socket_t socket_fd, short ev_flags, void * ptr) 23 | { 24 | P_TRANS_ITEM p_trans = (P_TRANS_ITEM)ptr; 25 | ENC_FRAME from_f; 26 | ENC_FRAME to_f; 27 | 28 | int nread = recvfrom(socket_fd, 29 | (void *)from_f.dat, sizeof(from_f.dat), 0, NULL, NULL); 30 | 31 | if (nread > 0) 32 | { 33 | from_f.len = nread; 34 | encrypt(&p_trans->ctx_enc, &from_f, &to_f); 35 | bufferevent_write(p_trans->bev_d, to_f.dat, to_f.len); 36 | } 37 | } 38 | 39 | void thread_bufferevent_cb(struct bufferevent *bev, short events, void *ptr) 40 | { 41 | P_TRANS_ITEM p_trans = (P_TRANS_ITEM)ptr; 42 | 43 | struct event_base *base = bufferevent_get_base(bev); 44 | int loop_terminate_flag = 0; 45 | 46 | //只有使用bufferevent_socket_connect进行的连接才会得到CONNECTED的事件 47 | if (events & BEV_EVENT_CONNECTED) 48 | { 49 | st_d_print("GOT BEV_EVENT_CONNECTED event! "); 50 | } 51 | else if (events & BEV_EVENT_ERROR) 52 | { 53 | st_d_error("GOT BEV_EVENT_ERROR event[%d]! ", p_trans->usr_lport); 54 | 55 | ss_free_trans(p_trans->p_activ_item, p_trans); 56 | } 57 | else if (events & BEV_EVENT_EOF) 58 | { 59 | st_d_print("GOT BEV_EVENT_EOF event[%d]! ", p_trans->usr_lport); 60 | 61 | // 实际传输端结束,那么只针对这个传输,把对端的连接断开, 62 | // 由于TCP连接,那么对端的be_usr_srv和be_daemon_srv也会收到BEV_EVENT_EOF消息 63 | ss_free_trans(p_trans->p_activ_item, p_trans); 64 | 65 | } 66 | else if (events & BEV_EVENT_TIMEOUT) 67 | { 68 | st_d_print("GOT BEV_EVENT_TIMEOUT event[%d]! ", p_trans->usr_lport); 69 | 70 | ss_free_trans(p_trans->p_activ_item, p_trans); 71 | } 72 | 73 | if (loop_terminate_flag) 74 | { 75 | bufferevent_free(bev); 76 | event_base_loopexit(base, NULL); 77 | } 78 | 79 | return; 80 | } 81 | 82 | 83 | /** 84 | * 读取事件,主要进行数据转发 85 | * 86 | * 这里命令字段和数据字段分开处理,命令是自己解析,而数据需要转发,需要 87 | * 为数据流程进行优化 88 | */ 89 | void thread_bufferread_cb(struct bufferevent *bev, void *ptr) 90 | { 91 | P_TRANS_ITEM p_trans = (P_TRANS_ITEM)ptr; 92 | 93 | struct evbuffer *input = bufferevent_get_input(bev); 94 | struct evbuffer *output = bufferevent_get_output(bev); 95 | 96 | if (bev == p_trans->bev_u && p_trans->bev_d) 97 | { 98 | //st_d_print("转发数据包USR->DAEMON"); 99 | bufferevent_write_buffer(p_trans->bev_d, bufferevent_get_input(bev)); 100 | } 101 | else if (bev == p_trans->bev_d && p_trans->bev_u) 102 | { 103 | //st_d_print("转发数据包DAEMON->USR"); 104 | bufferevent_write_buffer(p_trans->bev_u, bufferevent_get_input(bev)); 105 | } 106 | else 107 | { 108 | SYS_ABORT("WRRRRRR!"); 109 | } 110 | 111 | return; 112 | } 113 | 114 | void thread_bufferread_cb_enc(struct bufferevent *bev, void *ptr) 115 | { 116 | P_TRANS_ITEM p_trans = (P_TRANS_ITEM)ptr; 117 | 118 | ENC_FRAME from_f; 119 | ENC_FRAME to_f; 120 | 121 | struct evbuffer *input = bufferevent_get_input(bev); 122 | struct evbuffer *output = bufferevent_get_output(bev); 123 | 124 | if (bev == p_trans->bev_u && p_trans->bev_d) 125 | { 126 | //st_d_print("加密转发数据包USR->REMOTE"); // 解密 127 | 128 | from_f.len = bufferevent_read(p_trans->bev_u, from_f.dat, FRAME_SIZE); 129 | if (from_f.len > 0) 130 | { 131 | decrypt(&p_trans->ctx_dec, &from_f, &to_f); 132 | bufferevent_write(p_trans->bev_d, to_f.dat, from_f.len); 133 | } 134 | else 135 | { 136 | st_d_error("读取数据出错!"); 137 | } 138 | 139 | } 140 | else if (bev == p_trans->bev_d && p_trans->bev_u) 141 | { 142 | //st_d_print("加密转发数据包REMOTE->USR"); // 加密 143 | 144 | from_f.len = bufferevent_read(p_trans->bev_d, from_f.dat, FRAME_SIZE); 145 | if (from_f.len > 0) 146 | { 147 | encrypt(&p_trans->ctx_enc, &from_f, &to_f); 148 | bufferevent_write(p_trans->bev_u, to_f.dat, to_f.len); 149 | } 150 | else 151 | { 152 | st_d_error("读取数据出错!"); 153 | } 154 | } 155 | else 156 | { 157 | SYS_ABORT("WRRRRRR!"); 158 | } 159 | 160 | return; 161 | } 162 | 163 | 164 | void thread_bufferread_cb_dns_enc(struct bufferevent *bev, void *ptr) 165 | { 166 | P_TRANS_ITEM p_trans = (P_TRANS_ITEM)ptr; 167 | 168 | ENC_FRAME from_f; 169 | ENC_FRAME to_f; 170 | 171 | struct evbuffer *input = bufferevent_get_input(bev); 172 | struct evbuffer *output = bufferevent_get_output(bev); 173 | 174 | if (bev == p_trans->bev_d && ! p_trans->bev_u) 175 | { 176 | //st_d_print("加密转发数据包USR->REMOTE"); // 解密 177 | 178 | from_f.len = bufferevent_read(p_trans->bev_d, from_f.dat, FRAME_SIZE); 179 | if (from_f.len > 0) 180 | { 181 | decrypt(&p_trans->ctx_dec, &from_f, &to_f); 182 | 183 | // 把请求转发给远程的nameserver 184 | if (!p_trans->extra_ev) 185 | { 186 | int dns_socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); 187 | if (dns_socket < 0 ) 188 | { 189 | st_d_error("Create DNS socket error!"); 190 | return; 191 | } 192 | 193 | evutil_make_socket_closeonexec(dns_socket); 194 | evutil_make_socket_nonblocking(dns_socket); 195 | unsigned int optval = 1; 196 | setsockopt(dns_socket, IPPROTO_TCP, TCP_NODELAY, &optval, sizeof(optval));//禁用NAGLE算法 197 | 198 | p_trans->extra_ev = event_new(bufferevent_get_base(bev), 199 | dns_socket, EV_READ | EV_PERSIST, dns_remote_cb, p_trans); 200 | event_add(p_trans->extra_ev, NULL); 201 | } 202 | 203 | struct sockaddr_in sin; 204 | memset(&sin, 0, sizeof(sin)); 205 | sin.sin_family = AF_INET; 206 | sin.sin_addr.s_addr = inet_addr("8.8.8.8"); 207 | sin.sin_port = htons(53); /* Port Num */ 208 | 209 | sendto(event_get_fd(p_trans->extra_ev), 210 | to_f.dat, to_f.len, 0, (struct sockaddr *)&sin, sizeof(sin)); 211 | } 212 | else 213 | { 214 | st_d_error("读取数据出错!"); 215 | } 216 | 217 | } 218 | 219 | return; 220 | } 221 | 222 | static void *thread_run(void *arg); 223 | static void thread_process(int fd, short which, void *arg); 224 | 225 | static void wait_for_thread_registration(int nthreads) 226 | { 227 | while (init_count < nthreads) { 228 | pthread_cond_wait(&init_cond, &init_lock); 229 | } 230 | } 231 | 232 | static void register_thread_initialized(void) 233 | { 234 | pthread_mutex_lock(&init_lock); 235 | init_count++; 236 | st_d_print("线程数目[%d]OK!", init_count); 237 | pthread_cond_signal(&init_cond); 238 | pthread_mutex_unlock(&init_lock); 239 | } 240 | 241 | extern RET_T ss_create_worker_threads(size_t thread_num, P_THREAD_OBJ threads) 242 | { 243 | int i = 0; 244 | 245 | pthread_attr_t attr; 246 | int ret = 0; 247 | 248 | pthread_mutex_init(&init_lock, NULL); 249 | pthread_cond_init(&init_cond, NULL); 250 | 251 | for (i=0; i < thread_num; ++i) 252 | { 253 | int fds[2]; 254 | if (pipe(fds)) { 255 | SYS_ABORT("Can't create notify pipe"); 256 | } 257 | 258 | threads[i].notify_receive_fd = fds[0]; 259 | threads[i].notify_send_fd = fds[1]; 260 | 261 | threads[i].base = event_init(); 262 | if (! threads[i].base ){ 263 | SYS_ABORT("Can't allocate event base"); 264 | } 265 | threads[i].p_notify_event = event_new(threads[i].base, threads[i].notify_receive_fd, 266 | EV_READ | EV_PERSIST, thread_process, &threads[i]); 267 | 268 | if (! threads[i].p_notify_event ){ 269 | SYS_ABORT("Can't allocate new event"); 270 | } 271 | 272 | if (event_add(threads[i].p_notify_event, 0) == -1) { 273 | SYS_ABORT("Can't monitor libevent notify pipe"); 274 | } 275 | 276 | slist_init(&threads[i].conn_queue); 277 | pthread_mutex_init(&threads[i].q_lock, NULL); 278 | 279 | pthread_attr_init(&attr); 280 | if ((ret = pthread_create(&threads[i].thread_id, &attr, thread_run, (void*)(&threads[i]))) != 0) 281 | { 282 | SYS_ABORT("Cannot create worker thread %s", strerror(ret)); 283 | } 284 | } 285 | 286 | 287 | pthread_mutex_lock(&init_lock); 288 | wait_for_thread_registration(thread_num); 289 | pthread_mutex_unlock(&init_lock); 290 | 291 | } 292 | 293 | static void *thread_run(void *arg) 294 | { 295 | P_THREAD_OBJ me = (P_THREAD_OBJ)arg; 296 | 297 | register_thread_initialized(); 298 | 299 | event_base_loop(me->base, 0); 300 | 301 | return NULL; 302 | } 303 | 304 | 305 | /* 306 | * Processes an incoming "handle a new connection" item. This is called when 307 | * input arrives on the libevent wakeup pipe. 308 | */ 309 | 310 | /** 311 | * 这里有一个竞争条件:如果这里不能建立libevent连接,或者发送HD_CMD_SS5_ACT之前就收到了 312 | * EOF的事件,那么客户端就会存在一个僵尸的trans连接,客户端目前是单线程的,必须消除这种 313 | * 消耗 314 | * 315 | * 目前想到的处理方式就是,在拆除trans的同时,额外的向客户端主通道发送一个命令 316 | */ 317 | static void thread_process(int fd, short which, void *arg) 318 | { 319 | P_THREAD_OBJ p_threadobj = (P_THREAD_OBJ)arg; 320 | P_TRANS_ITEM p_trans = NULL; 321 | P_SLIST_HEAD p_list = NULL; 322 | P_C_ITEM p_c_item = NULL; 323 | struct bufferevent *new_bev = NULL; 324 | struct bufferevent *new_ext_bev = NULL; 325 | char buf[1]; 326 | CTL_HEAD head; 327 | 328 | if (read(fd, buf, 1) != 1) 329 | { 330 | st_d_error("Can't read from libevent pipe\n"); 331 | return; 332 | } 333 | 334 | switch (buf[0]) 335 | { 336 | case 'D': // DAEMON->USR 337 | p_list = slist_fetch(&p_threadobj->conn_queue); 338 | if (!p_list) 339 | { 340 | st_d_error("无法从任务队列中获取任务!"); 341 | return; 342 | } 343 | 344 | p_c_item = list_entry(p_list, C_ITEM, list); 345 | p_trans = (P_TRANS_ITEM)p_c_item->arg.ptr; 346 | 347 | new_bev = 348 | bufferevent_socket_new(p_threadobj->base, p_c_item->socket, BEV_OPT_CLOSE_ON_FREE); 349 | bufferevent_setcb(new_bev, thread_bufferread_cb, NULL, thread_bufferevent_cb, p_trans); 350 | 351 | p_trans->bev_d = new_bev; 352 | free(p_c_item); 353 | 354 | if (p_trans->bev_u == NULL || p_trans->usr_lport == 0 || p_trans->p_activ_item == NULL) 355 | { 356 | SYS_ABORT("USR SIDE SHOULD BE OK ALREAY!!!"); 357 | } 358 | 359 | st_d_print("WORKTHREAD-> DAEMON_USR(%d) OK!", p_trans->usr_lport); 360 | st_d_print("DDDDD: 当前活动连接数:[[[ %d ]]],任务队列:[[ %d ]]", 361 | slist_count(&p_trans->p_activ_item->trans), slist_count(&p_threadobj->conn_queue)); 362 | 363 | st_d_print("激活客户端Bufferevent使能!"); 364 | memset(&head, 0, CTL_HEAD_LEN); 365 | head.direct = USR_DAEMON; 366 | head.cmd = HD_CMD_CONN_ACT; 367 | head.extra_param = p_trans->usr_lport; 368 | head.mach_uuid = p_trans->p_activ_item->mach_uuid; 369 | bufferevent_write(p_trans->p_activ_item->bev_daemon, &head, CTL_HEAD_LEN); 370 | head.direct = DAEMON_USR; 371 | bufferevent_write(p_trans->p_activ_item->bev_usr, &head, CTL_HEAD_LEN); 372 | 373 | // never too late to enable it! 374 | bufferevent_enable(new_bev, EV_READ|EV_WRITE); 375 | break; 376 | 377 | case 'U': //USR->DAEMON 378 | p_list = slist_fetch(&p_threadobj->conn_queue); 379 | if (!p_list) 380 | { 381 | st_d_error("无法从任务队列中获取任务!"); 382 | return; 383 | } 384 | 385 | p_c_item = list_entry(p_list, C_ITEM, list); 386 | p_trans = (P_TRANS_ITEM)p_c_item->arg.ptr; 387 | 388 | new_bev = 389 | bufferevent_socket_new(p_threadobj->base, p_c_item->socket, BEV_OPT_CLOSE_ON_FREE); 390 | bufferevent_setcb(new_bev, thread_bufferread_cb, NULL, thread_bufferevent_cb, p_trans); 391 | bufferevent_enable(new_bev, EV_READ|EV_WRITE); 392 | 393 | p_trans->bev_u = new_bev; 394 | free(p_c_item); 395 | 396 | st_d_print("WORKTHREAD-> USR_DAEMON(%d) OK!", p_trans->usr_lport); 397 | 398 | break; 399 | 400 | case 'S': // DAEMON->USR 401 | p_list = slist_fetch(&p_threadobj->conn_queue); 402 | if (!p_list) 403 | { 404 | st_d_error("无法从任务队列中获取任务!"); 405 | return; 406 | } 407 | p_c_item = list_entry(p_list, C_ITEM, list); 408 | p_trans = (P_TRANS_ITEM)p_c_item->arg.ptr; 409 | 410 | assert(p_trans->is_enc); 411 | assert(p_trans->dat); 412 | 413 | encrypt_ctx_init(&p_trans->ctx_enc, p_trans->usr_lport, p_trans->p_activ_item->enc_key, 1); 414 | encrypt_ctx_init(&p_trans->ctx_dec, p_trans->usr_lport, p_trans->p_activ_item->enc_key, 0); 415 | 416 | int remote_socket = 0; 417 | char* buf = (char *)p_trans->dat; 418 | 419 | if (buf[3] == 0x01) 420 | { 421 | struct sockaddr_in sin; 422 | memset(&sin, 0, sizeof(sin)); 423 | 424 | sin.sin_family = AF_INET; 425 | memcpy(&sin.sin_addr.s_addr, &buf[4], 4); 426 | memcpy(&sin.sin_port, &buf[4+4], 2); 427 | free(p_trans->dat); 428 | 429 | st_d_print("REQUEST: %s:%d", inet_ntoa(sin.sin_addr), ntohs(sin.sin_port)); 430 | 431 | remote_socket = ss_connect_srv(&sin); 432 | if (remote_socket == -1) 433 | { 434 | close(p_c_item->socket); 435 | free(p_c_item); 436 | st_d_error("CONNECT ERROR!"); 437 | return; 438 | } 439 | } 440 | else 441 | { 442 | char remote_addr[128]; 443 | unsigned short remote_port = 0; 444 | memset(remote_addr, 0, sizeof(remote_addr)); 445 | strncpy(remote_addr, &buf[4+1], buf[4]); 446 | memcpy(&remote_port, &buf[4+1+buf[4]], 2); 447 | free(p_trans->dat); 448 | 449 | P_DNS_STRUCT p_dns = (P_DNS_STRUCT)calloc(sizeof(DNS_STRUCT), 1); 450 | if (!p_dns) 451 | { 452 | st_d_error("申请内存失败:%d", sizeof(DNS_STRUCT)); 453 | close(p_c_item->socket); 454 | free(p_c_item); 455 | return; 456 | } 457 | 458 | st_d_print("REQUEST: %s:%d", remote_addr, ntohs(remote_port)); 459 | 460 | strncpy(p_dns->hostname, remote_addr, sizeof(p_dns->hostname)); 461 | p_dns->port = remote_port; 462 | p_dns->p_c_item = p_c_item; 463 | p_dns->p_threadobj = p_threadobj; 464 | p_dns->p_trans = p_trans; 465 | 466 | struct evutil_addrinfo hints; 467 | struct evdns_getaddrinfo_request *req; 468 | memset(&hints, 0, sizeof(hints)); 469 | hints.ai_family = AF_INET; 470 | hints.ai_flags = EVUTIL_AI_CANONNAME; 471 | /* Unless we specify a socktype, we'll get at least two entries for 472 | * each address: one for TCP and one for UDP. That's not what we 473 | * want. */ 474 | hints.ai_socktype = SOCK_STREAM; 475 | hints.ai_protocol = IPPROTO_TCP; 476 | 477 | 478 | req = evdns_getaddrinfo( 479 | srvopt.evdns_base, remote_addr, NULL /* no service name given */, 480 | &hints, dns_query_cb, p_dns); 481 | if (req == NULL) { 482 | printf(" [request for %s returned immediately]\n", remote_addr); 483 | /* No need to free user_data or decrement n_pending_requests; that 484 | * happened in the callback. */ 485 | } 486 | 487 | return; 488 | } 489 | 490 | free(p_c_item); 491 | 492 | evutil_make_socket_nonblocking(p_c_item->socket); 493 | new_bev = 494 | bufferevent_socket_new(p_threadobj->base, p_c_item->socket, BEV_OPT_CLOSE_ON_FREE); 495 | assert(new_bev); 496 | bufferevent_setcb(new_bev, thread_bufferread_cb_enc, NULL, thread_bufferevent_cb, p_trans); 497 | 498 | evutil_make_socket_nonblocking(remote_socket); 499 | new_ext_bev = 500 | bufferevent_socket_new(p_threadobj->base, remote_socket , BEV_OPT_CLOSE_ON_FREE); 501 | assert(new_ext_bev); 502 | bufferevent_setcb(new_ext_bev, thread_bufferread_cb_enc, NULL, thread_bufferevent_cb, p_trans); 503 | 504 | p_trans->bev_d = new_bev; 505 | p_trans->bev_u = new_ext_bev; 506 | 507 | st_d_print("DDDDD: 当前活动连接数:[[[ %d ]]], 任务队列:[[ %d ]]", 508 | slist_count(&p_trans->p_activ_item->trans), slist_count(&p_threadobj->conn_queue)); 509 | 510 | st_d_print("SS5激活客户端Bufferevent使能!"); 511 | memset(&head, 0, CTL_HEAD_LEN); 512 | head.direct = USR_DAEMON; 513 | head.cmd = HD_CMD_SS5_ACT; 514 | head.extra_param = p_trans->usr_lport; 515 | head.mach_uuid = p_trans->p_activ_item->mach_uuid; 516 | 517 | assert(p_trans->p_activ_item->bev_daemon); 518 | bufferevent_write(p_trans->p_activ_item->bev_daemon, &head, CTL_HEAD_LEN); 519 | 520 | // never too late to enable it! 521 | bufferevent_enable(new_bev, EV_READ|EV_WRITE); 522 | bufferevent_enable(new_ext_bev, EV_READ|EV_WRITE); 523 | break; 524 | 525 | case 'N': // DAEMON->USR 526 | p_list = slist_fetch(&p_threadobj->conn_queue); 527 | if (!p_list) 528 | { 529 | st_d_error("无法从任务队列中获取任务!"); 530 | return; 531 | } 532 | p_c_item = list_entry(p_list, C_ITEM, list); 533 | p_trans = (P_TRANS_ITEM)p_c_item->arg.ptr; 534 | 535 | assert(p_trans->is_enc); 536 | assert(p_trans->dat); 537 | 538 | encrypt_ctx_init(&p_trans->ctx_enc, p_trans->usr_lport, p_trans->p_activ_item->enc_key, 1); 539 | encrypt_ctx_init(&p_trans->ctx_dec, p_trans->usr_lport, p_trans->p_activ_item->enc_key, 0); 540 | 541 | 542 | free(p_c_item); 543 | 544 | evutil_make_socket_nonblocking(p_c_item->socket); 545 | new_bev = 546 | bufferevent_socket_new(p_threadobj->base, p_c_item->socket, BEV_OPT_CLOSE_ON_FREE); 547 | assert(new_bev); 548 | bufferevent_setcb(new_bev, thread_bufferread_cb_dns_enc, NULL, thread_bufferevent_cb, p_trans); 549 | 550 | 551 | p_trans->bev_d = new_bev; 552 | p_trans->bev_u = NULL; 553 | 554 | st_d_print("DDDDD: 当前活动连接数:[[[ %d ]]], 任务队列:[[ %d ]]", 555 | slist_count(&p_trans->p_activ_item->trans), slist_count(&p_threadobj->conn_queue)); 556 | 557 | 558 | // never too late to enable it! 559 | bufferevent_enable(new_bev, EV_READ|EV_WRITE); 560 | 561 | st_d_print("DNS激活客户端Bufferevent使能!"); 562 | memset(&head, 0, CTL_HEAD_LEN); 563 | head.direct = USR_DAEMON; 564 | head.cmd = HD_CMD_DNS_ACT; 565 | head.extra_param = p_trans->usr_lport; 566 | head.mach_uuid = p_trans->p_activ_item->mach_uuid; 567 | 568 | assert(p_trans->p_activ_item->bev_daemon); 569 | bufferevent_write(p_trans->p_activ_item->bev_daemon, &head, CTL_HEAD_LEN); 570 | 571 | break; 572 | 573 | default: 574 | SYS_ABORT("WHAT DO I GET: %c", buf[0]); 575 | break; 576 | } 577 | 578 | return; 579 | } 580 | 581 | void dns_query_cb(int errcode, struct evutil_addrinfo *addr, void *ptr) 582 | { 583 | P_DNS_STRUCT p_dns = (P_DNS_STRUCT)ptr; 584 | 585 | if (errcode) 586 | { 587 | printf("DNS Query error for: %s -> %s\n", p_dns->hostname, evutil_gai_strerror(errcode)); 588 | } 589 | else 590 | { 591 | struct evutil_addrinfo *ai; 592 | struct sockaddr_in sin; 593 | 594 | for (ai = addr; ai; ai = ai->ai_next) 595 | { 596 | if (ai->ai_family == AF_INET) 597 | { 598 | memset(&sin, 0, sizeof(sin)); 599 | sin.sin_family = AF_INET; 600 | sin.sin_addr = ((struct sockaddr_in *)ai->ai_addr)->sin_addr; 601 | sin.sin_port = p_dns->port; 602 | 603 | st_d_print("REQUEST: %s:%d", inet_ntoa(sin.sin_addr), ntohs(sin.sin_port)); 604 | 605 | int remote_socket = ss_connect_srv(&sin); 606 | if (remote_socket == -1) 607 | { 608 | st_d_error("REQUEST: %s:%d FAILED!", inet_ntoa(sin.sin_addr), ntohs(sin.sin_port)); 609 | continue; 610 | } 611 | 612 | evutil_make_socket_nonblocking(p_dns->p_c_item->socket); 613 | struct bufferevent *new_bev = 614 | bufferevent_socket_new(p_dns->p_threadobj->base, p_dns->p_c_item->socket, BEV_OPT_CLOSE_ON_FREE); 615 | assert(new_bev); 616 | bufferevent_setcb(new_bev, thread_bufferread_cb_enc, NULL, thread_bufferevent_cb, p_dns->p_trans); 617 | 618 | evutil_make_socket_nonblocking(remote_socket); 619 | struct bufferevent *new_ext_bev = 620 | bufferevent_socket_new(p_dns->p_threadobj->base, remote_socket , BEV_OPT_CLOSE_ON_FREE); 621 | assert(new_ext_bev); 622 | bufferevent_setcb(new_ext_bev, thread_bufferread_cb_enc, NULL, thread_bufferevent_cb, p_dns->p_trans); 623 | 624 | p_dns->p_trans->bev_d = new_bev; 625 | p_dns->p_trans->bev_u = new_ext_bev; 626 | 627 | st_d_print("DDDDD: 当前活动连接数:[[[ %d ]]], 任务队列:[[ %d ]]", 628 | slist_count(&p_dns->p_trans->p_activ_item->trans), 629 | slist_count(&p_dns->p_threadobj->conn_queue)); 630 | 631 | 632 | CTL_HEAD head; 633 | memset(&head, 0, CTL_HEAD_LEN); 634 | head.direct = USR_DAEMON; 635 | head.cmd = HD_CMD_SS5_ACT; 636 | head.extra_param = p_dns->p_trans->usr_lport; 637 | head.mach_uuid = p_dns->p_trans->p_activ_item->mach_uuid; 638 | 639 | assert(p_dns->p_trans->p_activ_item->bev_daemon); 640 | //bufferevent_write(p_dns->p_trans->p_activ_item->bev_daemon, &head, CTL_HEAD_LEN); 641 | write(bufferevent_getfd(p_dns->p_trans->p_activ_item->bev_daemon), &head, CTL_HEAD_LEN); 642 | 643 | st_d_print("SS5激活客户端Bufferevent使能 %d!", p_dns->p_trans->usr_lport); 644 | // never too late to enable it! 645 | bufferevent_enable(new_bev, EV_READ|EV_WRITE); 646 | bufferevent_enable(new_ext_bev, EV_READ|EV_WRITE); 647 | 648 | break; 649 | 650 | } 651 | 652 | st_d_print("ALL REQUEST FOR %s FAILED!", p_dns->hostname); 653 | 654 | } 655 | evutil_freeaddrinfo(addr); 656 | } 657 | 658 | free(p_dns->p_c_item); 659 | free(p_dns); 660 | 661 | return; 662 | } 663 | 664 | 665 | /** 666 | * 667 | * 用主管道命令的方式,发送结束TRANS信息 668 | * 多次调用该命令是无害的,因为客户端检测不到对应的trans就忽略之 669 | */ 670 | void ss_cmd_end_trans(P_TRANS_ITEM p_trans) 671 | { 672 | if (!p_trans || !p_trans->p_activ_item || !p_trans->p_activ_item->bev_daemon) 673 | { 674 | SYS_ABORT("NOT SUITE FOR SEND CMD!!!"); 675 | } 676 | 677 | CTL_HEAD head; 678 | memset(&head, 0, CTL_HEAD_LEN); 679 | 680 | head.direct = USR_DAEMON; 681 | head.cmd = HD_CMD_END_TRANS; 682 | head.extra_param = p_trans->usr_lport; 683 | head.mach_uuid = p_trans->p_activ_item->mach_uuid; 684 | 685 | assert(p_trans->p_activ_item->bev_daemon); 686 | bufferevent_write(p_trans->p_activ_item->bev_daemon, &head, CTL_HEAD_LEN); 687 | 688 | return; 689 | } 690 | 691 | -------------------------------------------------------------------------------- /server/source/sshinner_s_utils.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include /* See NOTES */ 6 | #include 7 | 8 | #include 9 | 10 | #include 11 | #include 12 | 13 | #include "sshinner_s.h" 14 | 15 | extern RET_T json_fetch_and_copy(struct json_object *p_obj, const char* key, char* store, int max_len) 16 | { 17 | json_object *p_store_obj = NULL; 18 | 19 | if (!p_obj || !key || !strlen(key) || !store) 20 | return RET_NO; 21 | 22 | if (json_object_object_get_ex(p_obj, key, &p_store_obj) && 23 | json_object_get_string_len(p_store_obj)) 24 | { 25 | strncpy(store, json_object_get_string(p_store_obj), max_len); 26 | return RET_YES; 27 | } 28 | 29 | return RET_NO; 30 | } 31 | 32 | extern RET_T load_settings_server(P_SRV_OPT p_opt) 33 | { 34 | json_object *p_obj = NULL; 35 | json_object *p_class = NULL; 36 | json_object *p_store_obj = NULL; 37 | 38 | if (!p_opt) 39 | return RET_NO; 40 | 41 | if( ! (p_obj = json_object_from_file("settings.json")) ) 42 | return RET_NO; 43 | 44 | if(json_object_object_get_ex(p_obj,"server",&p_class)) 45 | { 46 | st_d_print("handling server configuration...."); 47 | 48 | if (json_object_object_get_ex(p_class,"port",&p_store_obj)) 49 | p_opt->port = json_object_get_int(p_store_obj); 50 | 51 | if (json_object_object_get_ex(p_class,"thread_num",&p_store_obj)) 52 | p_opt->thread_num = json_object_get_int(p_store_obj); 53 | else 54 | p_opt->thread_num = 5; /*default*/ 55 | 56 | json_object_put(p_obj); 57 | return RET_YES; 58 | } 59 | 60 | json_object_put(p_obj); 61 | return RET_NO; 62 | } 63 | 64 | 65 | extern void dump_srv_opts(P_SRV_OPT p_opt) 66 | { 67 | if (!p_opt) 68 | return; 69 | 70 | st_d_print("PORT:%d", p_opt->port); 71 | 72 | return; 73 | } 74 | 75 | 76 | extern void ss_ret_cmd_ok(struct bufferevent *bev, 77 | sd_id128_t uuid, enum DIREC direct) 78 | { 79 | CTL_HEAD ret_head; 80 | memset(&ret_head, 0, CTL_HEAD_LEN); 81 | ret_head.mach_uuid = uuid; 82 | ret_head.cmd = HD_CMD_OK; 83 | ret_head.direct = direct; 84 | 85 | bufferevent_write(bev, &ret_head, CTL_HEAD_LEN); 86 | 87 | return; 88 | } 89 | 90 | extern void ss_ret_cmd_err(struct bufferevent *bev, 91 | sd_id128_t uuid, enum DIREC direct) 92 | { 93 | CTL_HEAD ret_head; 94 | memset(&ret_head, 0, CTL_HEAD_LEN); 95 | ret_head.mach_uuid = uuid; 96 | ret_head.cmd = HD_CMD_ERROR; 97 | ret_head.direct = direct; 98 | 99 | bufferevent_write(bev, &ret_head, CTL_HEAD_LEN); 100 | 101 | return; 102 | } 103 | 104 | 105 | /** 106 | * 没有消息负载的发送 107 | */ 108 | RET_T sc_send_head_cmd(struct bufferevent *bev, P_CTL_HEAD p_head, 109 | int cmd, enum DIREC direct, unsigned long extra_param) 110 | { 111 | CTL_HEAD head; 112 | memset(&head, 0, CTL_HEAD_LEN); 113 | 114 | if (bev == NULL) 115 | { 116 | st_d_error("bev == NULL"); 117 | return RET_NO; 118 | } 119 | 120 | head.direct = direct; 121 | head.cmd = cmd; 122 | head.extra_param = extra_param; 123 | head.mach_uuid = p_head->mach_uuid; 124 | head.usrport = p_head->usrport; 125 | head.daemonport = p_head->daemonport; 126 | 127 | bufferevent_write(bev, &head, CTL_HEAD_LEN); 128 | 129 | return RET_YES; 130 | } 131 | 132 | #if 0 133 | 134 | evutil_socket_t 135 | ss_get_tcp_socket_for_host(const char *hostname, ev_uint16_t port) 136 | { 137 | char port_buf[6]; 138 | struct evutil_addrinfo hints; 139 | struct evutil_addrinfo *answer = NULL; 140 | int err; 141 | evutil_socket_t sock; 142 | 143 | /* Convert the port to decimal. */ 144 | evutil_snprintf(port_buf, sizeof(port_buf), "%d", (int)port); 145 | 146 | /* Build the hints to tell getaddrinfo how to act. */ 147 | memset(&hints, 0, sizeof(hints)); 148 | hints.ai_family = AF_INET; /* v4 or v6 is fine. */ 149 | hints.ai_socktype = SOCK_STREAM; 150 | hints.ai_protocol = IPPROTO_TCP; /* We want a TCP socket */ 151 | /* Only return addresses we can use. */ 152 | hints.ai_flags = EVUTIL_AI_ADDRCONFIG; 153 | 154 | /* Look up the hostname. */ 155 | err = evutil_getaddrinfo(hostname, port_buf, &hints, &answer); 156 | if (err != 0) { 157 | st_d_error( "Error while resolving '%s': %s", 158 | hostname, evutil_gai_strerror(err)); 159 | return -1; 160 | } 161 | 162 | /* If there was no error, we should have at least one answer. */ 163 | assert(answer); 164 | /* Just use the first answer. */ 165 | sock = socket(answer->ai_family, 166 | answer->ai_socktype, 167 | answer->ai_protocol); 168 | if (sock < 0) 169 | return -1; 170 | if (connect(sock, answer->ai_addr, answer->ai_addrlen)) { 171 | /* Note that we're doing a blocking connect in this function. 172 | * If this were nonblocking, we'd need to treat some errors 173 | * (like EINTR and EAGAIN) specially. */ 174 | EVUTIL_CLOSESOCKET(sock); 175 | return -1; 176 | } 177 | 178 | return sock; 179 | } 180 | #endif 181 | 182 | int ss_connect_srv(struct sockaddr_in* sin) 183 | { 184 | int reuseaddr_on = 1; 185 | 186 | int sk_fd = socket(AF_INET, SOCK_STREAM, 0); 187 | if (sk_fd < 0) 188 | return -1; 189 | 190 | unsigned int optval = 1; 191 | setsockopt(sk_fd, IPPROTO_TCP, TCP_NODELAY, &optval, sizeof(optval));//禁用NAGLE算法 192 | 193 | if (setsockopt(sk_fd, SOL_SOCKET, SO_REUSEADDR, &reuseaddr_on, 194 | sizeof(reuseaddr_on)) == -1) 195 | { 196 | st_d_print("Reuse socket opt faile!\n"); 197 | return -1; 198 | } 199 | if (connect(sk_fd, (struct sockaddr *)sin, sizeof(struct sockaddr_in))) 200 | { 201 | st_d_error("Connect to server failed!\n"); 202 | close(sk_fd); 203 | return -1; 204 | } 205 | 206 | return sk_fd; 207 | } 208 | -------------------------------------------------------------------------------- /server/ssl/private.key: -------------------------------------------------------------------------------- 1 | -----BEGIN RSA PRIVATE KEY----- 2 | MIIEogIBAAKCAQEAyC/9iLFjrSc6Tvui2OyL5PLpTuPB+UVfmQKS4Jgv/ICwN/YT 3 | 086oTbXkR6wEBqFuuB8kN6Z73o8QMaaNZHNZmOEfuz4Rjkd991OvJcHAGt8cnrk1 4 | UVuSonh/puRGkjZRtkc23v0b5TthjAXNDgSGrHtTR+j0E4c6lg0mOTnG0oYmGgOb 5 | db1t3ZqDO+N4VaQ1CIPtH1V0JLXbveEkKYJxZ87yTAnBITikGyhLPUP6D8OMKSMu 6 | fsHwf1itpYGmS8o4n+OF0CfGMFSs1Av1JJZ1THrTLSE0/qYIlXc7kyFrOCPRK+F2 7 | bphbFUZu/VXoQYMbwwdy4kUw5OPCPJCnwCJS0wIDAQABAoIBAHuC+IeFAv3LbTNc 8 | GF6Em8+XfBFbfsuAXPo3101ROJIvCAqO/i65m6fOqNj7rcQ1h+178UmQo25ukExB 9 | +YzXiplDlONe6VAClhqp/C9sek1aCPt5RAc9W5x4gjIDN/NwJjwzdgxg1/w4Bfhx 10 | f9G9QyZaNMjyVt1RmvkHheTa2+v5FzKqEje7sBcvMX0kv2HCenzSMVN6LOkFD7ld 11 | njsBAUaW5CyMKIsAt2IMwdhU5IrNH/8z9/+/NNzcZJ34LgHgY5aVHhkZ9JTn9d8C 12 | Na5jnd+m9jrlJCK89autnqsPmRDmpiloTXoNy2VL/yQfoy4d62MGKydbsZSTXFh5 13 | FOmVDzECgYEA6sHo18Bk+7lUutGmYelOJlVKG/Ofj78ZqQV16G+iR87dbQjDpUp/ 14 | ln/xFb0QxO0mapZSMMWeXbPukI9TOWuxffKr78DNF2s4Zmp+d6cmT21ldco4Wq77 15 | t7+HQNdImuOqtD+tYqPAH+CIu0IHw9guJwdbdTIw554WWMFj3b009CkCgYEA2k1G 16 | zgEKkuf8T9yIifUFLOkTBNQkJyuZF1Xg827eeGXBSpbZaJ81r4oiIh0+7wNqfvMU 17 | 6q5Pt3bUKEcfVpu+NbdjBrVuveVdPYlHDuGLWEp+EFF1ZdM9FpQpSWtYPXG0sE4c 18 | mIdqjC/qCU1+LLttXz4LsQVFq2n8JinA8R7+TpsCgYAukC2l9aRSBY2XzJOq4gK9 19 | ObeMWcMxWN83Fj0v0Eyo35At20orE97AtDnWbPzRgpRXGd/NirUBsvnDtJn2TrUS 20 | 3TpbQKutVHgIYGEbTI0dvf4c4fJRklmdNaEXLFxbVIL8Y5D5eq9V40xbkBpILy3g 21 | UeZDFaR7nHCkRB+R0MCbGQKBgFik0H+ORLDqqrXzIy6B5BwceLCZRCTzuzKSmMnA 22 | 122kRBz5rEajf7VMLhgUMB32ESSDqJazOYOSKQxB9SPCEjbVxMxQmCtcG8SFHemZ 23 | BHBRr2cI7NbwM/obJ7i8chRhO7HrxgjZ1BYgzrQAV5/qa7slArJbJbM5Uj5c7g/7 24 | OeDJAoGAMRzH1bQbIPJgGx84Wq52Rg38krD86TfGAVSKzeLzjYjUJSSmsFz8IwkI 25 | hx74uH6spbBIPDpVI/I5eZTfbT5cxVyXzJlxqt0mKQ6hx5W8O2DIu+p5GyMyyg+H 26 | fLzqwC/oARyYDiu/mUNSjfPGy6JJ0Th1rccO4hHushg+imzieQU= 27 | -----END RSA PRIVATE KEY----- 28 | --------------------------------------------------------------------------------