summaryrefslogtreecommitdiff
path: root/latency.c
diff options
context:
space:
mode:
Diffstat (limited to 'latency.c')
-rw-r--r--latency.c97
1 files changed, 97 insertions, 0 deletions
diff --git a/latency.c b/latency.c
new file mode 100644
index 0000000..6181e84
--- /dev/null
+++ b/latency.c
@@ -0,0 +1,97 @@
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/uio.h>
+#include <errno.h>
+#include <netdb.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#include "proxy.h"
+
+static int parse_host(const char *host, const char *port, struct addrinfo **addr)
+{
+ struct addrinfo hints = {
+ .ai_family = AF_UNSPEC,
+ .ai_socktype = SOCK_STREAM,
+ .ai_flags = AI_PASSIVE,
+ };
+
+ int err;
+ if ((err = getaddrinfo(host, port, &hints, addr))) {
+ fprintf(stderr, "getaddrinfo failed: %s\n", gai_strerror(err));
+ return -1;
+ }
+
+ return 0;
+}
+
+static int listen_source(struct addrinfo *source)
+{
+ int fd = -1;
+ for (struct addrinfo *a = source; a; a = a->ai_next) {
+ if ((fd = socket(a->ai_family, a->ai_socktype, a->ai_protocol)) == -1)
+ continue;
+ if (!bind(fd, a->ai_addr, a->ai_addrlen) && !listen(fd, 1))
+ break;
+ close(fd);
+ fd = -1;
+ }
+ return fd;
+}
+
+static int connect_target(struct addrinfo *target)
+{
+ int fd = -1;
+ for (struct addrinfo *a = target; a; a = a->ai_next) {
+ if ((fd = socket(a->ai_family, a->ai_socktype, a->ai_protocol)) == -1)
+ continue;
+ if (connect(fd, a->ai_addr, a->ai_addrlen) != -1)
+ break;
+ close(fd);
+ fd = -1;
+ }
+ return fd;
+}
+
+int main(int argc, char **argv)
+{
+ struct addrinfo *source;
+ struct addrinfo *target;
+
+ if (argc != 3) {
+ fprintf(stderr, "usage: %s targethost targetport\n", argv[0]);
+ return -1;
+ }
+
+ if (parse_host(NULL, "1234", &source))
+ return -1;
+ if (parse_host(argv[1], argv[2], &target))
+ return -1;
+
+ int listenfd = listen_source(source);
+ if (listenfd < 0) {
+ perror("listen_source");
+ return -1;
+ }
+
+ for (;;) {
+ int sourcefd = accept(listenfd, NULL, NULL);
+ if (sourcefd == -1) break;
+
+ int targetfd = connect_target(target);
+ if (targetfd == -1) {
+ perror("connect_target");
+ close(sourcefd);
+ break;
+ }
+
+ proxy(sourcefd, targetfd, 500);
+
+ close(targetfd);
+ close(sourcefd);
+ }
+
+ close(listenfd);
+ return 0;
+}
+