├── CMakeLists.txt ├── LICENSE ├── README.md ├── client ├── client.c ├── client.h ├── common.c ├── common.h ├── os.c └── os.h ├── common ├── command.h ├── global.c └── global.h ├── server ├── cmd.c ├── cmd.h ├── common.c ├── common.h ├── listener.c ├── listener.h ├── server.c ├── server.h ├── tunnel.c └── tunnel.h ├── structure ├── array.c ├── array.h ├── queue.c ├── queue.h ├── stack.c └── stack.h ├── tunnel.c └── tunneld.c /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | project(tunnel C) 2 | 3 | set(CMAKE_C_STANDARD 99) 4 | 5 | if(WIN32) 6 | MESSAGE(STATUS "Now is windows") 7 | link_libraries(ws2_32 wsock32) 8 | endif() 9 | 10 | if(UNIX AND NOT APPLE) 11 | set(LINUX TRUE) 12 | endif() 13 | 14 | if(LINUX) 15 | message(STATUS ">>> Linux") 16 | add_executable(tunneld tunneld.c common/global.h common/global.c server/server.c server/server.h server/tunnel.c server/tunnel.h server/common.c server/common.h server/listener.c server/listener.h common/command.h structure/queue.h structure/queue.c server/cmd.c server/cmd.h structure/array.h structure/array.c) 17 | else() 18 | message(STATUS ">>> Not Linux, Can't compile tunneld, cause platform not supported.") 19 | endif() 20 | 21 | add_executable(tunnel tunnel.c common/command.h common/global.h common/global.c structure/queue.h structure/queue.c client/client.c client/client.h client/os.c client/os.h structure/array.h structure/array.c client/common.c client/common.h) -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Tunnel 2 | Tunnel是一款单线程、轻量级和高性能的内网穿透程序,支持TCP流量转发(支持任何TCP上层协议,包括HTTP,SSH等),支持多客户端同时连接。 3 | 4 | 解决公网无法访问内部网络服务问题,使内部网络服务能被公网访问。 5 | 6 | ## 说明 7 | - 该项目使用CMake构建,Linux系统编译后会产生两个可执行文件,tunneld(服务器端)和tunnel(客户端),其他系统编译后只会产生tunnel(客户端)。 8 | - tunneld考虑性能原因,使用epoll I/O模型,仅支持Linux系统,且Linux内核版本要大于等于2.5.44。 9 | - tunnel使用select I/O模型,支持主流系统(Mac OS、Windows、Linux)。 10 | - 公网映射端口为动态分配,暂时不支持指定端口。 11 | 12 | ## tunneld(服务器端)使用说明 13 | 执行 tunneld 文件 14 | ``` 15 | $ tunneld 16 | $ Enter listening port(default 8877):8877 17 | $ Enter connection password(default maqian.cc):maqian.cc 18 | $ Port:8877, Password:maqian.cc 19 | $ Listening... 20 | ``` 21 | 这时 tunneld 已启动成功,等待客户端连接。 22 | 23 | ## tunnel(客户端)使用说明 24 | 执行 tunnel 文件 25 | ``` 26 | $ tunnel 27 | $ Enter server IP:xx.xx.xxx.xxx 28 | $ Enter server port(default 8877):8877 29 | $ Enter connection password(default maqian.cc):maqian.cc 30 | $ Enter local port:22 31 | $ Server IP:xx.xx.xxx.xxx, Server Port:8877, Password:maqian.cc, Local Port:22 32 | $ Successfully connected, address: xx.xx.xxx.xxx:45915 33 | ``` 34 | 这样 tunnel 就连接服务器成功了,address是映射到公网的IP和端口,通过访问address的IP和端口就可以访问内部网络服务了。 35 | 36 | ## 下载 37 | [https://github.com/i183/tunnel/releases](https://github.com/i183/tunnel/releases) -------------------------------------------------------------------------------- /client/client.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "client.h" 5 | #include "common.h" 6 | #include "../common/command.h" 7 | #include "os.h" 8 | 9 | #define READ_BUF_LEN 1024 10 | 11 | fd_list rl, wl, el; 12 | Array tag; 13 | int rfd; 14 | char token[50]; 15 | char rip[30]; 16 | int rport, lport; 17 | 18 | void init() { 19 | rl.li = newArrayDefault(sizeof(struct connection *)); 20 | wl.li = newArrayDefault(sizeof(struct connection *)); 21 | el.li = newArrayDefault(sizeof(struct connection *)); 22 | tag = newArrayDefault(sizeof(struct connection *)); 23 | } 24 | 25 | void add_fd_to_rel(struct connection *conn) { 26 | if (indexOfItemInArray(rl.li, &conn) == -1) { 27 | addArrayForPointer(rl.li, conn); 28 | } 29 | if (indexOfItemInArray(el.li, &conn) == -1) { 30 | addArrayForPointer(el.li, conn); 31 | } 32 | } 33 | 34 | void add_fd_to_wl(struct connection *conn) { 35 | if (indexOfItemInArray(wl.li, &conn) == -1) { 36 | addArrayForPointer(wl.li, conn); 37 | } 38 | } 39 | 40 | void remove_rel_by_conn(struct connection *conn) { 41 | int i1 = removeArrayByItem(rl.li, &conn); 42 | if (i1 >= 0 && i1 < rl.num) { 43 | rl.num--; 44 | } 45 | 46 | int i2 = removeArrayByItem(el.li, &conn); 47 | if (i2 >= 0 && i2 < el.num) { 48 | el.num--; 49 | } 50 | } 51 | 52 | void remove_wl_by_conn(struct connection *conn) { 53 | int i = removeArrayByItem(wl.li, &conn); 54 | if (i >= 0 && i < wl.num) { 55 | wl.num--; 56 | } 57 | } 58 | 59 | void remove_fd_by_tag() { 60 | for (int i = 0; i < tag->size; i++) { 61 | struct connection *conn = getArrayForPointer(tag, i); 62 | remove_rel_by_conn(conn); 63 | remove_wl_by_conn(conn); 64 | } 65 | } 66 | 67 | /** 68 | * 读取事件分发 69 | * @param conn 70 | * @return 71 | */ 72 | int dist_read(struct connection *conn); 73 | 74 | /** 75 | * 写入事件分发 76 | * @param conn 77 | * @return 78 | */ 79 | int dist_write(struct connection *conn); 80 | 81 | int send_alive(struct connection *tunnel); 82 | 83 | long wait_time(struct connection *tunnel); 84 | 85 | int handler_1(struct connection *conn); 86 | 87 | int handler_2(struct connection *conn); 88 | 89 | int handler_3(struct connection *conn); 90 | 91 | int create_tunnel(char *ip, int r_port, int l_port, char *password) { 92 | strcpy(rip, ip); 93 | rport = r_port; 94 | lport = l_port; 95 | 96 | socket_start(); 97 | init(); 98 | 99 | socket_t sock = socket_stream(); 100 | if (sock == INVALID_SOCKET) { 101 | perror("invalid socket"); 102 | return -1; 103 | } 104 | 105 | sockaddr_t dest_addr = create_sockaddr(ip, r_port); 106 | 107 | if (connect(sock, (struct sockaddr *) &dest_addr, sizeof(dest_addr)) == SOCKET_ERROR) { 108 | perror("connect error"); 109 | socket_close(sock); 110 | return -1; 111 | } 112 | 113 | struct c_tunnel_conn *tc = malloc(sizeof(struct c_tunnel_conn)); 114 | tc->cmd_buf[0] = 0; 115 | tc->cmd_buf_len = 0; 116 | tc->last_alive = time(null); 117 | struct connection *tunnel = create_conn(sock, C_TUNNEL, true, tc); 118 | tunnel->asyn_conn = true; 119 | 120 | char msg[256]; 121 | sprintf(msg, "%s %s\n", TUNNEL, password); 122 | if (write_data(tunnel, msg, strlen(msg)) == -1) { 123 | return -1; 124 | } 125 | 126 | add_fd_to_rel(tunnel); 127 | 128 | while (true) { 129 | int count = select_os(&rl, &wl, &el, wait_time(tunnel)); 130 | //发送心跳包 131 | send_alive(tunnel); 132 | if (count <= 0) { 133 | continue; 134 | } 135 | 136 | for (int i = 0; i < el.num; ++i) { 137 | struct connection *conn = getArrayForPointer(el.li, i); 138 | if (conn->type == C_TUNNEL) { 139 | error("Tunnel connection is exception"); 140 | return -1; 141 | } 142 | tag_close_conn(conn, tag); 143 | } 144 | verify_asyn_conn(&rl, tag); 145 | verify_asyn_conn(&wl, tag); 146 | for (int i = 0; i < rl.num; ++i) { 147 | struct connection *conn = getArrayForPointer(rl.li, i); 148 | dist_read(conn); 149 | } 150 | for (int i = 0; i < wl.num; ++i) { 151 | struct connection *conn = getArrayForPointer(wl.li, i); 152 | dist_write(conn); 153 | } 154 | close_conn_arr(tag); 155 | remove_fd_by_tag(); 156 | resetArrayEmpty(tag); 157 | } 158 | 159 | return 0; 160 | } 161 | 162 | int send_alive(struct connection *tunnel) { 163 | struct c_tunnel_conn *tc = tunnel->ptr; 164 | if (time(null) - tc->last_alive < C_ALIVE_SECOND) { 165 | return 1; 166 | } 167 | char msg[20]; 168 | sprintf(msg, "%s\n", ALIVE); 169 | if (write_data(tunnel, msg, strlen(msg)) == -1) { 170 | return -1; 171 | } 172 | tc->last_alive = time(null); 173 | printf("Send alive, Current timestamp %ld\n", tc->last_alive); 174 | return 0; 175 | } 176 | 177 | long wait_time(struct connection *tunnel) { 178 | struct c_tunnel_conn *tc = tunnel->ptr; 179 | time_t t = time(null) - tc->last_alive; 180 | if (t >= C_ALIVE_SECOND) { 181 | return 0; 182 | } else { 183 | return (C_ALIVE_SECOND - t) * 1000; 184 | } 185 | } 186 | 187 | int dist_read(struct connection *conn) { 188 | if (conn->tag_close == true && conn->asyn_conn == true) { 189 | return -1; 190 | } 191 | 192 | if (conn->type == C_TUNNEL) { 193 | handler_1(conn); 194 | } else if (conn->type == C_R_SERVER) { 195 | handler_2(conn); 196 | } else if (conn->type == C_L_SERVER) { 197 | handler_3(conn); 198 | } 199 | return 0; 200 | } 201 | 202 | int dist_write(struct connection *conn) { 203 | if (conn->tag_close == true && conn->asyn_conn == true) { 204 | return -1; 205 | } 206 | 207 | int r = handler_write(conn); 208 | if (r != 1) { 209 | remove_wl_by_conn(conn); 210 | } 211 | if (r == -1) { 212 | tag_close_conn(conn, tag); 213 | return -1; 214 | } 215 | 216 | if (conn->type == C_R_SERVER) { 217 | struct r_server_conn *rs = conn->ptr; 218 | handler_3(rs->l_server_conn); 219 | } else if (conn->type == C_L_SERVER) { 220 | struct l_server_conn *ls = conn->ptr; 221 | handler_2(ls->r_server_conn); 222 | } 223 | return 0; 224 | } 225 | 226 | int connecto(struct connection *conn, const sockaddr_t *addr) { 227 | if (conn->is_asyn) { 228 | int r = socket_connect(conn->fd, addr); 229 | //非阻塞connect 返回 -1 并且 errno == ECONNECTED 表示正在建立链接 230 | if (r == -1 && errno == ECONNECTED) { 231 | return 0; 232 | } else { 233 | return -1; 234 | } 235 | } else { 236 | return socket_connect(conn->fd, addr); 237 | } 238 | } 239 | 240 | int request() { 241 | socket_t rs = socket_stream(); 242 | socket_t ls = socket_stream(); 243 | struct connection *rc = create_conn(rs, C_R_SERVER, true, null); 244 | struct connection *lc = create_conn(ls, C_L_SERVER, true, null); 245 | struct r_server_conn *rcp = malloc(sizeof(struct r_server_conn)); 246 | struct l_server_conn *lcp = malloc(sizeof(struct l_server_conn)); 247 | rcp->l_server_conn = lc; 248 | lcp->r_server_conn = rc; 249 | rc->ptr = rcp; 250 | lc->ptr = lcp; 251 | 252 | sockaddr_t raddr = create_sockaddr(rip, rport); 253 | sockaddr_t laddr = create_sockaddr("127.0.0.1", lport); 254 | 255 | if (connecto(rc, &raddr) == -1 || connecto(lc, &laddr) == -1) { 256 | close_conn(rc); 257 | close_conn(lc); 258 | return -1; 259 | } 260 | 261 | //发送拉请求(由于是异步连接,先写入待写数据区,连接成功后写入) 262 | char msg[256]; 263 | sprintf(msg, "%s %d %s\n", PULL, rfd, token); 264 | wait_data(rc, msg, strlen(msg)); 265 | 266 | //printf("Send pull\n"); 267 | add_fd_to_rel(rc); 268 | add_fd_to_rel(lc); 269 | add_fd_to_wl(rc); 270 | add_fd_to_wl(lc); 271 | 272 | return 0; 273 | } 274 | 275 | int read_write(struct connection *read_conn, struct connection *write_conn) { 276 | while (true) { 277 | if (write_conn->len > 0) { 278 | //存在待写入数据,结束循环 279 | break; 280 | } 281 | 282 | char buf[READ_BUF_LEN]; 283 | ssize_t len = recv(read_conn->fd, buf, READ_BUF_LEN, 0); 284 | if (len == -1) { 285 | if (net_error()) { 286 | perror("read_write Read data"); 287 | return -1; 288 | } 289 | break; 290 | } else if (len == 0) { 291 | return -1; 292 | } 293 | 294 | int flag = write_data(write_conn, buf, len); 295 | if (flag == -1) { 296 | return -1; 297 | } else if (flag == 1) { 298 | add_fd_to_wl(write_conn); 299 | } 300 | } 301 | return 0; 302 | } 303 | 304 | void set_cmd_buf(struct c_tunnel_conn *tc, char *buf) { 305 | strcat(tc->cmd_buf, buf); 306 | } 307 | 308 | boolean get_cmd(struct c_tunnel_conn *tc, char *line) { 309 | char *p = strchr(tc->cmd_buf, '\n'); 310 | if (p) { 311 | unsigned long index = p - tc->cmd_buf; 312 | memcpy(line, tc->cmd_buf, index + 1); 313 | line[index] = 0; 314 | 315 | size_t len = strlen(tc->cmd_buf); 316 | for (int i = (int) index + 1; i < len; i++) { 317 | tc->cmd_buf[i - index - 1] = tc->cmd_buf[i]; 318 | } 319 | tc->cmd_buf[len - index - 1] = 0; 320 | return true; 321 | } 322 | return false; 323 | } 324 | 325 | int handler_1(struct connection *conn) { 326 | boolean done = false; 327 | while (true) { 328 | if (conn->len > 0) { 329 | //存在待写入数据,结束循环 330 | break; 331 | } 332 | 333 | char buf[READ_BUF_LEN]; 334 | ssize_t len = recv(conn->fd, buf, READ_BUF_LEN, 0); 335 | if (len == -1) { 336 | if (net_error()) { 337 | perror("handler_1 Read data"); 338 | done = true; 339 | } 340 | break; 341 | } else if (len == 0) { 342 | done = true; 343 | break; 344 | } 345 | buf[len] = 0; 346 | 347 | struct c_tunnel_conn *tc = conn->ptr; 348 | strcat(tc->cmd_buf, buf); 349 | 350 | char line[256]; 351 | boolean gc = get_cmd(tc, line); 352 | while (gc) { 353 | char command[30] = ""; 354 | sscanf(line, "%s", command); 355 | if (strcmp(command, SUCCESS) == 0) { 356 | int a_port; 357 | sscanf(line, "success %d %d %s", &rfd, &a_port, token); 358 | printf("Successfully connected, address: %s:%d\n", rip, a_port); 359 | } else if (strcmp(command, REQUEST) == 0) { 360 | request(); 361 | } else if (strcmp(command, C_ERROR) == 0) { 362 | printf("%s\n", line); 363 | } else { 364 | done = true; 365 | printf("Unknown command: %s\n", command); 366 | break; 367 | } 368 | gc = get_cmd(tc, line); 369 | } 370 | } 371 | 372 | if (done) { 373 | tag_close_conn(conn, tag); 374 | } 375 | return 0; 376 | } 377 | 378 | int handler_2(struct connection *conn) { 379 | struct connection *lc = ((struct r_server_conn *) conn->ptr)->l_server_conn; 380 | if (conn->asyn_conn != true || lc->asyn_conn != true) { 381 | return 1; 382 | } 383 | int r = read_write(conn, lc); 384 | if (r == -1) { 385 | tag_close_conn(conn, tag); 386 | } 387 | return r; 388 | } 389 | 390 | int handler_3(struct connection *conn) { 391 | struct connection *rc = ((struct l_server_conn *) conn->ptr)->r_server_conn; 392 | if (conn->asyn_conn != true || rc->asyn_conn != true) { 393 | return 1; 394 | } 395 | int r = read_write(conn, rc); 396 | if (r == -1) { 397 | tag_close_conn(conn, tag); 398 | } 399 | return r; 400 | } -------------------------------------------------------------------------------- /client/client.h: -------------------------------------------------------------------------------- 1 | #ifndef TUNNEL_CLIENT_H 2 | #define TUNNEL_CLIENT_H 3 | 4 | #include "os.h" 5 | #include "../common/global.h" 6 | 7 | #define C_TUNNEL 1 8 | #define C_R_SERVER 2 9 | #define C_L_SERVER 3 10 | 11 | #define C_ALIVE_SECOND 60 12 | 13 | struct connection { 14 | socket_t fd; 15 | char type; //1.与服务器建立的隧道 2.远程服务器连接 3.本地服务器连接 16 | void *write_buf; //等待写入的数据 17 | int len; //等待写入数据的长度 18 | boolean tag_close; //标记已关闭 19 | boolean is_asyn; //是否为异步连接 20 | boolean asyn_conn; //异步连接是否成功 21 | void *ptr; //额外数据指针 22 | }; 23 | 24 | /** 25 | * 通道连接 26 | */ 27 | struct c_tunnel_conn { 28 | char cmd_buf[1024 * 2]; 29 | int cmd_buf_len; 30 | time_t last_alive; //最后一次发送心跳时间(秒) 31 | }; 32 | 33 | /** 34 | * 远程服务器连接 35 | */ 36 | struct r_server_conn { 37 | struct connection *l_server_conn; 38 | }; 39 | 40 | /** 41 | * 本地服务器连接 42 | */ 43 | struct l_server_conn { 44 | struct connection *r_server_conn; 45 | }; 46 | 47 | /** 48 | * 与服务器建立隧道 49 | * @param ip 远程服务器IP 50 | * @param r_port 远程服务器端口 51 | * @param l_port 本地服务器端口 52 | * @param password 53 | * @return 54 | */ 55 | int create_tunnel(char *ip, int r_port, int l_port, char *password); 56 | 57 | #endif //TUNNEL_CLIENT_H 58 | -------------------------------------------------------------------------------- /client/common.c: -------------------------------------------------------------------------------- 1 | // 2 | // Created by maqian on 2018/11/1. 3 | // 4 | 5 | #include 6 | #include 7 | #include "common.h" 8 | #include "os.h" 9 | 10 | struct connection *create_conn(socket_t fd, int type, boolean is_asyn, void *ptr) { 11 | struct connection *conn = malloc(sizeof(struct connection)); 12 | conn->fd = fd; 13 | conn->type = type; 14 | conn->tag_close = false; 15 | conn->write_buf = null; 16 | conn->len = 0; 17 | conn->is_asyn = is_asyn; 18 | conn->asyn_conn = false; 19 | conn->ptr = ptr; 20 | 21 | if (is_asyn) { 22 | socket_set_nonblock(conn->fd); 23 | } 24 | return conn; 25 | } 26 | 27 | void verify_asyn_conn(fd_list *fl, Array tag) { 28 | int optval; 29 | socklen_t optlen = sizeof(optval); 30 | for (int i = 0; i < fl->num; ++i) { 31 | struct connection *conn = getArrayForPointer(fl->li, i); 32 | if (!conn->tag_close && conn->is_asyn && !conn->asyn_conn) { 33 | if (getsockopt(conn->fd, SOL_SOCKET, SO_ERROR, (char *) &optval, &optlen) || optval) { 34 | //连接失败,关闭连接 35 | tag_close_conn(conn, tag); 36 | } else { 37 | conn->asyn_conn = true; 38 | handler_write(conn); 39 | } 40 | } 41 | } 42 | } 43 | 44 | void tag_close_conn(struct connection *conn, Array arr) { 45 | if (conn == null || conn->tag_close == true) { 46 | return; 47 | } 48 | 49 | conn->tag_close = true; 50 | addArrayForPointer(arr, conn); 51 | //printf("Tag close connection, fd: %d type: %d\n", conn->fd, conn->type); 52 | if (conn->type == C_TUNNEL) { 53 | error("The main socket closed"); 54 | exit(1); 55 | } else if (conn->type == C_R_SERVER) { 56 | if (conn->ptr != null) { 57 | struct r_server_conn *p = conn->ptr; 58 | tag_close_conn(p->l_server_conn, arr); 59 | } 60 | } else if (conn->type == C_L_SERVER) { 61 | if (conn->ptr != null) { 62 | struct l_server_conn *p = conn->ptr; 63 | tag_close_conn(p->r_server_conn, arr); 64 | } 65 | } 66 | } 67 | 68 | int close_conn(struct connection *conn) { 69 | //printf("Closed connection, fd: %d type: %d p:%p\n", conn->fd, conn->type, conn); 70 | 71 | int res = socket_close(conn->fd); 72 | if (conn->ptr) { 73 | free(conn->ptr); 74 | } 75 | if (conn->write_buf && conn->len > 0) { 76 | free(conn->write_buf); 77 | } 78 | free(conn); 79 | return res; 80 | } 81 | 82 | void close_conn_arr(Array arr) { 83 | for (int i = 0; i < arr->size; i++) { 84 | close_conn(getArrayForPointer(arr, i)); 85 | } 86 | } 87 | 88 | int wait_data(struct connection *conn, const void *buf, size_t len) { 89 | if (conn->len > 0) { 90 | void *bs = malloc(conn->len + len); 91 | memcpy(bs, conn->write_buf, conn->len); 92 | memcpy(bs + conn->len, buf, len); 93 | free(conn->write_buf); 94 | conn->write_buf = bs; 95 | conn->len = conn->len + len; 96 | return 1; 97 | } else { 98 | conn->write_buf = malloc(len); 99 | memcpy(conn->write_buf, buf, len); 100 | conn->len = len; 101 | return 0; 102 | } 103 | } 104 | 105 | int write_data(struct connection *conn, const void *buf, size_t len) { 106 | //检测是否有待写数据 107 | if (conn->len > 0) { 108 | void *bs = malloc(conn->len + len); 109 | memcpy(bs, conn->write_buf, conn->len); 110 | memcpy(bs + conn->len, buf, len); 111 | free(conn->write_buf); 112 | conn->write_buf = bs; 113 | conn->len = conn->len + len; 114 | return 1; 115 | } 116 | ssize_t res = send(conn->fd, buf, len, 0); 117 | if ((res == -1 && net_error()) || res == 0) { 118 | //写入数据时出错或连接关闭 119 | perror("write"); 120 | return -1; 121 | } else if (res == -1) { 122 | conn->write_buf = malloc(len); 123 | memcpy(conn->write_buf, buf, len); 124 | conn->len = len; 125 | return 1; 126 | } else if (res < len) { 127 | conn->write_buf = malloc(len - res); 128 | memcpy(conn->write_buf, buf + res, len - res); 129 | conn->len = len - res; 130 | return 1; 131 | } 132 | return 0; 133 | } 134 | 135 | /** 136 | * 处理写入事件 137 | * @param e 138 | * @return 139 | */ 140 | int handler_write(struct connection *conn) { 141 | // 检测当前连接是否可写入 142 | if (conn->is_asyn && !conn->asyn_conn) { 143 | return -2; 144 | } 145 | 146 | //检测是否有待写数据 147 | if (conn->len <= 0) { 148 | return 0; 149 | } 150 | 151 | ssize_t len = send(conn->fd, conn->write_buf, conn->len, 0); 152 | if ((len == -1 && net_error()) || len == 0) { 153 | //写入数据时出错或连接关闭 154 | perror("write"); 155 | return -1; 156 | } else if (len == -1) { 157 | printf("len == -1\n"); 158 | return 1; 159 | } else if (len > 0) { 160 | //写入数据成功 161 | //删除待写数据 162 | free(conn->write_buf); 163 | conn->len = 0; 164 | } 165 | return 0; 166 | } 167 | -------------------------------------------------------------------------------- /client/common.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by maqian on 2018/11/1. 3 | // 4 | 5 | #ifndef TUNNEL_COMMON_H 6 | #define TUNNEL_COMMON_H 7 | 8 | #include 9 | #include "client.h" 10 | #include "../common/global.h" 11 | 12 | struct connection *create_conn(socket_t fd, int type, boolean is_asyn, void *ptr); 13 | 14 | void verify_asyn_conn(fd_list *fl, Array tag); 15 | 16 | void tag_close_conn(struct connection *conn, Array arr); 17 | 18 | int close_conn(struct connection *conn); 19 | 20 | void close_conn_arr(Array arr); 21 | 22 | int wait_data(struct connection *conn, const void *buf, size_t len); 23 | 24 | int write_data(struct connection *conn, const void *buf, size_t len); 25 | 26 | int handler_write(struct connection *conn); 27 | 28 | #endif //TUNNEL_COMMON_H 29 | -------------------------------------------------------------------------------- /client/os.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "os.h" 4 | #include "client.h" 5 | #include "../common/global.h" 6 | 7 | #ifdef _WIN32 8 | void _socket_start(void) { 9 | WSACleanup(); 10 | } 11 | #endif 12 | 13 | void socket_start() { 14 | #ifdef _WIN32 15 | WSADATA wsad; 16 | WSAStartup(MAKEWORD(2, 2), &wsad); 17 | atexit(_socket_start); 18 | #endif 19 | IGNORE_SIGPIPE(); 20 | } 21 | 22 | socket_t socket_stream() { 23 | return socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 24 | } 25 | 26 | sockaddr_t create_sockaddr(char *ip, int port) { 27 | #ifdef _WIN32 28 | sockaddr_t addr; 29 | addr.sin_family = AF_INET; 30 | addr.sin_port = htons(port); 31 | addr.sin_addr.s_addr = inet_addr(ip); 32 | return addr; 33 | #else 34 | sockaddr_t addr; 35 | addr.sin_family = AF_INET; 36 | addr.sin_port = htons(port); 37 | addr.sin_addr.s_addr = inet_addr(ip); 38 | return addr; 39 | #endif 40 | } 41 | 42 | int socket_close(socket_t s) { 43 | #ifdef _WIN32 44 | return closesocket(s); 45 | #else 46 | return close(s); 47 | #endif 48 | } 49 | 50 | int socket_set_block(socket_t s) { 51 | #ifdef _WIN32 52 | u_long mode = 0; 53 | return ioctlsocket(s, FIONBIO, &mode); 54 | #else 55 | int mode = fcntl(s, F_GETFL, 0); 56 | if (mode == SOCKET_ERROR) 57 | return SOCKET_ERROR; 58 | if (mode & O_NONBLOCK) 59 | return fcntl(s, F_SETFL, mode & ~O_NONBLOCK); 60 | return 0; 61 | #endif 62 | } 63 | 64 | int socket_set_nonblock(socket_t s) { 65 | #ifdef _WIN32 66 | u_long mode = 1; 67 | return ioctlsocket(s, FIONBIO, &mode); 68 | #else 69 | int mode = fcntl(s, F_GETFL, 0); 70 | if (mode == SOCKET_ERROR) 71 | return SOCKET_ERROR; 72 | if (mode & O_NONBLOCK) 73 | return 0; 74 | return fcntl(s, F_SETFL, mode | O_NONBLOCK); 75 | #endif 76 | } 77 | 78 | int socket_connect(socket_t s, const sockaddr_t *addr) { 79 | return connect(s, (const struct sockaddr *) addr, sizeof(*addr)); 80 | } 81 | 82 | boolean net_error() { 83 | #ifdef _WIN32 84 | return WSAGetLastError() != WSAEWOULDBLOCK; 85 | #else 86 | return EAGAIN != errno; 87 | #endif 88 | } 89 | 90 | int socket_addr(const char *ip, uint16_t port, sockaddr_t *addr) { 91 | if (!ip || !*ip || !addr) { 92 | fprintf(stderr, "check empty ip = %s, port = %hu, addr = %p.\n", ip, port, addr); 93 | return -1; 94 | } 95 | 96 | addr->sin_family = AF_INET; 97 | addr->sin_port = htons(port); 98 | addr->sin_addr.s_addr = inet_addr(ip); 99 | if (addr->sin_addr.s_addr == INADDR_NONE) { 100 | struct hostent *host = gethostbyname(ip); 101 | if (!host || !host->h_addr) { 102 | fprintf(stderr, "check ip is error = %s.\n", ip); 103 | return -1; 104 | } 105 | // 尝试一种, 默认ipv4 106 | memcpy(&addr->sin_addr, host->h_addr, host->h_length); 107 | } 108 | memset(addr->sin_zero, 0, sizeof addr->sin_zero); 109 | 110 | return 0; 111 | } 112 | 113 | void fd_set_to_fd_list(fd_list *fl, fd_set *fs) { 114 | if (fl && fl->li && fs) { 115 | fl->num = 0; 116 | Array li = fl->li; 117 | for (int i = 0; i < li->size; i++) { 118 | struct connection *conn = getArrayForPointer(li, i); 119 | if (FD_ISSET(conn->fd, fs)) { 120 | if (fl->num != i) { 121 | struct connection *temp = getArrayForPointer(li, fl->num); 122 | setArrayForPointer(li, fl->num, conn); 123 | setArrayForPointer(li, i, temp); 124 | } 125 | fl->num++; 126 | } 127 | } 128 | 129 | } 130 | } 131 | 132 | int get_max_fd(fd_list *fl) { 133 | int max = 0; 134 | if (fl && fl->li) { 135 | Array li = fl->li; 136 | for (int i = 0; i < li->size; i++) { 137 | struct connection *conn = getArrayForPointer(li, i); 138 | if (conn->fd > max) { 139 | max = conn->fd; 140 | } 141 | } 142 | } 143 | return max; 144 | } 145 | 146 | void fd_list_to_fd_set(fd_list *fl, fd_set *fs) { 147 | FD_ZERO(fs); 148 | if (fl && fl->li) { 149 | Array li = fl->li; 150 | for (int i = 0; i < li->size; i++) { 151 | struct connection *conn = getArrayForPointer(li, i); 152 | FD_SET(conn->fd, fs); 153 | } 154 | } 155 | } 156 | 157 | int select_os(fd_list *rl, fd_list *wl, fd_list *el, long timeout_ms) { 158 | int max_fd = get_max_fd(rl), temp; 159 | if ((temp = get_max_fd(wl)) > max_fd) { 160 | max_fd = temp; 161 | } 162 | if ((temp = get_max_fd(el)) > max_fd) { 163 | max_fd = temp; 164 | } 165 | 166 | struct timeval tv; 167 | struct timeval *timeout; 168 | if (timeout_ms < 0) { 169 | timeout = null; 170 | } else { 171 | tv.tv_sec = timeout_ms / 1000; 172 | tv.tv_usec = (timeout_ms % 1000) * 100; 173 | timeout = &tv; 174 | } 175 | 176 | fd_set rs, ws, es; 177 | fd_list_to_fd_set(rl, &rs); 178 | fd_list_to_fd_set(wl, &ws); 179 | fd_list_to_fd_set(el, &es); 180 | 181 | int result = select(max_fd + 1, &rs, &ws, &es, timeout); 182 | if (result > 0) { 183 | fd_set_to_fd_list(rl, &rs); 184 | fd_set_to_fd_list(wl, &ws); 185 | fd_set_to_fd_list(el, &es); 186 | } 187 | return result; 188 | } -------------------------------------------------------------------------------- /client/os.h: -------------------------------------------------------------------------------- 1 | #ifndef TUNNEL_OS_H 2 | #define TUNNEL_OS_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include "../structure/array.h" 12 | 13 | #define IGNORE_SIGNAL(sig) signal(sig, SIG_IGN) 14 | 15 | /* Handle Header Files */ 16 | #ifdef _WIN32 17 | #pragma comment(lib, "ws2_32.lib") 18 | #undef FD_SETSIZE 19 | #define FD_SETSIZE (1024) 20 | #include 21 | #include 22 | 23 | #undef errno 24 | #define errno WSAGetLastError() 25 | 26 | #define IGNORE_SIGPIPE() 27 | 28 | // connect链接还在进行中, linux显示 EINPROGRESS,winds是 WSAEWOULDBLOCK 29 | #define ECONNECTED WSAEWOULDBLOCK 30 | 31 | typedef int socklen_t; 32 | typedef SOCKET socket_t; 33 | 34 | #else 35 | 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | #include 43 | #include 44 | #include 45 | 46 | #define INVALID_SOCKET (~0) 47 | #define SOCKET_ERROR (-1) 48 | 49 | #define IGNORE_SIGPIPE() IGNORE_SIGNAL(SIGPIPE) 50 | 51 | #define ECONNECTED EINPROGRESS 52 | 53 | typedef int socket_t; 54 | 55 | #endif 56 | 57 | typedef struct sockaddr_in sockaddr_t; 58 | 59 | void socket_start(); 60 | 61 | socket_t socket_stream(); 62 | 63 | sockaddr_t create_sockaddr(char *ip, int port); 64 | 65 | int socket_close(socket_t s); 66 | 67 | int socket_set_block(socket_t s); 68 | 69 | int socket_set_nonblock(socket_t s); 70 | 71 | int socket_connect(socket_t s, const sockaddr_t *addr); 72 | 73 | boolean net_error(); 74 | 75 | int socket_addr(const char *ip, uint16_t port, sockaddr_t *addr); 76 | 77 | typedef struct { 78 | Array li; 79 | int num; //可写、可读或异常数量 80 | } fd_list; 81 | 82 | /** 83 | * select io 84 | * @param rl 监测可写列表 85 | * @param wl 监测可读列表 86 | * @param el 监测异常列表 87 | * @param timeout_ms 超时时间(毫秒)-1 无限等待 0立即返回 88 | * @return 89 | */ 90 | int select_os(fd_list *rl, fd_list *wl, fd_list *el, long timeout_ms); 91 | 92 | #endif //TUNNEL_OS_H 93 | -------------------------------------------------------------------------------- /common/command.h: -------------------------------------------------------------------------------- 1 | #ifndef TUNNEL_COMMAND_H 2 | #define TUNNEL_COMMAND_H 3 | 4 | #define TUNNEL "tunnel" 5 | #define PULL "pull" 6 | #define SUCCESS "success" 7 | #define REQUEST "request" 8 | #define ALIVE "alive" 9 | 10 | #define C_ERROR "error" 11 | 12 | #endif //TUNNEL_COMMAND_H 13 | -------------------------------------------------------------------------------- /common/global.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include "global.h" 7 | 8 | void error(char *s) { 9 | fprintf(stderr, "Error: %s\n", s); 10 | exit(EXIT_FAILURE); 11 | } 12 | 13 | void line_to_zero(char *s) { 14 | char *index = strchr(s, '\n'); 15 | if (index) { 16 | s[index - s] = 0; 17 | } 18 | } 19 | 20 | /** 21 | * 获取系统类型 22 | * @return 1.linux 2.os x 3.windows 4.unix 5.其他 23 | */ 24 | int get_system_type() { 25 | #ifdef __linux__ 26 | return 1; 27 | #elif __APPLE__ 28 | return 2; 29 | #elif defined(_WIN32) || defined(WIN32) 30 | return 3; 31 | #elif __unix_ 32 | return 4; 33 | #else 34 | return 5; 35 | #endif 36 | } 37 | 38 | boolean memeq(void *p1, void *p2, int n) { 39 | char *c1 = p1, *c2 = p2; 40 | for (; n > 0; c1++, c2++, n--) { 41 | if (*c1 != *c2) { 42 | return false; 43 | } 44 | } 45 | return true; 46 | } 47 | 48 | int enter(void *dest, size_t dest_size, char *def) { 49 | if (fgets(dest, dest_size, stdin) != NULL) { 50 | /** 51 | * Find the newline and, if present, zero it out 52 | */ 53 | char *newline = strchr(dest, '\n'); 54 | if (newline) 55 | *newline = 0; 56 | 57 | if (strlen(dest) == 0) { 58 | strcpy(dest, def); 59 | return 0; 60 | } else { 61 | return 1; 62 | } 63 | } 64 | return -1; 65 | } 66 | 67 | void clear_stdin() { 68 | char c; 69 | while ((c = getchar()) != EOF && c != '\n') { 70 | printf("%c", c); 71 | }; 72 | } -------------------------------------------------------------------------------- /common/global.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by maqian on 2018/6/15. 3 | // 4 | 5 | #ifndef LEARN_C_COMMON_H 6 | #define LEARN_C_COMMON_H 7 | 8 | #include 9 | 10 | #ifndef NULL 11 | #define NULL ((void *)0) 12 | #endif 13 | #ifndef null 14 | #define null ((void *)0) 15 | #endif 16 | 17 | typedef unsigned char boolean; 18 | 19 | #ifndef TRUE 20 | #define TRUE 1 21 | #endif 22 | 23 | #ifndef FALSE 24 | #define FALSE 0 25 | #endif 26 | 27 | #ifndef true 28 | #define true 1 29 | #endif 30 | 31 | #ifndef false 32 | #define false 0 33 | #endif 34 | 35 | void error(char *s); 36 | 37 | void line_to_zero(char *s); 38 | 39 | /** 40 | * 获取系统类型 41 | * @return 1.linux 2.os x 3.windows 4.其他 42 | */ 43 | int get_system_type(); 44 | 45 | /** 46 | * 比较一段内存存储的数据是否相同 47 | * @param p1 48 | * @param p2 49 | * @param n 内存段字节数 50 | * @return 51 | */ 52 | boolean memeq(void *p1, void *p2, int n); 53 | 54 | int enter(void *dest, size_t dest_size, char *def); 55 | 56 | void clear_stdin(); 57 | 58 | #endif //LEARN_C_COMMON_H 59 | -------------------------------------------------------------------------------- /server/cmd.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include "cmd.h" 6 | #include "../common/command.h" 7 | #include "common.h" 8 | #include "tunnel.h" 9 | 10 | int tunnel_cmd(int epfd, struct connection *conn, const char *cmd, const char *pw) { 11 | char password[50] = ""; 12 | sscanf(cmd, "tunnel %s", password); 13 | if (strcmp(password, pw)) { 14 | //密码错误 15 | char msg[256]; 16 | sprintf(msg, "%s %s\n", C_ERROR, "密码错误"); 17 | write_data(conn, msg, strlen(msg)); 18 | return -1; 19 | } 20 | 21 | if (create_tunnel(epfd, conn) == -1) { 22 | return -1; 23 | } 24 | return 0; 25 | } 26 | 27 | int pull_cmd(int epfd, struct connection *conn, const char *cmd) { 28 | int fd = -1; 29 | char token[50] = ""; 30 | sscanf(cmd, "pull %d %s", &fd, token); 31 | if (fd == -1 || strlen(token) == 0) { 32 | char msg[256]; 33 | sprintf(msg, "%s %s\n", C_ERROR, "参数错误"); 34 | write_data(conn, msg, strlen(msg)); 35 | return -1; 36 | } 37 | 38 | struct tunnel *tp = get_tunnel(fd)->ptr; 39 | if (strcmp(token, tp->token) != 0) { 40 | char msg[256]; 41 | sprintf(msg, "%s %s\n", C_ERROR, "Token错误"); 42 | write_data(conn, msg, strlen(msg)); 43 | return -1; 44 | } 45 | 46 | struct listen_user *lu = tp->listen_user_conn->ptr; 47 | if (isQueueEmpty(lu->queue)) { 48 | char msg[256]; 49 | sprintf(msg, "%s %s\n", C_ERROR, "没有待处理的连接"); 50 | write_data(conn, msg, strlen(msg)); 51 | return -1; 52 | } 53 | 54 | struct client_conn *cc = malloc(sizeof(struct client_conn)); 55 | cc->user_conn = outQueueForPointer(lu->queue); 56 | conn->ptr = cc; 57 | conn->type = S_CLIENT; 58 | 59 | struct user_conn *uc = malloc(sizeof(struct user_conn)); 60 | uc->client_conn = conn; 61 | cc->user_conn->ptr = uc; 62 | 63 | struct epoll_event ev; 64 | ev.data.ptr = cc->user_conn; 65 | ev.events = EPOLLIN | EPOLLOUT | EPOLLET;//边缘触发选项 66 | 67 | if (epoll_ctl(epfd, EPOLL_CTL_ADD, cc->user_conn->fd, &ev) == -1) { 68 | perror("epoll_ctl"); 69 | return -1; 70 | } 71 | 72 | return 0; 73 | } -------------------------------------------------------------------------------- /server/cmd.h: -------------------------------------------------------------------------------- 1 | #include "server.h" 2 | 3 | #ifndef TUNNEL_CMD_H 4 | #define TUNNEL_CMD_H 5 | 6 | int tunnel_cmd(int epfd, struct connection *conn, const char *cmd, const char *pw); 7 | 8 | int pull_cmd(int epfd, struct connection *conn, const char *cmd); 9 | 10 | #endif //TUNNEL_CMD_H 11 | -------------------------------------------------------------------------------- /server/common.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include "common.h" 11 | #include "server.h" 12 | #include "tunnel.h" 13 | 14 | struct connection *create_conn(int fd, int type, void *ptr) { 15 | struct connection *conn = malloc(sizeof(struct connection)); 16 | conn->fd = fd; 17 | conn->type = type; 18 | conn->write_buf = null; 19 | conn->len = 0; 20 | conn->tag_close = false; 21 | conn->ptr = ptr; 22 | return conn; 23 | } 24 | 25 | void tag_close_conn(struct connection *conn, Array arr) { 26 | if (conn == null || conn->tag_close == true) { 27 | return; 28 | } 29 | 30 | conn->tag_close = true; 31 | addArrayForPointer(arr, conn); 32 | //printf("Tag close connection, fd: %d type: %d\n", conn->fd, conn->type); 33 | if (conn->type == S_LISTEN_CLIENT) { 34 | error("The main socket closed"); 35 | exit(1); 36 | } else if (conn->type == S_LISTEN_USER) { 37 | if (conn->ptr != null) { 38 | struct listen_user *p = conn->ptr; 39 | tag_close_conn(p->tunnel_conn, arr); 40 | 41 | while (!isQueueEmpty(p->queue)) { 42 | tag_close_conn(outQueueForPointer(p->queue), arr); 43 | } 44 | freeQueue(p->queue); 45 | } 46 | } else if (conn->type == S_UNKNOWN) { 47 | 48 | } else if (conn->type == S_TUNNEL) { 49 | if (conn->ptr != null) { 50 | struct tunnel *p = conn->ptr; 51 | tag_close_conn(p->listen_user_conn, arr); 52 | } 53 | } else if (conn->type == S_CLIENT) { 54 | if (conn->ptr != null) { 55 | struct client_conn *p = conn->ptr; 56 | tag_close_conn(p->user_conn, arr); 57 | } 58 | } else if (conn->type == S_USER) { 59 | if (conn->ptr != null) { 60 | struct user_conn *p = conn->ptr; 61 | tag_close_conn(p->client_conn, arr); 62 | } 63 | } 64 | } 65 | 66 | int close_conn(struct connection *conn) { 67 | //printf("Closed connection, fd: %d type: %d p:%p\n", conn->fd, conn->type, conn); 68 | if (conn->type == S_TUNNEL) { 69 | remove_tunnel(conn->fd); 70 | struct tunnel *t = conn->ptr; 71 | if (t->token) { 72 | free(t->token); 73 | } 74 | } 75 | int res = close(conn->fd); 76 | if (conn->ptr) { 77 | free(conn->ptr); 78 | } 79 | if (conn->write_buf && conn->len > 0) { 80 | free(conn->write_buf); 81 | } 82 | free(conn); 83 | return res; 84 | } 85 | 86 | void close_conn_arr(Array arr) { 87 | for (int i = 0; i < arr->size; i++) { 88 | close_conn(getArrayForPointer(arr, i)); 89 | } 90 | } 91 | 92 | int write_data(struct connection *conn, const void *buf, size_t len) { 93 | //检测是否有待写数据 94 | if (conn->len > 0) { 95 | void *bs = malloc(conn->len + len); 96 | memcpy(bs, conn->write_buf, conn->len); 97 | memcpy(bs + conn->len, buf, len); 98 | printf("WF %p\n", conn->write_buf); 99 | free(conn->write_buf); 100 | conn->write_buf = bs; 101 | conn->len = conn->len + len; 102 | return 1; 103 | } 104 | ssize_t res = write(conn->fd, buf, len); 105 | if ((res == -1 && EAGAIN != errno) || res == 0) { 106 | //写入数据时出错或连接关闭 107 | perror("write"); 108 | return -1; 109 | } else if (res == -1) { 110 | conn->write_buf = malloc(len); 111 | memcpy(conn->write_buf, buf, len); 112 | conn->len = len; 113 | return 1; 114 | } else if (res < len) { 115 | conn->write_buf = malloc(len - res); 116 | memcpy(conn->write_buf, buf + res, len - res); 117 | conn->len = len - res; 118 | return 1; 119 | } 120 | return 0; 121 | } 122 | 123 | int make_socket_non_blocking(int fd) { 124 | int flags, s; 125 | // 获取当前flag 126 | flags = fcntl(fd, F_GETFL, 0); 127 | if (-1 == flags) { 128 | perror("Get fd status"); 129 | return -1; 130 | } 131 | 132 | flags |= O_NONBLOCK; 133 | 134 | // 设置flag 135 | s = fcntl(fd, F_SETFL, flags); 136 | if (-1 == s) { 137 | perror("Set fd status"); 138 | return -1; 139 | } 140 | return 0; 141 | } 142 | 143 | int make_socket_block(int s) { 144 | int mode = fcntl(s, F_GETFL, 0); 145 | if (mode == -1) 146 | return -1; 147 | if (mode & O_NONBLOCK) 148 | return fcntl(s, F_SETFL, mode & ~O_NONBLOCK); 149 | return 0; 150 | } 151 | 152 | void log_info(const char *str) { 153 | syslog(LOG_USER | LOG_INFO, "[INFO] %s\n", str); 154 | } 155 | 156 | void log_err(const char *str) { 157 | syslog(LOG_USER | LOG_INFO, "[ERROR] %s\n", str); 158 | } 159 | 160 | boolean is_use(int port) { 161 | boolean b = true; 162 | struct sockaddr_in addr = {0}; 163 | addr.sin_family = AF_INET; 164 | addr.sin_addr.s_addr = INADDR_ANY; 165 | addr.sin_port = htons(port); 166 | 167 | int fd = socket(AF_INET, SOCK_STREAM, 0); 168 | if (fd == -1) { 169 | goto END; 170 | } 171 | 172 | int on = 1; 173 | // 打开 socket 端口复用, 防止测试的时候出现 Address already in use 174 | if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) == -1) { 175 | goto END; 176 | } 177 | 178 | if (bind(fd, (const struct sockaddr *) &addr, sizeof(addr)) == -1) { 179 | goto END; 180 | } 181 | b = false; 182 | END: 183 | close(fd); 184 | return b; 185 | } -------------------------------------------------------------------------------- /server/common.h: -------------------------------------------------------------------------------- 1 | #ifndef TUNNEL_COMMON_H 2 | #define TUNNEL_COMMON_H 3 | 4 | #include "../structure/array.h" 5 | 6 | struct connection *create_conn(int fd, int type, void *ptr); 7 | 8 | void tag_close_conn(struct connection *conn, Array arr); 9 | 10 | int close_conn(struct connection *conn); 11 | 12 | void close_conn_arr(Array arr); 13 | 14 | int write_data(struct connection *conn, const void *buf, size_t len); 15 | 16 | int make_socket_non_blocking(int fd); 17 | 18 | int make_socket_block(int fd); 19 | 20 | void log_info(const char *str); 21 | 22 | void log_err(const char *str); 23 | 24 | boolean is_use(int port); 25 | 26 | #endif //TUNNEL_COMMON_H 27 | -------------------------------------------------------------------------------- /server/listener.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "listener.h" 5 | #include "common.h" 6 | 7 | int create_listener(int port, int backlog, boolean reuse_addr, boolean non_blocking) { 8 | struct sockaddr_in server_addr = {0}; 9 | server_addr.sin_family = AF_INET; 10 | server_addr.sin_addr.s_addr = INADDR_ANY; 11 | server_addr.sin_port = htons(port); 12 | 13 | int listenfd = socket(AF_INET, SOCK_STREAM, 0); 14 | if (listenfd == -1) { 15 | log_err("Open listen socket"); 16 | return -1; 17 | } 18 | 19 | int on = 1; 20 | // 打开 socket 端口复用, 防止测试的时候出现 Address already in use 21 | if (reuse_addr && setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) == -1) { 22 | log_err("Set socket"); 23 | return -1; 24 | } 25 | 26 | if (bind(listenfd, (const struct sockaddr *) &server_addr, sizeof(server_addr)) == -1) { 27 | log_err("Bind port"); 28 | return -1; 29 | } 30 | 31 | if (non_blocking && make_socket_non_blocking(listenfd) == -1) { 32 | log_err("Make socket non blocking"); 33 | return -1; 34 | } 35 | 36 | if (listen(listenfd, backlog) == -1) { 37 | log_err("Start listen"); 38 | return -1; 39 | } 40 | 41 | return listenfd; 42 | } -------------------------------------------------------------------------------- /server/listener.h: -------------------------------------------------------------------------------- 1 | #ifndef TUNNEL_LISTENER_H 2 | #define TUNNEL_LISTENER_H 3 | 4 | #include "../common/global.h" 5 | 6 | /** 7 | * 创建监听器 8 | * @param port 9 | * @return 10 | */ 11 | int create_listener(int port, int backlog, boolean reuse_addr, boolean non_blocking); 12 | 13 | #endif //TUNNEL_LISTENER_H 14 | -------------------------------------------------------------------------------- /server/server.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include "server.h" 12 | #include "../common/global.h" 13 | #include "tunnel.h" 14 | #include "common.h" 15 | #include "listener.h" 16 | #include "../common/command.h" 17 | #include "cmd.h" 18 | 19 | #define MAX_EVENT 20 20 | #define READ_BUF_LEN 1024 21 | #define TUNNEL_MAP_SIZE 20 22 | 23 | const char *pw = null; 24 | 25 | Array tag; 26 | 27 | int handler_write(const struct epoll_event *e); 28 | 29 | int handler_1(int epfd, const struct epoll_event *e); 30 | 31 | int handler_2(int epfd, const struct epoll_event *e); 32 | 33 | int handler_3(int epfd, const struct epoll_event *e); 34 | 35 | int handler_4(int epfd, const struct epoll_event *e); 36 | 37 | int handler_5(int epfd, const struct epoll_event *e); 38 | 39 | int handler_6(int epfd, const struct epoll_event *e); 40 | 41 | 42 | int start(int port, char *password) { 43 | pw = password; 44 | tag = newArrayDefault(sizeof(struct connection *)); 45 | initTunnelMap(TUNNEL_MAP_SIZE); 46 | 47 | int epfd = 0; 48 | int listenfd = create_listener(port, 200, true, true); 49 | //验证listener是否创建成功 50 | if (listenfd == -1) { 51 | return -1; 52 | } 53 | struct connection *conn = create_conn(listenfd, S_LISTEN_CLIENT, NULL); 54 | 55 | struct epoll_event ev, event[MAX_EVENT]; 56 | log_info("Listening...\n"); 57 | // 创建epoll实例 58 | epfd = epoll_create1(0); 59 | if (epfd == 1) { 60 | log_err("Create epoll instance"); 61 | return -1; 62 | } 63 | 64 | ev.data.ptr = conn; 65 | ev.events = EPOLLIN | EPOLLET;//边缘触发选项 66 | // 设置epoll的事件 67 | if (epoll_ctl(epfd, EPOLL_CTL_ADD, listenfd, &ev) == -1) { 68 | log_err("Set epoll_ctl"); 69 | return -1; 70 | } 71 | 72 | while (true) { 73 | // 等待事件 74 | int wait_count = epoll_wait(epfd, event, MAX_EVENT, -1); 75 | 76 | for (int i = 0; i < wait_count; i++) { 77 | struct epoll_event e = event[i]; 78 | struct connection *conn = (struct connection *) e.data.ptr; 79 | uint32_t events = event[i].events; 80 | 81 | // 判断epoll是否发生错误 82 | if (events & EPOLLERR || events & EPOLLHUP) { 83 | log_err("Epoll has error\n"); 84 | tag_close_conn(conn, tag); 85 | continue; 86 | } 87 | 88 | //可写事件 89 | if (events & EPOLLOUT && conn->tag_close == false) { 90 | if (handler_write(&e) == -1) { 91 | //写入数据出错,关闭连接 92 | tag_close_conn(conn, tag); 93 | continue; 94 | } 95 | } 96 | 97 | if (conn->tag_close == true) { 98 | continue; 99 | } 100 | 101 | if (conn->type == 1) { 102 | handler_1(epfd, &e); 103 | } else if (conn->type == 2) { 104 | handler_2(epfd, &e); 105 | } else if (conn->type == 3) { 106 | handler_3(epfd, &e); 107 | } else if (conn->type == 4) { 108 | handler_4(epfd, &e); 109 | } else if (conn->type == 5) { 110 | handler_5(epfd, &e); 111 | } else if (conn->type == 6) { 112 | handler_6(epfd, &e); 113 | } 114 | } 115 | close_conn_arr(tag); 116 | resetArrayEmpty(tag); 117 | } 118 | 119 | return 0; 120 | } 121 | 122 | /** 123 | * 处理写入事件 124 | * @param e 125 | * @return 126 | */ 127 | int handler_write(const struct epoll_event *e) { 128 | struct connection *conn = (struct connection *) e->data.ptr; 129 | //检测是否有待写数据 130 | if (conn->len <= 0) { 131 | return 0; 132 | } 133 | 134 | ssize_t len = write(conn->fd, conn->write_buf, conn->len); 135 | if ((len == -1 && EAGAIN != errno) || len == 0) { 136 | //写入数据时出错或连接关闭 137 | log_err("write"); 138 | return -1; 139 | } else if (len == -1) { 140 | return 1; 141 | } else if (len > 0) { 142 | //写入数据成功 143 | //删除待写数据 144 | free(conn->write_buf); 145 | conn->len = 0; 146 | } 147 | return 0; 148 | } 149 | 150 | int read_write_client(struct connection *conn) { 151 | if (conn->type != S_CLIENT) { 152 | return -1; 153 | } 154 | 155 | struct connection *uc = ((struct client_conn *) conn->ptr)->user_conn; 156 | 157 | while (true) { 158 | if (uc->len > 0) { 159 | //存在待写入数据,结束循环 160 | break; 161 | } 162 | 163 | char buf[READ_BUF_LEN]; 164 | ssize_t len = read(conn->fd, buf, READ_BUF_LEN); 165 | if (len == -1) { 166 | if (EAGAIN != errno) { 167 | log_err("Read data"); 168 | return -1; 169 | } 170 | break; 171 | } else if (len == 0) { 172 | return -1; 173 | } 174 | 175 | int flag = write_data(uc, buf, len); 176 | if (flag == -1) { 177 | return -1; 178 | } 179 | } 180 | return 0; 181 | } 182 | 183 | 184 | int read_write_user(struct connection *conn) { 185 | if (conn->type != S_USER) { 186 | return -1; 187 | } 188 | 189 | struct connection *cc = ((struct user_conn *) conn->ptr)->client_conn; 190 | 191 | while (true) { 192 | if (cc->len > 0) { 193 | //存在待写入数据,结束循环 194 | break; 195 | } 196 | 197 | char buf[READ_BUF_LEN + 1]; 198 | ssize_t len = read(conn->fd, buf, READ_BUF_LEN); 199 | if (len == -1) { 200 | if (EAGAIN != errno) { 201 | log_err("Read data"); 202 | return -1; 203 | } 204 | break; 205 | } else if (len == 0) { 206 | return -1; 207 | } 208 | 209 | int flag = write_data(cc, buf, len); 210 | if (flag == -1) { 211 | return -1; 212 | } 213 | } 214 | return 0; 215 | } 216 | 217 | /** 218 | * 处理"监听客户端请求的Socket"事件 219 | * @return 220 | */ 221 | int handler_1(int epfd, const struct epoll_event *e) { 222 | struct connection *conn = (struct connection *) e->data.ptr; 223 | while (true) { 224 | struct sockaddr_in in_addr = {0}; 225 | socklen_t in_addr_len = sizeof(in_addr); 226 | int accp_fd = accept(conn->fd, (struct sockaddr *) &in_addr, &in_addr_len); 227 | if (accp_fd == -1) { 228 | break; 229 | } 230 | 231 | //printf("Accept client IP:%s, Port:%d\n", inet_ntoa(in_addr.sin_addr), ntohs(in_addr.sin_port)); 232 | 233 | if (make_socket_non_blocking(accp_fd) == -1) { 234 | log_err("Accept make socket non blocking"); 235 | return -1; 236 | } 237 | 238 | struct connection *uc = create_conn(accp_fd, S_UNKNOWN, null); 239 | struct epoll_event ev; 240 | ev.data.ptr = uc; 241 | ev.events = EPOLLIN | EPOLLOUT | EPOLLET;//边缘触发选项 242 | 243 | // 为新accept的 file describe 设置epoll事件 244 | if (epoll_ctl(epfd, EPOLL_CTL_ADD, accp_fd, &ev) == -1) { 245 | log_err("epoll_ctl"); 246 | return -1; 247 | } 248 | 249 | } 250 | return 0; 251 | } 252 | 253 | /** 254 | * 处理"监听用户请求的Socket"事件 255 | * @return 256 | */ 257 | int handler_2(int epfd, const struct epoll_event *e) { 258 | struct connection *conn = (struct connection *) e->data.ptr; 259 | while (true) { 260 | struct sockaddr_in in_addr = {0}; 261 | socklen_t in_addr_len = sizeof(in_addr); 262 | int accp_fd = accept(conn->fd, (struct sockaddr *) &in_addr, &in_addr_len); 263 | if (accp_fd == -1) { 264 | break; 265 | } 266 | 267 | //printf("Accept user IP:%s, Port:%d\n", inet_ntoa(in_addr.sin_addr), ntohs(in_addr.sin_port)); 268 | 269 | if (make_socket_non_blocking(accp_fd) == -1) { 270 | log_err("Accept make socket non blocking"); 271 | return -1; 272 | } 273 | 274 | struct connection *user_conn = create_conn(accp_fd, S_USER, null); 275 | struct listen_user *lu = conn->ptr; 276 | inQueueForPointer(lu->queue, user_conn); 277 | 278 | char msg[20]; 279 | sprintf(msg, "%s\n", REQUEST); 280 | //printf("Send request\n"); 281 | int flag = write_data(lu->tunnel_conn, msg, strlen(msg)); //通知客户端有新的请求 282 | if (flag == -1) { 283 | tag_close_conn(conn, tag); 284 | break; 285 | } 286 | 287 | } 288 | return 0; 289 | } 290 | 291 | /** 292 | * 处理"未知"事件 293 | * @return 294 | */ 295 | int handler_3(int epfd, const struct epoll_event *e) { 296 | struct connection *conn = (struct connection *) e->data.ptr; 297 | boolean done = false; 298 | while (true) { 299 | if (conn->len > 0) { 300 | //存在待写入数据,结束循环 301 | break; 302 | } 303 | 304 | char buf[READ_BUF_LEN]; 305 | ssize_t len = read(conn->fd, buf, READ_BUF_LEN); 306 | if (len == -1) { 307 | if (EAGAIN != errno) { 308 | log_err("Read data"); 309 | done = true; 310 | } 311 | break; 312 | } else if (len == 0) { 313 | done = true; 314 | break; 315 | } 316 | buf[len] = 0; 317 | 318 | line_to_zero(buf); 319 | //printf("handler_3 Read the content: %s\n", buf); 320 | 321 | char command[30] = ""; 322 | sscanf(buf, "%s ", command); 323 | if (command == null) { 324 | done = true; 325 | break; 326 | } else if (strcmp(command, TUNNEL) == 0) { 327 | //处理tunnel命令 328 | if (tunnel_cmd(epfd, conn, buf, pw) == -1) { 329 | done = true; 330 | break; 331 | } 332 | break; 333 | } else if (strcmp(command, PULL) == 0) { 334 | //处理pull命令 335 | //printf("Receive pull\n"); 336 | if (pull_cmd(epfd, conn, buf) == -1) { 337 | done = true; 338 | break; 339 | } 340 | break; 341 | } else { 342 | done = true; 343 | break; 344 | } 345 | } 346 | 347 | if (done) { 348 | tag_close_conn(conn, tag); 349 | } 350 | return 0; 351 | } 352 | 353 | /** 354 | * 处理"与客户端建立的隧道"事件 355 | * @return 356 | */ 357 | int handler_4(int epfd, const struct epoll_event *e) { 358 | struct connection *conn = (struct connection *) e->data.ptr; 359 | boolean done = false; 360 | while (true) { 361 | if (conn->len > 0) { 362 | //存在待写入数据,结束循环 363 | break; 364 | } 365 | 366 | char buf[READ_BUF_LEN]; 367 | ssize_t len = read(conn->fd, buf, READ_BUF_LEN); 368 | if (len == -1) { 369 | if (EAGAIN != errno) { 370 | log_err("Read data"); 371 | done = true; 372 | } 373 | break; 374 | } else if (len == 0) { 375 | done = true; 376 | break; 377 | } 378 | buf[len] = 0; 379 | //printf("handler_4 Read the content: %s\n", buf); 380 | } 381 | 382 | if (done) { 383 | tag_close_conn(conn, tag); 384 | } 385 | return 0; 386 | } 387 | 388 | /** 389 | * 处理"客户端处理请求连接"事件 390 | * @return 391 | */ 392 | int handler_5(int epfd, const struct epoll_event *e) { 393 | struct connection *conn = (struct connection *) e->data.ptr; 394 | struct connection *uc = ((struct client_conn *) conn->ptr)->user_conn; 395 | 396 | if (e->events & EPOLLIN) { 397 | if (read_write_client(conn) == -1) { 398 | tag_close_conn(conn, tag); 399 | return -1; 400 | } 401 | } 402 | 403 | if (e->events & EPOLLOUT) { 404 | if (read_write_user(uc) == -1) { 405 | tag_close_conn(conn, tag); 406 | return -1; 407 | } 408 | } 409 | 410 | return 0; 411 | } 412 | 413 | /** 414 | * 处理"用户的请求连接"事件 415 | * @return 416 | */ 417 | int handler_6(int epfd, const struct epoll_event *e) { 418 | struct connection *conn = (struct connection *) e->data.ptr; 419 | struct connection *cc = ((struct user_conn *) conn->ptr)->client_conn; 420 | 421 | if (e->events & EPOLLIN) { 422 | if (read_write_user(conn) == -1) { 423 | tag_close_conn(conn, tag); 424 | return -1; 425 | } 426 | } 427 | 428 | if (e->events & EPOLLOUT) { 429 | if (read_write_client(cc) == -1) { 430 | tag_close_conn(conn, tag); 431 | return -1; 432 | } 433 | } 434 | return 0; 435 | } -------------------------------------------------------------------------------- /server/server.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by maqian on 2018/9/7. 3 | // 4 | 5 | #include 6 | #include "../common/global.h" 7 | #include "../structure/queue.h" 8 | 9 | #ifndef TUNNEL_SERVER_H 10 | #define TUNNEL_SERVER_H 11 | 12 | #define S_LISTEN_CLIENT 1 13 | #define S_LISTEN_USER 2 14 | #define S_UNKNOWN 3 15 | #define S_TUNNEL 4 16 | #define S_CLIENT 5 17 | #define S_USER 6 18 | 19 | struct connection { 20 | int fd; 21 | char type; //1.监听客户端请求的Socket 2.监听用户请求的Socket 3.未知 4.与客户端建立的隧道 5.客户端处理请求连接 6.用户的请求连接 22 | void *write_buf; //等待写入的数据 23 | size_t len; //等待写入数据的长度 24 | boolean tag_close; //标记已关闭 25 | void *ptr; //额外数据指针 26 | }; 27 | 28 | struct listen_user { 29 | struct connection *tunnel_conn; 30 | int port; //监听的端口号 31 | Queue queue; 32 | }; 33 | 34 | struct tunnel { 35 | struct connection *listen_user_conn; 36 | char *token; //客户端处理请求连接时需要验证Token 37 | }; 38 | 39 | struct client_conn { 40 | struct connection *user_conn; 41 | }; 42 | 43 | struct user_conn { 44 | struct connection *client_conn; 45 | }; 46 | 47 | int start(int port, char *password); 48 | 49 | #endif //TUNNEL_SERVER_H 50 | -------------------------------------------------------------------------------- /server/tunnel.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include "tunnel.h" 10 | #include "server.h" 11 | #include "common.h" 12 | #include "listener.h" 13 | #include "../common/command.h" 14 | 15 | #define TOKEN_LEN 30 16 | 17 | struct entity { 18 | int fd; 19 | struct connection *conn; 20 | struct entity *next; 21 | }; 22 | 23 | struct hash_map { 24 | struct entity **arr; 25 | int size; 26 | }; 27 | 28 | struct hash_map map; 29 | 30 | /** 31 | * 计算hash值 32 | * @param mp 33 | * @param fd 34 | * @return 35 | */ 36 | int hash(struct hash_map *mp, int fd) { 37 | return fd % mp->size; 38 | } 39 | 40 | /** 41 | * 初始化Tunnel散列 42 | */ 43 | void initTunnelMap(int size) { 44 | if (size <= 0) { 45 | size = 10; //如果size为非法值,将size设为10 46 | } 47 | map.arr = malloc(sizeof(struct entity *) * size); 48 | memset(map.arr, 0, sizeof(struct entity *) * size); //数据初始化--清零 49 | map.size = size; 50 | } 51 | 52 | void put_tunnel(int fd, struct connection *conn) { 53 | int h = hash(&map, fd); 54 | struct entity *e = malloc(sizeof(struct entity)); 55 | e->fd = fd; 56 | e->conn = conn; 57 | e->next = map.arr[h]; 58 | map.arr[h] = e; 59 | } 60 | 61 | struct connection *get_tunnel(int fd) { 62 | int h = hash(&map, fd); 63 | struct entity *e = map.arr[h]; 64 | while (e != null) { 65 | if (e->fd == fd) { 66 | return e->conn; 67 | } 68 | e = e->next; 69 | } 70 | return null; 71 | } 72 | 73 | boolean remove_tunnel(int fd) { 74 | int h = hash(&map, fd); 75 | for (struct entity **curr = &map.arr[h]; *curr;) { 76 | struct entity *e = *curr; 77 | if (e->fd == fd) { 78 | *curr = e->next; 79 | free(e); 80 | return true; 81 | } else 82 | curr = &e->next; 83 | } 84 | return false; 85 | } 86 | 87 | char *gen_token() { 88 | char *str = malloc(TOKEN_LEN + 1); 89 | srand(time(NULL));//通过时间函数设置随机数种子,使得每次运行结果随机。 90 | for (int i = 0; i < TOKEN_LEN; i++) { 91 | int flag = rand() % 3; 92 | switch (flag) { 93 | case 0: 94 | str[i] = rand() % 26 + 'a'; 95 | break; 96 | case 1: 97 | str[i] = rand() % 26 + 'A'; 98 | break; 99 | case 2: 100 | str[i] = rand() % 10 + '0'; 101 | break; 102 | } 103 | } 104 | str[TOKEN_LEN] = 0; 105 | return str; 106 | } 107 | 108 | int create_tunnel(int epfd, struct connection *conn) { 109 | int listenfd = create_listener(0, 200, false, true); 110 | if (listenfd == -1) { 111 | return -1; 112 | } 113 | 114 | //获取监听的端口号 115 | struct sockaddr_in addr; 116 | socklen_t sin_size = sizeof(struct sockaddr_in); 117 | getsockname(listenfd, (struct sockaddr *) &addr, &sin_size); 118 | //设置连接的相关信息 119 | struct listen_user *lu = malloc(sizeof(struct listen_user)); 120 | lu->tunnel_conn = conn; 121 | lu->port = ntohs(addr.sin_port); 122 | lu->queue = newQueue(sizeof(struct connection *)); 123 | 124 | struct connection *listen_user_conn = create_conn(listenfd, S_LISTEN_USER, lu); 125 | 126 | struct tunnel *t = malloc(sizeof(struct tunnel)); 127 | t->listen_user_conn = listen_user_conn; 128 | t->token = gen_token(); 129 | 130 | conn->type = S_TUNNEL; //更改类型为隧道 131 | conn->ptr = t; 132 | 133 | struct epoll_event ev; 134 | ev.data.ptr = listen_user_conn; 135 | ev.events = EPOLLIN | EPOLLET;//边缘触发选项 136 | 137 | // 设置epoll的事件 138 | if (epoll_ctl(epfd, EPOLL_CTL_ADD, listenfd, &ev) == -1) { 139 | log_err("Set epoll_ctl"); 140 | return -1; 141 | } 142 | 143 | //将tunnel连接插入散列 144 | put_tunnel(conn->fd, conn); 145 | char msg[256]; 146 | sprintf(msg, "%s %d %d %s\n", SUCCESS, conn->fd, lu->port, t->token); 147 | // 通知客户端隧道创建成功(success 隧道FD 监听用户请求的端口号 Pull请求的Token) 148 | if (write_data(conn, msg, strlen(msg)) == -1) { 149 | return -1; 150 | } 151 | 152 | struct sockaddr_in in_addr = {0}; 153 | socklen_t nl = sizeof(in_addr); 154 | getpeername(conn->fd, (struct sockaddr *) &in_addr, &nl); 155 | char info[256]; 156 | sprintf(info, "Accept client IP:%s\n", inet_ntoa(in_addr.sin_addr)); 157 | log_info(info); 158 | //printf("Change type to tunnel.\n"); 159 | return listenfd; 160 | } -------------------------------------------------------------------------------- /server/tunnel.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by maqian on 2018/9/11. 3 | // 4 | #include "server.h" 5 | 6 | #ifndef TUNNEL_TUNNEL_H 7 | #define TUNNEL_TUNNEL_H 8 | 9 | /** 10 | * 初始化Tunnel散列 11 | * @param size 散列大小 12 | */ 13 | void initTunnelMap(int size); 14 | 15 | /** 16 | * 创建 tunnel 17 | * @param epfd 18 | * @param conn 19 | * @return 20 | */ 21 | int create_tunnel(int epfd, struct connection *conn); 22 | 23 | struct connection *get_tunnel(int fd); 24 | 25 | boolean remove_tunnel(int fd); 26 | 27 | #endif //TUNNEL_TUNNEL_H 28 | -------------------------------------------------------------------------------- /structure/array.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "array.h" 5 | #include "../common/global.h" 6 | 7 | boolean isOutRange(Array arr, int index) { 8 | if (index > arr->size - 1 || index < 0) { 9 | return true; 10 | } 11 | 12 | return false; 13 | } 14 | 15 | boolean nonOutRange(Array arr, int index) { 16 | return !isOutRange(arr, index); 17 | } 18 | 19 | void rangeCheck(Array arr, int index) { 20 | if (isOutRange(arr, index)) { 21 | error("Array index out range!"); 22 | } 23 | } 24 | 25 | boolean isFullCapacity(Array arr) { 26 | return arr->size == arr->capacity; 27 | } 28 | 29 | void expand(Array arr) { 30 | int newCapacity = arr->capacity * ARRAY_EXPAND_INTENSITY + 1; 31 | 32 | void *newData = malloc(newCapacity * arr->typeSize); 33 | memcpy(newData, arr->data, arr->size * arr->typeSize); 34 | free(arr->data); 35 | arr->data = newData; 36 | arr->capacity = newCapacity; 37 | } 38 | 39 | Array newArray(int typeSize, int initialCapacity) { 40 | if (initialCapacity <= 0) { 41 | error("initialCapacity must be greater than 0!"); 42 | } 43 | Array arr = malloc(sizeof(struct ArrayStructure)); 44 | arr->data = malloc(initialCapacity * typeSize); 45 | arr->typeSize = typeSize; 46 | arr->capacity = initialCapacity; 47 | arr->size = 0; 48 | return arr; 49 | } 50 | 51 | Array newArrayDefault(int typeSize) { 52 | return newArray(typeSize, ARRAY_DEFAULT_CAPACITY); 53 | } 54 | 55 | void addArray(Array arr, void *item) { 56 | 57 | if (isFullCapacity(arr)) { 58 | expand(arr); 59 | } 60 | 61 | memcpy(arr->data + arr->size * arr->typeSize, item, arr->typeSize); 62 | arr->size++; 63 | } 64 | 65 | void insertArray(Array arr, int index, void *item) { 66 | rangeCheck(arr, index); 67 | 68 | if (isFullCapacity(arr)) { 69 | expand(arr); 70 | } 71 | 72 | for (int i = arr->size; i > index; i--) { 73 | memcpy(arr->data + i * arr->typeSize, arr->data + (i - 1) * arr->typeSize, arr->typeSize); 74 | } 75 | memcpy(arr->data + index * arr->typeSize, item, arr->typeSize); 76 | arr->size++; 77 | } 78 | 79 | void setArray(Array arr, int index, void *item) { 80 | rangeCheck(arr, index); 81 | memcpy(arr->data + index * arr->typeSize, item, arr->typeSize); 82 | } 83 | 84 | int indexOfItemInArray(Array arr, void *item) { 85 | for (int i = 0; i < arr->size; i++) { 86 | if (memeq(item, arr->data + i * arr->typeSize, arr->typeSize)) { 87 | return i; 88 | } 89 | } 90 | return -1; 91 | } 92 | 93 | int removeArrayByItem(Array arr, void *item) { 94 | int i = indexOfItemInArray(arr, item); 95 | if (i >= 0) { 96 | removeArray(arr, i); 97 | return i; 98 | } 99 | return i; 100 | } 101 | 102 | void removeArray(Array arr, int index) { 103 | rangeCheck(arr, index); 104 | 105 | for (int i = index + 1; i < arr->size; i++) { 106 | memcpy(arr->data + (i - 1) * arr->typeSize, arr->data + i * arr->typeSize, arr->typeSize); 107 | } 108 | arr->size--; 109 | } 110 | 111 | void *getArray(Array arr, int index, void *dst) { 112 | rangeCheck(arr, index); 113 | 114 | memcpy(dst, arr->data + index * arr->typeSize, arr->typeSize); 115 | 116 | return dst; 117 | } 118 | 119 | void resetArrayEmpty(Array arr) { 120 | arr->size = 0; 121 | } 122 | 123 | void freeArray(Array arr) { 124 | free(arr->data); 125 | free(arr); 126 | } 127 | 128 | void addArrayForInt(Array arr, int item) { 129 | addArray(arr, &item); 130 | } 131 | 132 | void addArrayForLong(Array arr, long item) { 133 | addArray(arr, &item); 134 | } 135 | 136 | void addArrayForDouble(Array arr, double item) { 137 | addArray(arr, &item); 138 | } 139 | 140 | void addArrayForChar(Array arr, char item) { 141 | addArray(arr, &item); 142 | } 143 | 144 | void addArrayForPointer(Array arr, void *item) { 145 | addArray(arr, &item); 146 | } 147 | 148 | void insertArrayForInt(Array arr, int index, int item) { 149 | insertArray(arr, index, &item); 150 | } 151 | 152 | void insertArrayForLong(Array arr, int index, long item) { 153 | insertArray(arr, index, &item); 154 | } 155 | 156 | void insertArrayForDouble(Array arr, int index, double item) { 157 | insertArray(arr, index, &item); 158 | } 159 | 160 | void insertArrayForChar(Array arr, int index, char item) { 161 | insertArray(arr, index, &item); 162 | } 163 | 164 | void insertArrayForPointer(Array arr, int index, void *item) { 165 | insertArray(arr, index, &item); 166 | } 167 | 168 | void setArrayForPointer(Array arr, int index, void *item) { 169 | setArray(arr, index, &item); 170 | } 171 | 172 | int getArrayForInt(Array arr, int index) { 173 | int item; 174 | getArray(arr, index, &item); 175 | return item; 176 | } 177 | 178 | long getArrayForLong(Array arr, int index) { 179 | long item; 180 | getArray(arr, index, &item); 181 | return item; 182 | } 183 | 184 | double getArrayForDouble(Array arr, int index) { 185 | double item; 186 | getArray(arr, index, &item); 187 | return item; 188 | } 189 | 190 | char getArrayForChar(Array arr, int index) { 191 | char item; 192 | getArray(arr, index, &item); 193 | return item; 194 | } 195 | 196 | void *getArrayForPointer(Array arr, int index) { 197 | void *item; 198 | getArray(arr, index, &item); 199 | return item; 200 | } -------------------------------------------------------------------------------- /structure/array.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by maqian on 2018/6/15. 3 | // 4 | 5 | #ifndef LEARN_C_ARRAY_H 6 | #define LEARN_C_ARRAY_H 7 | 8 | #include "../common/global.h" 9 | 10 | #define ARRAY_DEFAULT_CAPACITY 10 11 | #define ARRAY_EXPAND_INTENSITY 1.6 12 | 13 | typedef struct ArrayStructure { 14 | 15 | void *data; 16 | 17 | int typeSize; 18 | 19 | int size; 20 | 21 | int capacity; 22 | 23 | } *Array; 24 | 25 | /** 26 | * 创建Array 27 | * @param typeSize 28 | * @param initialCapacity 29 | * @return 30 | */ 31 | Array newArray(int typeSize, int initialCapacity); 32 | 33 | /** 34 | * 创建Array 默认大小 35 | * @param typeSize 36 | * @return 37 | */ 38 | Array newArrayDefault(int typeSize); 39 | 40 | /** 41 | * 添加元素 42 | * @param arr 43 | * @param item 44 | */ 45 | void addArray(Array arr, void *item); 46 | 47 | /** 48 | * 插入元素到指定位置 49 | * @param arr 50 | * @param index 51 | * @param item 52 | */ 53 | void insertArray(Array arr, int index, void *item); 54 | 55 | /** 56 | * 设置指定元素值 57 | * @param arr 58 | * @param index 59 | * @param item 60 | */ 61 | void setArray(Array arr, int index, void *item); 62 | 63 | /** 64 | * 在Array中item的位置 65 | * @param arr 66 | * @param item 67 | * @return 68 | */ 69 | int indexOfItemInArray(Array arr, void *item); 70 | 71 | /** 72 | * 在Array中是否存在某元素 73 | * @param arr 74 | * @param item 75 | * @return 76 | */ 77 | int removeArrayByItem(Array arr, void *item); 78 | 79 | /** 80 | * 删除元素 81 | * @param arr 82 | * @param index 83 | */ 84 | void removeArray(Array arr, int index); 85 | 86 | /** 87 | * 获取元素 88 | * @param arr 89 | * @param index 90 | * @param dst 91 | * @return 92 | */ 93 | void *getArray(Array arr, int index, void *dst); 94 | 95 | /** 96 | * 置空 97 | * @param arr 98 | */ 99 | void resetArrayEmpty(Array arr); 100 | 101 | /** 102 | * 销毁Array 103 | * @param arr 104 | */ 105 | void freeArray(Array arr); 106 | 107 | /** 108 | * 插入Int 109 | * @param arr 110 | * @param item 111 | */ 112 | void addArrayForInt(Array arr, int item); 113 | 114 | /** 115 | * 插入Long 116 | * @param arr 117 | * @param item 118 | */ 119 | void addArrayForLong(Array arr, long item); 120 | 121 | /** 122 | * 插入Double 123 | * @param arr 124 | * @param item 125 | */ 126 | void addArrayForDouble(Array arr, double item); 127 | 128 | /** 129 | * 插入Char 130 | * @param arr 131 | * @param item 132 | */ 133 | void addArrayForChar(Array arr, char item); 134 | 135 | /** 136 | * 插入指针 137 | * @param arr 138 | * @param item 139 | */ 140 | void addArrayForPointer(Array arr, void *item); 141 | 142 | /** 143 | * 指定位置插入Int 144 | * @param arr 145 | * @param item 146 | */ 147 | void insertArrayForInt(Array arr, int index, int item); 148 | 149 | /** 150 | * 指定位置插入Long 151 | * @param arr 152 | * @param item 153 | */ 154 | void insertArrayForLong(Array arr, int index, long item); 155 | 156 | /** 157 | * 指定位置插入Double 158 | * @param arr 159 | * @param item 160 | */ 161 | void insertArrayForDouble(Array arr, int index, double item); 162 | 163 | /** 164 | * 指定位置插入Char 165 | * @param arr 166 | * @param item 167 | */ 168 | void insertArrayForChar(Array arr, int index, char item); 169 | 170 | /** 171 | * 指定位置插入指针 172 | * @param arr 173 | * @param item 174 | */ 175 | void insertArrayForPointer(Array arr, int index, void *item); 176 | 177 | 178 | void setArrayForPointer(Array arr, int index, void *item); 179 | 180 | /** 181 | * 获取Int数据 182 | * @param arr 183 | * @param index 184 | */ 185 | int getArrayForInt(Array arr, int index); 186 | 187 | /** 188 | * 获取Long数据 189 | * @param arr 190 | * @param index 191 | */ 192 | long getArrayForLong(Array arr, int index); 193 | 194 | /** 195 | * 获取Double数据 196 | * @param arr 197 | * @param index 198 | */ 199 | double getArrayForDouble(Array arr, int index); 200 | 201 | /** 202 | * 获取Char数据 203 | * @param arr 204 | * @param index 205 | */ 206 | char getArrayForChar(Array arr, int index); 207 | 208 | /** 209 | * 获取指针数据 210 | * @param arr 211 | * @param index 212 | */ 213 | void *getArrayForPointer(Array arr, int index); 214 | 215 | #endif //LEARN_C_ARRAY_H 216 | -------------------------------------------------------------------------------- /structure/queue.c: -------------------------------------------------------------------------------- 1 | #include "queue.h" 2 | #include "../common/global.h" 3 | #include 4 | #include 5 | 6 | static void resetNull(void *dst, int size) { 7 | char *b = dst; 8 | for (int i = 0; i < size; ++i) { 9 | b[i] = 0; 10 | } 11 | } 12 | 13 | Queue newQueue(int typeSize) { 14 | Queue queue = malloc(sizeof(struct QueueStructure)); 15 | queue->typeSize = typeSize; 16 | queue->head = null; 17 | queue->rear = null; 18 | queue->size = 0; 19 | return queue; 20 | } 21 | 22 | void inQueue(Queue q, void *item) { 23 | QueueDataPtr qdp = malloc(sizeof(QueueData)); 24 | qdp->data = memcpy(malloc(q->typeSize), item, q->typeSize); 25 | qdp->next = null; 26 | if (isQueueEmpty(q)) { 27 | q->head = qdp; 28 | } else { 29 | q->rear->next = qdp; 30 | } 31 | q->rear = qdp; 32 | q->size++; 33 | } 34 | 35 | void *outQueue(Queue q, void *dst) { 36 | if (isQueueEmpty(q)) { 37 | error("Queue is empty!"); 38 | } 39 | 40 | memcpy(dst, q->head->data, q->typeSize); 41 | QueueDataPtr temp = q->head; 42 | q->head = q->head->next; 43 | free(temp->data); 44 | free(temp); 45 | q->size--; 46 | return dst; 47 | } 48 | 49 | int isQueueEmpty(Queue q) { 50 | return q->size < 1; 51 | } 52 | 53 | void resetQueueEmpty(Queue q) { 54 | while (q->head) { 55 | QueueDataPtr cur = q->head; 56 | q->head = q->head->next; 57 | free(cur->data); 58 | free(cur); 59 | } 60 | q->size = 0; 61 | } 62 | 63 | void freeQueue(Queue q) { 64 | resetQueueEmpty(q); 65 | free(q); 66 | } 67 | 68 | 69 | void inQueueForInt(Queue q, int item) { 70 | inQueue(q, &item); 71 | } 72 | 73 | void inQueueForLong(Queue q, long item) { 74 | inQueue(q, &item); 75 | } 76 | 77 | void inQueueForDouble(Queue q, double item) { 78 | inQueue(q, &item); 79 | } 80 | 81 | void inQueueForChar(Queue q, char item) { 82 | inQueue(q, &item); 83 | } 84 | 85 | void inQueueForPointer(Queue q, void *item) { 86 | inQueue(q, &item); 87 | } 88 | 89 | 90 | int outQueueForInt(Queue q) { 91 | int item; 92 | outQueue(q, &item); 93 | return item; 94 | } 95 | 96 | long outQueueForLong(Queue q) { 97 | long item; 98 | outQueue(q, &item); 99 | return item; 100 | } 101 | 102 | double outQueueForDouble(Queue q) { 103 | double item; 104 | outQueue(q, &item); 105 | return item; 106 | } 107 | 108 | char outQueueForChar(Queue q) { 109 | char item; 110 | outQueue(q, &item); 111 | return item; 112 | } 113 | 114 | void *outQueueForPointer(Queue q) { 115 | void *item; 116 | outQueue(q, &item); 117 | return item; 118 | } -------------------------------------------------------------------------------- /structure/queue.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by maqian on 2018/6/15. 3 | // 4 | 5 | #ifndef LEARN_C_QUEUE_H 6 | #define LEARN_C_QUEUE_H 7 | typedef struct QueueNode { 8 | 9 | void *data; 10 | 11 | struct QueueNode *next; 12 | 13 | } QueueData, *QueueDataPtr; 14 | 15 | typedef struct QueueStructure { 16 | 17 | QueueData *head;//队列头指针 18 | 19 | QueueData *rear;//队列尾指针 20 | 21 | int typeSize;//类型占用字节数 22 | 23 | int size;//元素个数 24 | 25 | } *Queue; 26 | 27 | /** 28 | * 创建队列 29 | * @param typeSize 30 | * @return 31 | */ 32 | Queue newQueue(int typeSize); 33 | 34 | /** 35 | * 队列插入 36 | * @param sp 37 | * @param item 38 | */ 39 | void inQueue(Queue q, void *item); 40 | 41 | /** 42 | * 队列弹出 43 | * @param sp 44 | * @param dst 45 | * @return 46 | */ 47 | void *outQueue(Queue q, void *dst); 48 | 49 | /** 50 | * 队列是否为空 51 | * @param sp 52 | * @return 53 | */ 54 | int isQueueEmpty(Queue q); 55 | 56 | /** 57 | * 重置为空队列 58 | * @param sp 59 | */ 60 | void resetQueueEmpty(Queue q); 61 | 62 | /** 63 | * 销毁队列 64 | * @param s 65 | */ 66 | void freeQueue(Queue q); 67 | 68 | 69 | /** 70 | * 插入int 71 | * @param sp 72 | * @param item 73 | */ 74 | void inQueueForInt(Queue q, int item); 75 | 76 | /** 77 | * 插入long 78 | * @param sp 79 | * @param item 80 | */ 81 | void inQueueForLong(Queue q, long item); 82 | 83 | /** 84 | * 插入double 85 | * @param sp 86 | * @param item 87 | */ 88 | void inQueueForDouble(Queue q, double item); 89 | 90 | /** 91 | * 插入char 92 | * @param sp 93 | * @param item 94 | */ 95 | void inQueueForChar(Queue q, char item); 96 | 97 | /** 98 | * 插入指针 99 | * @param sp 100 | * @param item 101 | */ 102 | void inQueueForPointer(Queue q, void *item); 103 | 104 | 105 | /** 106 | * 出队列int 107 | * @param sp 108 | * @param item 109 | */ 110 | int outQueueForInt(Queue q); 111 | 112 | /** 113 | * 出队列long 114 | * @param sp 115 | * @param item 116 | */ 117 | long outQueueForLong(Queue q); 118 | 119 | /** 120 | * 出队列double 121 | * @param sp 122 | * @param item 123 | */ 124 | double outQueueForDouble(Queue q); 125 | 126 | /** 127 | * 出队列char 128 | * @param sp 129 | * @param item 130 | */ 131 | char outQueueForChar(Queue q); 132 | 133 | /** 134 | * 出队列指针 135 | * @param sp 136 | * @param item 137 | */ 138 | void *outQueueForPointer(Queue q); 139 | 140 | #endif //LEARN_C_QUEUE_H 141 | -------------------------------------------------------------------------------- /structure/stack.c: -------------------------------------------------------------------------------- 1 | #include "stack.h" 2 | #include "../common/global.h" 3 | #include 4 | #include 5 | 6 | static void resetNull(void *dst, int size) { 7 | char *b = dst; 8 | for (int i = 0; i < size; ++i) { 9 | b[i] = 0; 10 | } 11 | } 12 | 13 | Stack newStack(int typeSize) { 14 | Stack stack = malloc(sizeof(struct StackStructure)); 15 | stack->typeSize = typeSize; 16 | stack->head = null; 17 | stack->size = 0; 18 | return stack; 19 | } 20 | 21 | void inStack(Stack sp, void *item) { 22 | StackDataPtr sdp = malloc(sizeof(StackData)); 23 | sdp->data = memcpy(malloc(sp->typeSize), item, sp->typeSize); 24 | sdp->next = sp->head; 25 | sp->head = sdp; 26 | sp->size++; 27 | } 28 | 29 | void *outStack(Stack sp, void *dst) { 30 | if (isStackEmpty(sp)) { 31 | error("Stack is empty!"); 32 | } 33 | 34 | memcpy(dst, sp->head->data, sp->typeSize); 35 | StackDataPtr temp = sp->head; 36 | sp->head = sp->head->next; 37 | free(temp->data); 38 | free(temp); 39 | sp->size--; 40 | return dst; 41 | } 42 | 43 | int isStackEmpty(Stack sp) { 44 | return sp->size < 1; 45 | } 46 | 47 | void resetStackEmpty(Stack sp) { 48 | while (sp->head) { 49 | StackDataPtr cur = sp->head; 50 | sp->head = sp->head->next; 51 | free(cur->data); 52 | free(cur); 53 | } 54 | sp->size = 0; 55 | } 56 | 57 | void freeStack(Stack s) { 58 | resetStackEmpty(s); 59 | free(s); 60 | } 61 | 62 | 63 | void inStackForInt(Stack sp, int item) { 64 | inStack(sp, &item); 65 | } 66 | 67 | void inStackForLong(Stack sp, long item) { 68 | inStack(sp, &item); 69 | } 70 | 71 | void inStackForDouble(Stack sp, double item) { 72 | inStack(sp, &item); 73 | } 74 | 75 | void inStackForChar(Stack sp, char item) { 76 | inStack(sp, &item); 77 | } 78 | 79 | 80 | int outStackForInt(Stack s) { 81 | int item; 82 | outStack(s, &item); 83 | return item; 84 | } 85 | 86 | long outStackForLong(Stack s) { 87 | long item; 88 | outStack(s, &item); 89 | return item; 90 | } 91 | 92 | double outStackForDouble(Stack s) { 93 | double item; 94 | outStack(s, &item); 95 | return item; 96 | } 97 | 98 | char outStackForChar(Stack s) { 99 | char item; 100 | outStack(s, &item); 101 | return item; 102 | } -------------------------------------------------------------------------------- /structure/stack.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by maqian on 2018/6/15. 3 | // 4 | 5 | #ifndef LEARN_C_STACK_H 6 | #define LEARN_C_STACK_H 7 | 8 | typedef struct StackNode { 9 | 10 | void *data; 11 | 12 | struct StackNode *next; 13 | 14 | } StackData, *StackDataPtr; 15 | 16 | typedef struct StackStructure{ 17 | 18 | StackData *head;//栈数据头指针 19 | 20 | int typeSize;//类型占用字节数 21 | 22 | int size;//元素个数 23 | 24 | } *Stack; 25 | 26 | /** 27 | * 创建栈 28 | * @param typeSize 29 | * @return 30 | */ 31 | Stack newStack(int typeSize); 32 | 33 | /** 34 | * 栈插入 35 | * @param sp 36 | * @param item 37 | */ 38 | void inStack(Stack s, void *item); 39 | 40 | /** 41 | * 栈弹出 42 | * @param sp 43 | * @param dst 44 | * @return 45 | */ 46 | void *outStack(Stack s, void *dst); 47 | 48 | /** 49 | * 栈是否为空 50 | * @param sp 51 | * @return 52 | */ 53 | int isStackEmpty(Stack s); 54 | 55 | /** 56 | * 重置为空栈 57 | * @param sp 58 | */ 59 | void resetStackEmpty(Stack s); 60 | 61 | /** 62 | * 销毁栈 63 | * @param s 64 | */ 65 | void freeStack(Stack s); 66 | 67 | 68 | /** 69 | * 插入int 70 | * @param sp 71 | * @param item 72 | */ 73 | void inStackForInt(Stack s, int item); 74 | 75 | /** 76 | * 插入long 77 | * @param sp 78 | * @param item 79 | */ 80 | void inStackForLong(Stack s, long item); 81 | 82 | /** 83 | * 插入double 84 | * @param sp 85 | * @param item 86 | */ 87 | void inStackForDouble(Stack s, double item); 88 | 89 | /** 90 | * 插入char 91 | * @param sp 92 | * @param item 93 | */ 94 | void inStackForChar(Stack s, char item); 95 | 96 | 97 | /** 98 | * 出栈int 99 | * @param sp 100 | * @param item 101 | */ 102 | int outStackForInt(Stack s); 103 | 104 | /** 105 | * 出栈long 106 | * @param sp 107 | * @param item 108 | */ 109 | long outStackForLong(Stack s); 110 | 111 | /** 112 | * 出栈double 113 | * @param sp 114 | * @param item 115 | */ 116 | double outStackForDouble(Stack s); 117 | 118 | /** 119 | * 出栈char 120 | * @param sp 121 | * @param item 122 | */ 123 | char outStackForChar(Stack s); 124 | 125 | #endif //LEARN_C_STACK_H 126 | -------------------------------------------------------------------------------- /tunnel.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "common/global.h" 4 | #include "client/client.h" 5 | 6 | #define BUF_SIZE 100 7 | 8 | int main() { 9 | char *buf = malloc(BUF_SIZE); 10 | int r_port, l_port; 11 | char ip[BUF_SIZE], password[BUF_SIZE]; 12 | printf("Enter server IP:"); 13 | scanf("%s", ip); 14 | clear_stdin(); 15 | 16 | printf("Enter server port(default 8877):"); 17 | enter(buf, BUF_SIZE, "8877"); 18 | r_port = atoi(buf); 19 | 20 | printf("Enter connection password(default maqian.cc):"); 21 | enter(password, BUF_SIZE, "maqian.cc"); 22 | 23 | printf("Enter local port:"); 24 | scanf("%s", buf); 25 | clear_stdin(); 26 | l_port = atoi(buf); 27 | free(buf); 28 | printf("Server IP:%s, Server Port:%d, Password:%s, Local Port:%d\n", ip, r_port, password, l_port); 29 | return create_tunnel(ip, r_port, l_port, password); 30 | } -------------------------------------------------------------------------------- /tunneld.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include "server/server.h" 11 | #include "server/common.h" 12 | #include "common/global.h" 13 | 14 | #define BUF_SIZE 100 15 | 16 | int init_daemon(); 17 | 18 | int main() { 19 | char *buf = malloc(BUF_SIZE); 20 | int port; 21 | char password[BUF_SIZE]; 22 | printf("Enter listening port(default 8877):"); 23 | enter(buf, BUF_SIZE, "8877"); 24 | port = atoi(buf); 25 | printf("Enter connection password(default maqian.cc):"); 26 | enter(password, BUF_SIZE, "maqian.cc"); 27 | free(buf); 28 | printf("Port:%d, Password:%s\n", port, password); 29 | if (is_use(port)) { 30 | printf("The port already in use.\n"); 31 | return -1; 32 | } 33 | printf("Listening...\n"); 34 | init_daemon(); 35 | start(port, password); 36 | return 0; 37 | } 38 | 39 | int init_daemon() { 40 | int pid; 41 | int i; 42 | 43 | //忽略终端I/O信号,STOP信号 44 | signal(SIGTTOU, SIG_IGN); 45 | signal(SIGTTIN, SIG_IGN); 46 | signal(SIGTSTP, SIG_IGN); 47 | signal(SIGHUP, SIG_IGN); 48 | 49 | pid = fork(); 50 | if (pid > 0) { 51 | exit(0); //结束父进程,使得子进程成为后台进程 52 | } else if (pid < 0) { 53 | return -1; 54 | } 55 | 56 | //建立一个新的进程组,在这个新的进程组中,子进程成为这个进程组的首进程,以使该进程脱离所有终端 57 | setsid(); 58 | 59 | //再次新建一个子进程,退出父进程,保证该进程不是进程组长,同时让该进程无法再打开一个新的终端 60 | pid = fork(); 61 | if (pid > 0) { 62 | exit(0); 63 | } else if (pid < 0) { 64 | return -1; 65 | } 66 | 67 | //关闭所有从父进程继承的不再需要的文件描述符 68 | for (i = 0; i < NOFILE; close(i++)); 69 | 70 | //改变工作目录,使得进程不与任何文件系统联系 71 | chdir("/"); 72 | 73 | //将文件当时创建屏蔽字设置为0 74 | umask(0); 75 | 76 | //忽略SIGCHLD信号 77 | signal(SIGCHLD, SIG_IGN); 78 | 79 | return 0; 80 | } --------------------------------------------------------------------------------