├── echo-server ├── .gitignore ├── Cargo.toml ├── Cargo.lock └── src │ └── main.rs ├── sleep-server ├── .gitignore ├── Cargo.toml ├── src │ └── main.rs └── Cargo.lock ├── Makefile ├── util.h ├── server-recv-test.py ├── README.md ├── tcp-send-test.c ├── tcp-recv-test.c └── tcp-keepalive-test.c /echo-server/.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | -------------------------------------------------------------------------------- /sleep-server/.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | all: tcp-send-test tcp-recv-test tcp-keepalive-test 2 | 3 | tcp-send-test: 4 | 5 | tcp-recv-test: 6 | 7 | tcp-keepalive-test: 8 | 9 | .PHONY: clean 10 | 11 | clean: 12 | rm -f tcp-send-test tcp-recv-test tcp-keepalive-test 13 | -------------------------------------------------------------------------------- /echo-server/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "echo-server" 3 | version = "0.1.0" 4 | authors = ["Anders Trier "] 5 | edition = "2018" 6 | 7 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 8 | 9 | [dependencies] 10 | rlimit = "0.3.0" 11 | -------------------------------------------------------------------------------- /sleep-server/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "sleep-server" 3 | version = "0.1.0" 4 | authors = ["Anders Trier "] 5 | edition = "2018" 6 | 7 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 8 | 9 | [dependencies] 10 | futures = "0.3" 11 | rlimit = "0.3.0" 12 | 13 | [dependencies.async-std] 14 | version = "1.6" 15 | features = ["attributes"] 16 | -------------------------------------------------------------------------------- /util.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-2.0+ 2 | #ifndef __UTIL_H 3 | #define __UTIL_H 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | void msg(const char* format, ... ) 11 | { 12 | struct timeval tv = {}; 13 | va_list arglist; 14 | 15 | gettimeofday(&tv, NULL); 16 | 17 | printf("[%-.8ld.%-.6ld] ", tv.tv_sec, tv.tv_usec); 18 | va_start(arglist, format); 19 | vprintf(format, arglist); 20 | va_end(arglist); 21 | fflush(stdout); 22 | } 23 | 24 | #endif /* __UTIL_H */ 25 | -------------------------------------------------------------------------------- /server-recv-test.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # socat TCP-LISTEN:27182,reuseaddr,fork EXEC:"timeout $((60*60*6)) ./tcptester.py" 3 | import sys, time 4 | 5 | try: 6 | sleeptime = sys.stdin.readline(64) 7 | except EOFError: 8 | # Connection was closed 9 | sys.exit() 10 | 11 | try: 12 | sleeptimeint = int(sleeptime) 13 | except ValueError: 14 | # Not an integer 15 | sys.exit() 16 | 17 | if sleeptimeint < 0 or sleeptimeint > 60*60*24: 18 | sys.exit() 19 | 20 | time.sleep(sleeptimeint) 21 | 22 | print(sleeptimeint) 23 | -------------------------------------------------------------------------------- /echo-server/Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | [[package]] 4 | name = "cfg-if" 5 | version = "0.1.10" 6 | source = "registry+https://github.com/rust-lang/crates.io-index" 7 | checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" 8 | 9 | [[package]] 10 | name = "echo-server" 11 | version = "0.1.0" 12 | dependencies = [ 13 | "rlimit", 14 | ] 15 | 16 | [[package]] 17 | name = "libc" 18 | version = "0.2.88" 19 | source = "registry+https://github.com/rust-lang/crates.io-index" 20 | checksum = "03b07a082330a35e43f63177cc01689da34fbffa0105e1246cf0311472cac73a" 21 | 22 | [[package]] 23 | name = "rlimit" 24 | version = "0.3.0" 25 | source = "registry+https://github.com/rust-lang/crates.io-index" 26 | checksum = "e6d26e65e82a1e2628c5f209ec12f4508fa50e644bd2f264138e60129d61eae8" 27 | dependencies = [ 28 | "cfg-if", 29 | "libc", 30 | ] 31 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # TCP established connection idle-timeout tests for NAT implementations 2 | 3 | You can use these programs to test how long time your own NAT, or your ISP's CGN, will wait before dropping an idle TCP connection. 4 | 5 | I wrote a more thorough explanation of this issue on my blog, and blamed my ISP for killing my SSH connections: 6 | 7 | But here's the tl;dr: 8 | 9 | To be [RFC5382](https://tools.ietf.org/html/rfc5382) compliant, the NAT should wait at least 2 hours and 4 minutes before dropping the idle connection from its NAT table. 10 | This value allows TCP keepalives to do its job, since the interval before a keepalive packet is sent "[MUST default to no less than two hours](https://tools.ietf.org/html/rfc1122)", giving the keepalives a 4 minute window to rescue the connection. 11 | 12 | The idea is to establish some TCP connections to a server, wait some time and then send some data to test if the connections still works. This way we can discover the timeout period before the NAT will drop the connection. 13 | 14 | The tests will spawn 130 connections on startup, and test the first connection after 1 minute, the second after 2 minutes and so on (2 hours and 10 minutes total). 15 | 16 | `tcp-send-test` will do exactly that. 17 | 18 | `tcp-recv-test` will instead ask the server to test the connections (i.e be the one to try and send some send data after waiting). 19 | 20 | `tcp-keepalive-test` works essentially the same way as tcp-send-test, but instead of sending actual data, it will use TCP-keepalives. 21 | 22 | By default, the tests are configured to connect to a server sponsored by the non-profit organization [dotsrc.org](https://dotsrc.org/). 23 | 24 | To compile, just run `make`. 25 | 26 | You should start both `tcp-recv-test` and `tcp-send-test`, and wait for about 2½ hours. Then look for the last connection that worked - that timer + 1 min is probably the TCP idle-timeout of your NAT. 27 | -------------------------------------------------------------------------------- /echo-server/src/main.rs: -------------------------------------------------------------------------------- 1 | use std::net::{TcpListener, TcpStream}; 2 | use std::thread; 3 | use std::io::Read; 4 | use std::io::Write; 5 | use std::cmp::min; 6 | use rlimit::*; 7 | 8 | // Number of open file descriptors allowed 9 | const RLIMIT_NOFILE: u64 = 10000; 10 | 11 | fn handle_client(mut stream: TcpStream) { 12 | // Read up to 64 bytes from stream 13 | let mut buf = [0; 64]; 14 | match stream.read(&mut buf) { 15 | Ok(n) => { 16 | if n == 0 { 17 | // Connection was closed 18 | return; 19 | } 20 | let _ = stream.write_all(&buf[0..n]); 21 | } 22 | Err(e) => { 23 | eprintln!("read() error: {}", e); 24 | } 25 | } 26 | } 27 | 28 | fn raise_rlimit_nofile() -> std::io::Result<()> { 29 | // Allow this process to have many open connections (file descriptors) 30 | // Check GETRLIMIT(2) - RLIMIT_NOFILE for more info 31 | let (nofile_soft, nofile_hard) = getrlimit(Resource::NOFILE)?; 32 | if nofile_soft < RLIMIT_NOFILE { 33 | // GETRLIMIT(2): 34 | // The hard limit acts as a ceiling for the soft 35 | // limit: an unprivileged process may set only its soft limit to a value 36 | // in the range from 0 up to the hard limit 37 | let newlimit = min(RLIMIT_NOFILE, nofile_hard); 38 | match setrlimit(Resource::NOFILE, newlimit, nofile_hard) { 39 | Ok(()) => println!("Raised RLIMIT_NOFILE from {} to {}", nofile_soft, newlimit), 40 | Err(error) => return Err(error) 41 | } 42 | } 43 | Ok(()) 44 | } 45 | 46 | fn main() { 47 | raise_rlimit_nofile().unwrap_or_else(|error| { 48 | println!("Falied to update RLIMIT_NOFILE: {:?}. Continuing.", error); 49 | }); 50 | 51 | let listener = TcpListener::bind("0.0.0.0:31415").unwrap(); 52 | 53 | for stream in listener.incoming() { 54 | match stream { 55 | Ok(stream) => { 56 | thread::spawn(move || { 57 | handle_client(stream); 58 | }); 59 | } 60 | Err(e) => { 61 | eprintln!("listener.incoming() error: {}", e); 62 | } 63 | } 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /sleep-server/src/main.rs: -------------------------------------------------------------------------------- 1 | use async_std::net::{TcpListener, TcpStream}; 2 | use futures::stream::StreamExt; 3 | use std::{str, error}; 4 | use std::cmp::min; 5 | use std::time::Duration; 6 | use async_std::task; 7 | use async_std::prelude::*; 8 | use rlimit::*; 9 | 10 | // Number of open file descriptors allowed 11 | const RLIMIT_NOFILE: u64 = 10000; 12 | 13 | 14 | async fn handle_client(mut stream: TcpStream) -> Result<(), Box>{ 15 | // Read up to 64 bytes from stream 16 | let mut buf: [u8; 64] = [0; 64]; 17 | let n = stream.read(&mut buf).await?; 18 | 19 | if n == 0 { 20 | // Connection was closed 21 | return Ok(()); 22 | } 23 | 24 | let sleeptimestr = str::from_utf8(&buf[0..n])?.trim(); 25 | let sleeptime: u64 = sleeptimestr.parse()?; 26 | if sleeptime > 60*60*24 { 27 | return Err("not sleeping that long".into()); 28 | } 29 | task::sleep(Duration::from_secs(sleeptime)).await; 30 | 31 | stream.write(&buf[0..n]).await?; 32 | stream.flush().await?; 33 | Ok(()) 34 | } 35 | 36 | 37 | fn raise_rlimit_nofile() -> std::io::Result<()> { 38 | // Allow this process to have many open connections (file descriptors) 39 | // Check GETRLIMIT(2) - RLIMIT_NOFILE for more info 40 | let (nofile_soft, nofile_hard) = getrlimit(Resource::NOFILE)?; 41 | if nofile_soft < RLIMIT_NOFILE { 42 | // GETRLIMIT(2): 43 | // The hard limit acts as a ceiling for the soft 44 | // limit: an unprivileged process may set only its soft limit to a value 45 | // in the range from 0 up to the hard limit 46 | let newlimit = min(RLIMIT_NOFILE, nofile_hard); 47 | match setrlimit(Resource::NOFILE, newlimit, nofile_hard) { 48 | Ok(()) => println!("Raised RLIMIT_NOFILE from {} to {}", nofile_soft, newlimit), 49 | Err(error) => return Err(error) 50 | } 51 | } 52 | Ok(()) 53 | } 54 | 55 | 56 | #[async_std::main] 57 | async fn main() { 58 | raise_rlimit_nofile().unwrap_or_else(|error| { 59 | println!("Falied to update RLIMIT_NOFILE: {:?}. Continuing.", error); 60 | }); 61 | 62 | let listener = TcpListener::bind("0.0.0.0:27182").await.unwrap(); 63 | 64 | listener.incoming().for_each_concurrent( 65 | /* limit */ None, 66 | | tcpstream | async move { 67 | match tcpstream { 68 | Ok(stream) => { 69 | if let Err(e) = handle_client(stream).await { 70 | eprintln!("{}", e); 71 | } 72 | } 73 | Err(e) => { 74 | eprintln!("listener.incoming() error: {}", e); 75 | } 76 | } 77 | } 78 | ).await 79 | } 80 | -------------------------------------------------------------------------------- /tcp-send-test.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #include "util.h" 14 | 15 | int do_connect(struct sockaddr_in *dst) { 16 | int s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 17 | if (s == -1) { 18 | perror("socket"); 19 | return -1; 20 | } 21 | 22 | if (connect(s, (struct sockaddr *) dst, sizeof(struct sockaddr_in)) == -1) { 23 | perror("connect"); 24 | return -1; 25 | } 26 | 27 | /* for faster debugging 28 | // specifies the maximum amount of time in milliseconds 29 | // that transmitted data may remain unacknowledged before 30 | // TCP will forcibly close the corresponding connection 31 | // and return ETIMEDOUT to the application. 32 | if (setsockopt(s, IPPROTO_TCP, TCP_USER_TIMEOUT, 33 | (int []){ 10 * 1000 }, sizeof(int)) == -1) { 34 | perror("setsockopt TCP_USER_TIMEOUT"); 35 | return -1; 36 | } 37 | */ 38 | 39 | return s; 40 | } 41 | 42 | #define NCONNECTIONS 130 43 | int main(int argc, char *argv[]){ 44 | int tcpsessions[NCONNECTIONS] = {0}; 45 | char buf; 46 | struct sockaddr_in dst_addr = { 47 | .sin_family = AF_INET, 48 | .sin_port = htons(31415), 49 | .sin_addr = inet_addr("130.225.254.111"), 50 | }; 51 | 52 | msg("[+] Trying to establish connections: "); 53 | for (int i = 0; i < NCONNECTIONS; i++) { 54 | printf("%d ", i); 55 | fflush(stdout); 56 | tcpsessions[i] = do_connect(&dst_addr); 57 | if (tcpsessions[i] == -1) { 58 | return EXIT_FAILURE; 59 | } 60 | } 61 | printf("\n"); 62 | 63 | msg("[+] All connections established\n"); 64 | 65 | for (int i = 0; i < NCONNECTIONS; i++) { 66 | // This is not exact - we'll gradually drift 67 | // by the time it takes to write() and read() 68 | sleep(60); 69 | if (write(tcpsessions[i], "A", 1) != 1) { 70 | if (errno != ETIMEDOUT) { 71 | perror("write"); 72 | return EXIT_FAILURE; 73 | } 74 | msg("[-] Connection %d is dead (write)\n", i); 75 | close(tcpsessions[i]); 76 | continue; 77 | } 78 | 79 | if (read(tcpsessions[i], &buf, 1) != 1) { 80 | if (errno != ETIMEDOUT) { 81 | perror("read"); 82 | return EXIT_FAILURE; 83 | } 84 | msg("[-] Connection %d is dead (read)\n", i); 85 | close(tcpsessions[i]); 86 | continue; 87 | } 88 | msg("[+] Connection %d worked\n", i); 89 | 90 | close(tcpsessions[i]); 91 | } 92 | 93 | return 0; 94 | } 95 | -------------------------------------------------------------------------------- /tcp-recv-test.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #include "util.h" 16 | 17 | int do_connect(struct sockaddr_in *dst) { 18 | int s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 19 | if (s == -1) { 20 | perror("socket"); 21 | return -1; 22 | } 23 | 24 | if (connect(s, (struct sockaddr *) dst, sizeof(struct sockaddr_in)) == -1) { 25 | perror("connect"); 26 | return -1; 27 | } 28 | 29 | /* for faster debugging 30 | // specifies the maximum amount of time in milliseconds 31 | // that transmitted data may remain unacknowledged before 32 | // TCP will forcibly close the corresponding connection 33 | // and return ETIMEDOUT to the application. 34 | if (setsockopt(s, IPPROTO_TCP, TCP_USER_TIMEOUT, 35 | (int []){ 10 * 1000 }, sizeof(int)) == -1) { 36 | perror("setsockopt TCP_USER_TIMEOUT"); 37 | return -1; 38 | } 39 | */ 40 | 41 | return s; 42 | } 43 | 44 | #define NCONNECTIONS 130 45 | int main(int argc, char *argv[]){ 46 | int tcpsessions[NCONNECTIONS] = {0}; 47 | int serversleeptime[NCONNECTIONS] = {0}; 48 | char aint[64] = {0}; 49 | int ret; 50 | time_t startup_time = time(NULL); 51 | struct sockaddr_in dst_addr = { 52 | .sin_family = AF_INET, 53 | .sin_port = htons(27182), 54 | .sin_addr = inet_addr("130.225.254.111"), 55 | }; 56 | 57 | msg("[+] Trying to establish connections: "); 58 | for (int i = 0; i < NCONNECTIONS; i++) { 59 | serversleeptime[i] = (i+1) * 60; 60 | printf("%d (%ds), ", i, serversleeptime[i]); 61 | fflush(stdout); 62 | tcpsessions[i] = do_connect(&dst_addr); 63 | if (tcpsessions[i] == -1) { 64 | return EXIT_FAILURE; 65 | } 66 | snprintf(aint, sizeof(aint) - 1, "%d\n", serversleeptime[i]); 67 | write(tcpsessions[i], aint, strnlen(aint, sizeof aint)); 68 | } 69 | 70 | printf("\n"); 71 | msg("[+] All connections established\n"); 72 | 73 | // select() loop 74 | for (;;) { 75 | fd_set rfds; 76 | FD_ZERO(&rfds); 77 | int openconnections = 0; 78 | int maxfd = -1; 79 | 80 | for (int i = 0; i < NCONNECTIONS; i++) { 81 | if (tcpsessions[i] == -1) 82 | continue; 83 | FD_SET(tcpsessions[i], &rfds); 84 | maxfd = tcpsessions[i] > maxfd ? tcpsessions[i] : maxfd; 85 | openconnections++; 86 | } 87 | if (openconnections == 0) { 88 | msg("[+] No more alive connections left\n"); 89 | return EXIT_SUCCESS; 90 | } 91 | 92 | msg("[+] Waiting for the server to close a connection\n"); 93 | msg("[+] Open connections: %d\n", openconnections); 94 | 95 | ret = select(maxfd + 1, &rfds, NULL, NULL, NULL); 96 | if (ret == -1) { 97 | if (errno == EINTR) 98 | continue; 99 | perror("select"); 100 | return EXIT_FAILURE; 101 | } else if (ret) { 102 | for (int i = 0; i < NCONNECTIONS; i++) { 103 | if (tcpsessions[i] != -1 && FD_ISSET(tcpsessions[i], &rfds)) { 104 | ssize_t readret = read(tcpsessions[i], aint, sizeof(aint)-1); 105 | if (readret == -1) { 106 | msg("[-] Shouldn't happen:\n" 107 | "readret: %ld\n" 108 | "errno: %d (%m)\n" 109 | "i: %d\n" 110 | "tcpsessions[i]: %d\n" 111 | "aint: %s\n", 112 | readret, errno, i, tcpsessions[i], aint 113 | ); 114 | } else if (readret > 0) { 115 | aint[readret] = '\0'; 116 | time_t alivetime = time(NULL) - startup_time; 117 | msg("[+] Connection %d returned after %ldm %lds: %s\n", 118 | i, alivetime/60, alivetime%60, aint); 119 | } else { 120 | msg("[-] Shouldn't happen. Connection %d\n", i); 121 | } 122 | 123 | close(tcpsessions[i]); 124 | tcpsessions[i] = -1; 125 | } 126 | } 127 | } else { 128 | msg("[+] No data\n"); 129 | } 130 | } 131 | 132 | return 0; 133 | } 134 | -------------------------------------------------------------------------------- /tcp-keepalive-test.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #include "util.h" 14 | 15 | #ifdef __APPLE__ 16 | #define TCP_KEEPIDLE TCP_KEEPALIVE 17 | #endif 18 | 19 | int do_connect(struct sockaddr_in *dst, int keepalive_time) { 20 | int s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 21 | if (s == -1) { 22 | perror("socket"); 23 | return -1; 24 | } 25 | 26 | if (connect(s, (struct sockaddr *) dst, sizeof(struct sockaddr_in)) == -1) { 27 | perror("connect"); 28 | return -1; 29 | } 30 | 31 | // Enable TCP keepalive 32 | if (setsockopt(s, SOL_SOCKET, SO_KEEPALIVE, 33 | (int []){1}, sizeof(int)) == -1) { 34 | perror("setsockopt SO_KEEPALIVE"); 35 | return -1; 36 | } 37 | 38 | // The time (in seconds) the connection needs to remain idle before 39 | // TCP starts sending keepalive probes, if the socket option 40 | // SO_KEEPALIVE has been set on this socket. 41 | if (setsockopt(s, IPPROTO_TCP, TCP_KEEPIDLE, 42 | &keepalive_time, sizeof keepalive_time) == -1) { 43 | perror("setsockopt SO_KEEPIDLE"); 44 | return -1; 45 | } 46 | 47 | /* For faster debugging 48 | // The maximum number of keepalive probes TCP should send before 49 | // dropping the connection. 50 | if (setsockopt(s, IPPROTO_TCP, TCP_KEEPCNT, 51 | (int []){3}, sizeof(int)) == -1) { 52 | perror("setsockopt TCP_KEEPCNT"); 53 | return -1; 54 | } 55 | 56 | // The time (in seconds) between individual keepalive probes. 57 | if (setsockopt(s, IPPROTO_TCP, TCP_KEEPINTVL, 58 | (int []){5}, sizeof(int)) == -1) { 59 | perror("setsockopt TCP_KEEPINTVL"); 60 | return -1; 61 | } 62 | */ 63 | 64 | return s; 65 | } 66 | 67 | #define NCONNECTIONS 130 68 | int main(int argc, char *argv[]){ 69 | int tcpsessions[NCONNECTIONS] = {0}; 70 | int keepalivetime[NCONNECTIONS] = {0}; 71 | char buf; 72 | int ret; 73 | struct sockaddr_in dst_addr = { 74 | .sin_family = AF_INET, 75 | .sin_port = htons(31415), 76 | .sin_addr = inet_addr("130.225.254.111"), 77 | }; 78 | 79 | printf("[+] Trying to establish connections: "); 80 | for (int i = 0; i < NCONNECTIONS; i++) { 81 | // The first connection will have a keepalivetime of 1 min, 82 | // the second one 2 min, etc. 83 | keepalivetime[i] = (i + 1) * 60; 84 | printf("%d (%ds), ", i, keepalivetime[i]); 85 | fflush(stdout); 86 | tcpsessions[i] = do_connect(&dst_addr, keepalivetime[i]); 87 | if (tcpsessions[i] == -1) { 88 | return EXIT_FAILURE; 89 | } 90 | } 91 | printf("\n"); 92 | msg("[+] All connections established\n"); 93 | 94 | // select() loop 95 | for (;;) { 96 | fd_set rfds; 97 | FD_ZERO(&rfds); 98 | int openconnections = 0; 99 | int maxfd = -1; 100 | 101 | for (int i = 0; i < NCONNECTIONS; i++) { 102 | if (tcpsessions[i] == -1) 103 | continue; 104 | FD_SET(tcpsessions[i], &rfds); 105 | maxfd = tcpsessions[i] > maxfd ? tcpsessions[i] : maxfd; 106 | openconnections++; 107 | } 108 | if (openconnections == 0) { 109 | msg("[+] No more alive connections left\n"); 110 | return EXIT_SUCCESS; 111 | } 112 | 113 | msg("[+] Waiting for a connection to timeout.\n"); 114 | msg("[+] Open connections: %d\n", openconnections); 115 | 116 | ret = select(maxfd + 1, &rfds, NULL, NULL, NULL); 117 | if (ret == -1) { 118 | if (errno == EINTR) 119 | continue; 120 | perror("select"); 121 | return EXIT_FAILURE; 122 | } else if (ret) { 123 | for (int i = 0; i < NCONNECTIONS; i++) { 124 | if (tcpsessions[i] != -1 && FD_ISSET(tcpsessions[i], &rfds)) { 125 | ssize_t readret = read(tcpsessions[i], &buf, 1); 126 | if (readret != -1 || errno != ETIMEDOUT) { 127 | msg("[-] shouldn't happen:\n" 128 | "readret: %ld\n" 129 | "errno: %d (%m)\n" 130 | "i: %d\n" 131 | "tcpsessions[i]: %d\n", 132 | readret, errno, i, tcpsessions[i] 133 | ); 134 | close(tcpsessions[i]); 135 | tcpsessions[i] = -1; 136 | continue; 137 | } 138 | msg("[+] TCP connection died: "); 139 | printf("Connection %d, keepalivetime: %dm %ds\n", 140 | i, keepalivetime[i]/60, keepalivetime[i]%60); 141 | fflush(stdout); 142 | close(tcpsessions[i]); 143 | tcpsessions[i] = -1; 144 | } 145 | } 146 | } else { 147 | msg("[+] No data\n"); 148 | } 149 | } 150 | 151 | return 0; 152 | } 153 | -------------------------------------------------------------------------------- /sleep-server/Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | [[package]] 4 | name = "async-attributes" 5 | version = "1.1.1" 6 | source = "registry+https://github.com/rust-lang/crates.io-index" 7 | checksum = "efd3d156917d94862e779f356c5acae312b08fd3121e792c857d7928c8088423" 8 | dependencies = [ 9 | "quote", 10 | "syn", 11 | ] 12 | 13 | [[package]] 14 | name = "async-channel" 15 | version = "1.5.1" 16 | source = "registry+https://github.com/rust-lang/crates.io-index" 17 | checksum = "59740d83946db6a5af71ae25ddf9562c2b176b2ca42cf99a455f09f4a220d6b9" 18 | dependencies = [ 19 | "concurrent-queue", 20 | "event-listener", 21 | "futures-core", 22 | ] 23 | 24 | [[package]] 25 | name = "async-executor" 26 | version = "1.4.0" 27 | source = "registry+https://github.com/rust-lang/crates.io-index" 28 | checksum = "eb877970c7b440ead138f6321a3b5395d6061183af779340b65e20c0fede9146" 29 | dependencies = [ 30 | "async-task", 31 | "concurrent-queue", 32 | "fastrand", 33 | "futures-lite", 34 | "once_cell", 35 | "vec-arena", 36 | ] 37 | 38 | [[package]] 39 | name = "async-global-executor" 40 | version = "1.4.3" 41 | source = "registry+https://github.com/rust-lang/crates.io-index" 42 | checksum = "73079b49cd26b8fd5a15f68fc7707fc78698dc2a3d61430f2a7a9430230dfa04" 43 | dependencies = [ 44 | "async-executor", 45 | "async-io", 46 | "futures-lite", 47 | "num_cpus", 48 | "once_cell", 49 | ] 50 | 51 | [[package]] 52 | name = "async-io" 53 | version = "1.3.1" 54 | source = "registry+https://github.com/rust-lang/crates.io-index" 55 | checksum = "9315f8f07556761c3e48fec2e6b276004acf426e6dc068b2c2251854d65ee0fd" 56 | dependencies = [ 57 | "concurrent-queue", 58 | "fastrand", 59 | "futures-lite", 60 | "libc", 61 | "log", 62 | "nb-connect", 63 | "once_cell", 64 | "parking", 65 | "polling", 66 | "vec-arena", 67 | "waker-fn", 68 | "winapi", 69 | ] 70 | 71 | [[package]] 72 | name = "async-mutex" 73 | version = "1.4.0" 74 | source = "registry+https://github.com/rust-lang/crates.io-index" 75 | checksum = "479db852db25d9dbf6204e6cb6253698f175c15726470f78af0d918e99d6156e" 76 | dependencies = [ 77 | "event-listener", 78 | ] 79 | 80 | [[package]] 81 | name = "async-std" 82 | version = "1.8.0" 83 | source = "registry+https://github.com/rust-lang/crates.io-index" 84 | checksum = "8f9f84f1280a2b436a2c77c2582602732b6c2f4321d5494d6e799e6c367859a8" 85 | dependencies = [ 86 | "async-attributes", 87 | "async-channel", 88 | "async-global-executor", 89 | "async-io", 90 | "async-mutex", 91 | "blocking", 92 | "crossbeam-utils", 93 | "futures-channel", 94 | "futures-core", 95 | "futures-io", 96 | "futures-lite", 97 | "gloo-timers", 98 | "kv-log-macro", 99 | "log", 100 | "memchr", 101 | "num_cpus", 102 | "once_cell", 103 | "pin-project-lite", 104 | "pin-utils", 105 | "slab", 106 | "wasm-bindgen-futures", 107 | ] 108 | 109 | [[package]] 110 | name = "async-task" 111 | version = "4.0.3" 112 | source = "registry+https://github.com/rust-lang/crates.io-index" 113 | checksum = "e91831deabf0d6d7ec49552e489aed63b7456a7a3c46cff62adad428110b0af0" 114 | 115 | [[package]] 116 | name = "atomic-waker" 117 | version = "1.0.0" 118 | source = "registry+https://github.com/rust-lang/crates.io-index" 119 | checksum = "065374052e7df7ee4047b1160cca5e1467a12351a40b3da123c870ba0b8eda2a" 120 | 121 | [[package]] 122 | name = "autocfg" 123 | version = "1.0.1" 124 | source = "registry+https://github.com/rust-lang/crates.io-index" 125 | checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" 126 | 127 | [[package]] 128 | name = "blocking" 129 | version = "1.0.2" 130 | source = "registry+https://github.com/rust-lang/crates.io-index" 131 | checksum = "c5e170dbede1f740736619b776d7251cb1b9095c435c34d8ca9f57fcd2f335e9" 132 | dependencies = [ 133 | "async-channel", 134 | "async-task", 135 | "atomic-waker", 136 | "fastrand", 137 | "futures-lite", 138 | "once_cell", 139 | ] 140 | 141 | [[package]] 142 | name = "bumpalo" 143 | version = "3.4.0" 144 | source = "registry+https://github.com/rust-lang/crates.io-index" 145 | checksum = "2e8c087f005730276d1096a652e92a8bacee2e2472bcc9715a74d2bec38b5820" 146 | 147 | [[package]] 148 | name = "cache-padded" 149 | version = "1.1.1" 150 | source = "registry+https://github.com/rust-lang/crates.io-index" 151 | checksum = "631ae5198c9be5e753e5cc215e1bd73c2b466a3565173db433f52bb9d3e66dba" 152 | 153 | [[package]] 154 | name = "cc" 155 | version = "1.0.66" 156 | source = "registry+https://github.com/rust-lang/crates.io-index" 157 | checksum = "4c0496836a84f8d0495758516b8621a622beb77c0fed418570e50764093ced48" 158 | 159 | [[package]] 160 | name = "cfg-if" 161 | version = "0.1.10" 162 | source = "registry+https://github.com/rust-lang/crates.io-index" 163 | checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" 164 | 165 | [[package]] 166 | name = "cfg-if" 167 | version = "1.0.0" 168 | source = "registry+https://github.com/rust-lang/crates.io-index" 169 | checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" 170 | 171 | [[package]] 172 | name = "concurrent-queue" 173 | version = "1.2.2" 174 | source = "registry+https://github.com/rust-lang/crates.io-index" 175 | checksum = "30ed07550be01594c6026cff2a1d7fe9c8f683caa798e12b68694ac9e88286a3" 176 | dependencies = [ 177 | "cache-padded", 178 | ] 179 | 180 | [[package]] 181 | name = "crossbeam-utils" 182 | version = "0.8.1" 183 | source = "registry+https://github.com/rust-lang/crates.io-index" 184 | checksum = "02d96d1e189ef58269ebe5b97953da3274d83a93af647c2ddd6f9dab28cedb8d" 185 | dependencies = [ 186 | "autocfg", 187 | "cfg-if 1.0.0", 188 | "lazy_static", 189 | ] 190 | 191 | [[package]] 192 | name = "event-listener" 193 | version = "2.5.1" 194 | source = "registry+https://github.com/rust-lang/crates.io-index" 195 | checksum = "f7531096570974c3a9dcf9e4b8e1cede1ec26cf5046219fb3b9d897503b9be59" 196 | 197 | [[package]] 198 | name = "fastrand" 199 | version = "1.4.0" 200 | source = "registry+https://github.com/rust-lang/crates.io-index" 201 | checksum = "ca5faf057445ce5c9d4329e382b2ce7ca38550ef3b73a5348362d5f24e0c7fe3" 202 | dependencies = [ 203 | "instant", 204 | ] 205 | 206 | [[package]] 207 | name = "futures" 208 | version = "0.3.8" 209 | source = "registry+https://github.com/rust-lang/crates.io-index" 210 | checksum = "9b3b0c040a1fe6529d30b3c5944b280c7f0dcb2930d2c3062bca967b602583d0" 211 | dependencies = [ 212 | "futures-channel", 213 | "futures-core", 214 | "futures-executor", 215 | "futures-io", 216 | "futures-sink", 217 | "futures-task", 218 | "futures-util", 219 | ] 220 | 221 | [[package]] 222 | name = "futures-channel" 223 | version = "0.3.8" 224 | source = "registry+https://github.com/rust-lang/crates.io-index" 225 | checksum = "4b7109687aa4e177ef6fe84553af6280ef2778bdb7783ba44c9dc3399110fe64" 226 | dependencies = [ 227 | "futures-core", 228 | "futures-sink", 229 | ] 230 | 231 | [[package]] 232 | name = "futures-core" 233 | version = "0.3.8" 234 | source = "registry+https://github.com/rust-lang/crates.io-index" 235 | checksum = "847ce131b72ffb13b6109a221da9ad97a64cbe48feb1028356b836b47b8f1748" 236 | 237 | [[package]] 238 | name = "futures-executor" 239 | version = "0.3.8" 240 | source = "registry+https://github.com/rust-lang/crates.io-index" 241 | checksum = "4caa2b2b68b880003057c1dd49f1ed937e38f22fcf6c212188a121f08cf40a65" 242 | dependencies = [ 243 | "futures-core", 244 | "futures-task", 245 | "futures-util", 246 | ] 247 | 248 | [[package]] 249 | name = "futures-io" 250 | version = "0.3.8" 251 | source = "registry+https://github.com/rust-lang/crates.io-index" 252 | checksum = "611834ce18aaa1bd13c4b374f5d653e1027cf99b6b502584ff8c9a64413b30bb" 253 | 254 | [[package]] 255 | name = "futures-lite" 256 | version = "1.11.3" 257 | source = "registry+https://github.com/rust-lang/crates.io-index" 258 | checksum = "b4481d0cd0de1d204a4fa55e7d45f07b1d958abcb06714b3446438e2eff695fb" 259 | dependencies = [ 260 | "fastrand", 261 | "futures-core", 262 | "futures-io", 263 | "memchr", 264 | "parking", 265 | "pin-project-lite", 266 | "waker-fn", 267 | ] 268 | 269 | [[package]] 270 | name = "futures-macro" 271 | version = "0.3.8" 272 | source = "registry+https://github.com/rust-lang/crates.io-index" 273 | checksum = "77408a692f1f97bcc61dc001d752e00643408fbc922e4d634c655df50d595556" 274 | dependencies = [ 275 | "proc-macro-hack", 276 | "proc-macro2", 277 | "quote", 278 | "syn", 279 | ] 280 | 281 | [[package]] 282 | name = "futures-sink" 283 | version = "0.3.8" 284 | source = "registry+https://github.com/rust-lang/crates.io-index" 285 | checksum = "f878195a49cee50e006b02b93cf7e0a95a38ac7b776b4c4d9cc1207cd20fcb3d" 286 | 287 | [[package]] 288 | name = "futures-task" 289 | version = "0.3.8" 290 | source = "registry+https://github.com/rust-lang/crates.io-index" 291 | checksum = "7c554eb5bf48b2426c4771ab68c6b14468b6e76cc90996f528c3338d761a4d0d" 292 | dependencies = [ 293 | "once_cell", 294 | ] 295 | 296 | [[package]] 297 | name = "futures-util" 298 | version = "0.3.8" 299 | source = "registry+https://github.com/rust-lang/crates.io-index" 300 | checksum = "d304cff4a7b99cfb7986f7d43fbe93d175e72e704a8860787cc95e9ffd85cbd2" 301 | dependencies = [ 302 | "futures-channel", 303 | "futures-core", 304 | "futures-io", 305 | "futures-macro", 306 | "futures-sink", 307 | "futures-task", 308 | "memchr", 309 | "pin-project", 310 | "pin-utils", 311 | "proc-macro-hack", 312 | "proc-macro-nested", 313 | "slab", 314 | ] 315 | 316 | [[package]] 317 | name = "gloo-timers" 318 | version = "0.2.1" 319 | source = "registry+https://github.com/rust-lang/crates.io-index" 320 | checksum = "47204a46aaff920a1ea58b11d03dec6f704287d27561724a4631e450654a891f" 321 | dependencies = [ 322 | "futures-channel", 323 | "futures-core", 324 | "js-sys", 325 | "wasm-bindgen", 326 | "web-sys", 327 | ] 328 | 329 | [[package]] 330 | name = "hermit-abi" 331 | version = "0.1.17" 332 | source = "registry+https://github.com/rust-lang/crates.io-index" 333 | checksum = "5aca5565f760fb5b220e499d72710ed156fdb74e631659e99377d9ebfbd13ae8" 334 | dependencies = [ 335 | "libc", 336 | ] 337 | 338 | [[package]] 339 | name = "instant" 340 | version = "0.1.9" 341 | source = "registry+https://github.com/rust-lang/crates.io-index" 342 | checksum = "61124eeebbd69b8190558df225adf7e4caafce0d743919e5d6b19652314ec5ec" 343 | dependencies = [ 344 | "cfg-if 1.0.0", 345 | ] 346 | 347 | [[package]] 348 | name = "js-sys" 349 | version = "0.3.46" 350 | source = "registry+https://github.com/rust-lang/crates.io-index" 351 | checksum = "cf3d7383929f7c9c7c2d0fa596f325832df98c3704f2c60553080f7127a58175" 352 | dependencies = [ 353 | "wasm-bindgen", 354 | ] 355 | 356 | [[package]] 357 | name = "kv-log-macro" 358 | version = "1.0.7" 359 | source = "registry+https://github.com/rust-lang/crates.io-index" 360 | checksum = "0de8b303297635ad57c9f5059fd9cee7a47f8e8daa09df0fcd07dd39fb22977f" 361 | dependencies = [ 362 | "log", 363 | ] 364 | 365 | [[package]] 366 | name = "lazy_static" 367 | version = "1.4.0" 368 | source = "registry+https://github.com/rust-lang/crates.io-index" 369 | checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" 370 | 371 | [[package]] 372 | name = "libc" 373 | version = "0.2.81" 374 | source = "registry+https://github.com/rust-lang/crates.io-index" 375 | checksum = "1482821306169ec4d07f6aca392a4681f66c75c9918aa49641a2595db64053cb" 376 | 377 | [[package]] 378 | name = "log" 379 | version = "0.4.11" 380 | source = "registry+https://github.com/rust-lang/crates.io-index" 381 | checksum = "4fabed175da42fed1fa0746b0ea71f412aa9d35e76e95e59b192c64b9dc2bf8b" 382 | dependencies = [ 383 | "cfg-if 0.1.10", 384 | ] 385 | 386 | [[package]] 387 | name = "memchr" 388 | version = "2.3.4" 389 | source = "registry+https://github.com/rust-lang/crates.io-index" 390 | checksum = "0ee1c47aaa256ecabcaea351eae4a9b01ef39ed810004e298d2511ed284b1525" 391 | 392 | [[package]] 393 | name = "nb-connect" 394 | version = "1.0.2" 395 | source = "registry+https://github.com/rust-lang/crates.io-index" 396 | checksum = "8123a81538e457d44b933a02faf885d3fe8408806b23fa700e8f01c6c3a98998" 397 | dependencies = [ 398 | "libc", 399 | "winapi", 400 | ] 401 | 402 | [[package]] 403 | name = "num_cpus" 404 | version = "1.13.0" 405 | source = "registry+https://github.com/rust-lang/crates.io-index" 406 | checksum = "05499f3756671c15885fee9034446956fff3f243d6077b91e5767df161f766b3" 407 | dependencies = [ 408 | "hermit-abi", 409 | "libc", 410 | ] 411 | 412 | [[package]] 413 | name = "once_cell" 414 | version = "1.5.2" 415 | source = "registry+https://github.com/rust-lang/crates.io-index" 416 | checksum = "13bd41f508810a131401606d54ac32a467c97172d74ba7662562ebba5ad07fa0" 417 | 418 | [[package]] 419 | name = "parking" 420 | version = "2.0.0" 421 | source = "registry+https://github.com/rust-lang/crates.io-index" 422 | checksum = "427c3892f9e783d91cc128285287e70a59e206ca452770ece88a76f7a3eddd72" 423 | 424 | [[package]] 425 | name = "pin-project" 426 | version = "1.0.2" 427 | source = "registry+https://github.com/rust-lang/crates.io-index" 428 | checksum = "9ccc2237c2c489783abd8c4c80e5450fc0e98644555b1364da68cc29aa151ca7" 429 | dependencies = [ 430 | "pin-project-internal", 431 | ] 432 | 433 | [[package]] 434 | name = "pin-project-internal" 435 | version = "1.0.2" 436 | source = "registry+https://github.com/rust-lang/crates.io-index" 437 | checksum = "f8e8d2bf0b23038a4424865103a4df472855692821aab4e4f5c3312d461d9e5f" 438 | dependencies = [ 439 | "proc-macro2", 440 | "quote", 441 | "syn", 442 | ] 443 | 444 | [[package]] 445 | name = "pin-project-lite" 446 | version = "0.2.0" 447 | source = "registry+https://github.com/rust-lang/crates.io-index" 448 | checksum = "6b063f57ec186e6140e2b8b6921e5f1bd89c7356dda5b33acc5401203ca6131c" 449 | 450 | [[package]] 451 | name = "pin-utils" 452 | version = "0.1.0" 453 | source = "registry+https://github.com/rust-lang/crates.io-index" 454 | checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" 455 | 456 | [[package]] 457 | name = "polling" 458 | version = "2.0.2" 459 | source = "registry+https://github.com/rust-lang/crates.io-index" 460 | checksum = "a2a7bc6b2a29e632e45451c941832803a18cce6781db04de8a04696cdca8bde4" 461 | dependencies = [ 462 | "cfg-if 0.1.10", 463 | "libc", 464 | "log", 465 | "wepoll-sys", 466 | "winapi", 467 | ] 468 | 469 | [[package]] 470 | name = "proc-macro-hack" 471 | version = "0.5.19" 472 | source = "registry+https://github.com/rust-lang/crates.io-index" 473 | checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5" 474 | 475 | [[package]] 476 | name = "proc-macro-nested" 477 | version = "0.1.6" 478 | source = "registry+https://github.com/rust-lang/crates.io-index" 479 | checksum = "eba180dafb9038b050a4c280019bbedf9f2467b61e5d892dcad585bb57aadc5a" 480 | 481 | [[package]] 482 | name = "proc-macro2" 483 | version = "1.0.24" 484 | source = "registry+https://github.com/rust-lang/crates.io-index" 485 | checksum = "1e0704ee1a7e00d7bb417d0770ea303c1bccbabf0ef1667dae92b5967f5f8a71" 486 | dependencies = [ 487 | "unicode-xid", 488 | ] 489 | 490 | [[package]] 491 | name = "quote" 492 | version = "1.0.8" 493 | source = "registry+https://github.com/rust-lang/crates.io-index" 494 | checksum = "991431c3519a3f36861882da93630ce66b52918dcf1b8e2fd66b397fc96f28df" 495 | dependencies = [ 496 | "proc-macro2", 497 | ] 498 | 499 | [[package]] 500 | name = "rlimit" 501 | version = "0.3.0" 502 | source = "registry+https://github.com/rust-lang/crates.io-index" 503 | checksum = "e6d26e65e82a1e2628c5f209ec12f4508fa50e644bd2f264138e60129d61eae8" 504 | dependencies = [ 505 | "cfg-if 0.1.10", 506 | "libc", 507 | ] 508 | 509 | [[package]] 510 | name = "slab" 511 | version = "0.4.2" 512 | source = "registry+https://github.com/rust-lang/crates.io-index" 513 | checksum = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8" 514 | 515 | [[package]] 516 | name = "sleep-server" 517 | version = "0.1.0" 518 | dependencies = [ 519 | "async-std", 520 | "futures", 521 | "rlimit", 522 | ] 523 | 524 | [[package]] 525 | name = "syn" 526 | version = "1.0.55" 527 | source = "registry+https://github.com/rust-lang/crates.io-index" 528 | checksum = "a571a711dddd09019ccc628e1b17fe87c59b09d513c06c026877aa708334f37a" 529 | dependencies = [ 530 | "proc-macro2", 531 | "quote", 532 | "unicode-xid", 533 | ] 534 | 535 | [[package]] 536 | name = "unicode-xid" 537 | version = "0.2.1" 538 | source = "registry+https://github.com/rust-lang/crates.io-index" 539 | checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564" 540 | 541 | [[package]] 542 | name = "vec-arena" 543 | version = "1.0.0" 544 | source = "registry+https://github.com/rust-lang/crates.io-index" 545 | checksum = "eafc1b9b2dfc6f5529177b62cf806484db55b32dc7c9658a118e11bbeb33061d" 546 | 547 | [[package]] 548 | name = "waker-fn" 549 | version = "1.1.0" 550 | source = "registry+https://github.com/rust-lang/crates.io-index" 551 | checksum = "9d5b2c62b4012a3e1eca5a7e077d13b3bf498c4073e33ccd58626607748ceeca" 552 | 553 | [[package]] 554 | name = "wasm-bindgen" 555 | version = "0.2.69" 556 | source = "registry+https://github.com/rust-lang/crates.io-index" 557 | checksum = "3cd364751395ca0f68cafb17666eee36b63077fb5ecd972bbcd74c90c4bf736e" 558 | dependencies = [ 559 | "cfg-if 1.0.0", 560 | "wasm-bindgen-macro", 561 | ] 562 | 563 | [[package]] 564 | name = "wasm-bindgen-backend" 565 | version = "0.2.69" 566 | source = "registry+https://github.com/rust-lang/crates.io-index" 567 | checksum = "1114f89ab1f4106e5b55e688b828c0ab0ea593a1ea7c094b141b14cbaaec2d62" 568 | dependencies = [ 569 | "bumpalo", 570 | "lazy_static", 571 | "log", 572 | "proc-macro2", 573 | "quote", 574 | "syn", 575 | "wasm-bindgen-shared", 576 | ] 577 | 578 | [[package]] 579 | name = "wasm-bindgen-futures" 580 | version = "0.4.19" 581 | source = "registry+https://github.com/rust-lang/crates.io-index" 582 | checksum = "1fe9756085a84584ee9457a002b7cdfe0bfff169f45d2591d8be1345a6780e35" 583 | dependencies = [ 584 | "cfg-if 1.0.0", 585 | "js-sys", 586 | "wasm-bindgen", 587 | "web-sys", 588 | ] 589 | 590 | [[package]] 591 | name = "wasm-bindgen-macro" 592 | version = "0.2.69" 593 | source = "registry+https://github.com/rust-lang/crates.io-index" 594 | checksum = "7a6ac8995ead1f084a8dea1e65f194d0973800c7f571f6edd70adf06ecf77084" 595 | dependencies = [ 596 | "quote", 597 | "wasm-bindgen-macro-support", 598 | ] 599 | 600 | [[package]] 601 | name = "wasm-bindgen-macro-support" 602 | version = "0.2.69" 603 | source = "registry+https://github.com/rust-lang/crates.io-index" 604 | checksum = "b5a48c72f299d80557c7c62e37e7225369ecc0c963964059509fbafe917c7549" 605 | dependencies = [ 606 | "proc-macro2", 607 | "quote", 608 | "syn", 609 | "wasm-bindgen-backend", 610 | "wasm-bindgen-shared", 611 | ] 612 | 613 | [[package]] 614 | name = "wasm-bindgen-shared" 615 | version = "0.2.69" 616 | source = "registry+https://github.com/rust-lang/crates.io-index" 617 | checksum = "7e7811dd7f9398f14cc76efd356f98f03aa30419dea46aa810d71e819fc97158" 618 | 619 | [[package]] 620 | name = "web-sys" 621 | version = "0.3.46" 622 | source = "registry+https://github.com/rust-lang/crates.io-index" 623 | checksum = "222b1ef9334f92a21d3fb53dc3fd80f30836959a90f9274a626d7e06315ba3c3" 624 | dependencies = [ 625 | "js-sys", 626 | "wasm-bindgen", 627 | ] 628 | 629 | [[package]] 630 | name = "wepoll-sys" 631 | version = "3.0.1" 632 | source = "registry+https://github.com/rust-lang/crates.io-index" 633 | checksum = "0fcb14dea929042224824779fbc82d9fab8d2e6d3cbc0ac404de8edf489e77ff" 634 | dependencies = [ 635 | "cc", 636 | ] 637 | 638 | [[package]] 639 | name = "winapi" 640 | version = "0.3.9" 641 | source = "registry+https://github.com/rust-lang/crates.io-index" 642 | checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" 643 | dependencies = [ 644 | "winapi-i686-pc-windows-gnu", 645 | "winapi-x86_64-pc-windows-gnu", 646 | ] 647 | 648 | [[package]] 649 | name = "winapi-i686-pc-windows-gnu" 650 | version = "0.4.0" 651 | source = "registry+https://github.com/rust-lang/crates.io-index" 652 | checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" 653 | 654 | [[package]] 655 | name = "winapi-x86_64-pc-windows-gnu" 656 | version = "0.4.0" 657 | source = "registry+https://github.com/rust-lang/crates.io-index" 658 | checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" 659 | --------------------------------------------------------------------------------