// Comprehensive stress test for socket-like API #include #include #include #include #include #include #include #include #include #include #include "ZeroTierSDK.h" #define PASSED 0 #define FAILED -1 std::string str = "welcome to the machine"; // [] random // [OK] simple client ipv4 // [OK] simple server ipv4 // [?] simple client ipv6 // [?] simple server ipv6 // [OK] sustained client ipv4 // [OK] sustained server ipv4 // [?] sustained client ipv6 // [?] sustained server ipv6 // [] comprehensive client ipv4 // [] comprehensive server ipv6 // --- // comprehensive client addr port // comprehensive server port // simple [4|6] client addr port // simple [4|6] server port /****************************************************************************/ /* SIMPLE CLIENT */ /****************************************************************************/ // int ipv4_tcp_client_test(struct sockaddr_in *addr, int port) { int sockfd, err; if((sockfd = zts_socket(AF_INET, SOCK_STREAM, 0)) < 0) { printf("error creating ZeroTier socket"); exit(0); } if((err = zts_connect(sockfd, (const struct sockaddr *)addr, sizeof(addr))) < 0) { printf("error connecting to remote host (%d)\n", err); exit(0); } printf("sleeping... before writing to fd = %d\n", sockfd); int wrote = zts_write(sockfd, str.c_str(), str.length()); while(1) sleep(1); err = zts_close(sockfd); return (wrote == str.length() && !err) ? PASSED : FAILED; // if wrote correct number of bytes } // int ipv6_tcp_client_test(struct sockaddr_in6 *addr, int port) { int sockfd, err; if((sockfd = zts_socket(AF_INET, SOCK_STREAM, 0)) < 0) { printf("error creating ZeroTier socket"); exit(0); } if((err = zts_connect(sockfd, (const struct sockaddr *)addr, sizeof(addr))) < 0) { printf("error connecting to remote host (%d)\n", err); exit(0); } int wrote = zts_write(sockfd, str.c_str(), str.length()); err = zts_close(sockfd); return (wrote == str.length() && !err) ? PASSED : FAILED; // if wrote correct number of bytes } /****************************************************************************/ /* SIMPLE SERVER */ /****************************************************************************/ // int ipv4_tcp_server_test(struct sockaddr_in *addr, int port) { int sockfd, err; if((sockfd = zts_socket(AF_INET, SOCK_STREAM, 0)) < 0) { printf("error creating ZeroTier socket"); exit(0); } if((err = zts_bind(sockfd, (struct sockaddr *)addr, sizeof(struct sockaddr_in)) < 0)) { printf("error binding to interface (%d)\n", err); exit(0); } if((err = zts_listen(sockfd, 100)) < 0) { printf("error placing socket in LISTENING state (%d)\n", err); exit(0); } // TODO: handle new address if((err = zts_accept(sockfd, (struct sockaddr *)&addr, (socklen_t *)sizeof(addr))) < 0) { printf("error accepting connection (%d)\n", err); exit(0); } sleep(3); printf("accept fd = %d\n", err); char buf[32]; int read = zts_read(err, buf, sizeof buf); printf("buf = %s\n", buf); err = zts_close(err); //return (wrote == str.length() && !err) ? PASSED : FAILED; // if wrote correct number of bytes return err; } // int ipv6_tcp_server_test(struct sockaddr_in6 *addr, int port) { int sockfd, err; if((sockfd = zts_socket(AF_INET, SOCK_STREAM, 0)) < 0) { printf("error creating ZeroTier socket"); exit(0); } if((err = zts_bind(sockfd, (struct sockaddr *)addr, sizeof(struct sockaddr_in6)) < 0)) { printf("error binding to interface (%d)\n", err); exit(0); } if((err = zts_listen(sockfd, 1)) < 0) { printf("error placing socket in LISTENING state (%d)\n", err); exit(0); } // TODO: handle new address if((err = zts_accept(sockfd, (struct sockaddr *)&addr, (socklen_t *)sizeof(addr))) < 0) { printf("error accepting connection (%d)\n", err); exit(0); } int wrote = zts_write(sockfd, str.c_str(), str.length()); err = zts_close(sockfd); return (wrote == str.length() && !err) ? PASSED : FAILED; // if wrote correct number of bytes } /****************************************************************************/ /* SUSTAINED CLIENT */ /****************************************************************************/ // Maintain transfer for n_seconds OR n_times int ipv4_tcp_client_sustained_test(struct sockaddr_in *addr, int port, int n_seconds, int n_times) { int sockfd, err; int msg_len = str.length(); int wrote = 0; if((sockfd = zts_socket(AF_INET, SOCK_STREAM, 0)) < 0) { printf("error creating ZeroTier socket"); exit(0); } if((err = zts_connect(sockfd, (const struct sockaddr *)addr, sizeof(addr))) < 0) { printf("error connecting to remote host (%d)\n", err); exit(0); } if(n_seconds) { /* printf("testing for (%d) seconds\n", n_seconds); int wrote; for(int i=0; ih_addr, server->h_length); addr6.sin6_port = htons(port); printf(" running (%s) test as ipv=%s\n", mode.c_str(), protocol.c_str()); if(ipv6_tcp_client_test(&addr6, port) == PASSED) printf("PASSED\n"); else printf("FAILED\n"); return 0; } } // SIMPLE SERVER if(mode == "server") { port = atoi(argv[7]); printf("serving on port %s\n", argv[7]); // IPv4 if(protocol == "4") { addr.sin_port = htons(port); addr.sin_addr.s_addr = inet_addr(argv[6]); // addr.sin_addr.s_addr = htons(INADDR_ANY); addr.sin_family = AF_INET; printf(" running (%s) test as ipv=%s\n", mode.c_str(), protocol.c_str()); if(ipv4_tcp_server_test(&addr, port) == PASSED) printf("PASSED\n"); else printf("FAILED\n"); return 0; } // IPv6 if(protocol == "6") { server = gethostbyname2(argv[6],AF_INET6); memset((char *) &addr6, 0, sizeof(addr6)); addr6.sin6_flowinfo = 0; addr6.sin6_family = AF_INET6; addr6.sin6_port = htons(port); addr6.sin6_addr = in6addr_any; //memmove((char *) &addr6.sin6_addr.s6_addr, (char *) server->h_addr, server->h_length); printf(" running (%s) test as ipv=%s\n", mode.c_str(), protocol.c_str()); if(ipv6_tcp_server_test(&addr6, port) == PASSED) printf("PASSED\n"); else printf("FAILED\n"); return 0; } } } /****************************************************************************/ /* SUSTAINED */ /****************************************************************************/ // SUSTAINED // Performs a stress test for benchmarking performance if(type == "sustained") { protocol = argv[4]; // 4, 6 mode = argv[5]; // client, server // SUSTAINED CLIENT if(mode == "client") { port = atoi(argv[7]); printf("connecting to %s on port %s\n", argv[6], argv[7]); // IPv4 if(protocol == "4") { addr.sin_port = htons(port); addr.sin_addr.s_addr = inet_addr(argv[6]); addr.sin_family = AF_INET; printf(" running (%s) test as ipv=%s\n", mode.c_str(), protocol.c_str()); if(ipv4_tcp_client_sustained_test(&addr, port, n_seconds, n_times) == PASSED) printf("PASSED\n"); else printf("FAILED\n"); return 0; } // IPv6 if(protocol == "6") { server = gethostbyname2(argv[6],AF_INET6); memset((char *) &addr6, 0, sizeof(addr6)); addr6.sin6_flowinfo = 0; addr6.sin6_family = AF_INET6; memmove((char *) &addr6.sin6_addr.s6_addr, (char *) server->h_addr, server->h_length); addr6.sin6_port = htons(port); printf(" running (%s) test as ipv=%s\n", mode.c_str(), protocol.c_str()); if(ipv6_tcp_client_sustained_test(&addr6, port, n_seconds, n_times) == PASSED) printf("PASSED\n"); else printf("FAILED\n"); return 0; } } // SUSTAINED SERVER if(mode == "server") { port = atoi(argv[7]); printf("serving on port %s\n", argv[7]); // IPv4 if(protocol == "4") { addr.sin_port = htons(port); addr.sin_addr.s_addr = inet_addr(argv[6]); // addr.sin_addr.s_addr = htons(INADDR_ANY); addr.sin_family = AF_INET; printf(" running (%s) test as ipv=%s\n", mode.c_str(), protocol.c_str()); if(ipv4_tcp_server_sustained_test(&addr, port, n_seconds, n_times) == PASSED) printf("PASSED\n"); else printf("FAILED\n"); return 0; } // IPv6 if(protocol == "6") { server = gethostbyname2(argv[6],AF_INET6); memset((char *) &addr6, 0, sizeof(addr6)); addr6.sin6_flowinfo = 0; addr6.sin6_family = AF_INET6; addr6.sin6_port = htons(port); addr6.sin6_addr = in6addr_any; //memmove((char *) &addr6.sin6_addr.s6_addr, (char *) server->h_addr, server->h_length); printf(" running (%s) test as ipv=%s\n", mode.c_str(), protocol.c_str()); if(ipv6_tcp_server_sustained_test(&addr6, port, n_seconds, n_times) == PASSED) printf("PASSED\n"); else printf("FAILED\n"); return 0; } } } /****************************************************************************/ /* COMPREHENSIVE */ /****************************************************************************/ // COMPREHENSIVE // Tests ALL API calls if(type == "comprehensive") { } /****************************************************************************/ /* RANDOM */ /****************************************************************************/ // RANDOM // performs random API calls with plausible (and random) arguments/data if(type == "random") { } printf("invalid configuration. exiting.\n"); return 0; }