about summary refs log tree commit diff
diff options
context:
space:
mode:
authorNakidai <nakidai@disroot.org>2025-05-20 00:33:49 +0300
committerNakidai <nakidai@disroot.org>2025-05-20 00:33:49 +0300
commiteba7daeebc79080ede43d440ee075b0ef7ca96eb (patch)
tree283b9e10652648e8fa5ba5af982c7dcd48f48053
downloadsmalltcp-eba7daeebc79080ede43d440ee075b0ef7ca96eb.tar.gz
smalltcp-eba7daeebc79080ede43d440ee075b0ef7ca96eb.zip
Add code
-rw-r--r--.gitignore2
-rw-r--r--LICENSE10
-rw-r--r--Makefile19
-rw-r--r--README11
-rw-r--r--buc.c20
-rw-r--r--bus.c67
6 files changed, 129 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..a577849
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+buc
+bus
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..7ae8865
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,10 @@
+Permission to use, copy, modify, and/or distribute this software for
+any purpose with or without fee is hereby granted.
+
+THE SOFTWARE IS PROVIDED “AS IS” AND THE AUTHOR DISCLAIMS ALL
+WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE
+FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
+DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
+AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..5fd5245
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,19 @@
+RM ?= rm -f
+PREFIX ?= /usr/local/
+BINDIR ?= ${PREFIX}/bin
+
+CFLAGS += -ansi
+
+.PHONY: all
+all: buc bus
+
+install: all
+	install -d ${BINDIR}
+	install -m755 buc bus ${BINDIR}
+
+uninstall:
+	${RM} ${BINDIR}/buc ${BINDIR}/bus
+
+.PHONY: clean
+clean:
+	${RM} buc bus
diff --git a/README b/README
new file mode 100644
index 0000000..1930e75
--- /dev/null
+++ b/README
@@ -0,0 +1,11 @@
+SmallTCP
+========
+these are small scripts for TCP client (buc) and server (bus). buc connects to a
+server and works like netcat. bus broadcasts messages between peers.
+
+usages:
+buc [ip [port]]
+bus [port [ip]]
+
+default port in 8604
+default ip is (client == buc ? 127.0.0.1 : 0.0.0.0)
diff --git a/buc.c b/buc.c
new file mode 100644
index 0000000..d54d0d1
--- /dev/null
+++ b/buc.c
@@ -0,0 +1,20 @@
+#include <arpa/inet.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <poll.h>
+
+char buf[512]; progress, all;
+atoi(), err(), exit(), read(), write();
+
+#define	readbuf(sock)	((((progress = read((sock), buf, sizeof(buf))) == -1) && err(1, "read()") || !progress && exit(0)), progress)
+#define	sendbuf(sock, size)	(write(sock, buf, size) == -1 && err(1, "write()"))
+
+main(argc, argv) char **argv; {
+	struct sockaddr_in addr = {AF_INET, htons(argc > 2 ? atoi(argv[1]) : 8604), inet_addr(argc > 1 ? argv[1] : "127.0.0.1")};
+	struct pollfd fds[2] = {{0, POLLIN}, {0, POLLIN}};
+	for (	(fds[1].fd = socket(AF_INET, SOCK_STREAM, 0)) == -1 && err(1, "socket()"),
+	     	connect(fds[1].fd, (void *)&addr, sizeof(addr)) == -1 && err(1, "connect()");
+	;)   	poll(fds, 2, -1) == -1 && err(1, "poll()"),
+	     	fds[0].revents & POLLIN && sendbuf(fds[1].fd, readbuf(0)),
+	     	fds[1].revents & POLLIN && sendbuf(1, readbuf(fds[1].fd));
+}
diff --git a/bus.c b/bus.c
new file mode 100644
index 0000000..7b4d01d
--- /dev/null
+++ b/bus.c
@@ -0,0 +1,67 @@
+#include <signal.h>
+#include <arpa/inet.h>
+#include <netinet/in.h>
+#include <sys/socket.h>
+#include <poll.h>
+
+err(), warn(), warnx(), read(), write(), close();
+
+#define SOCKETS_MAX 128
+#define BUFFER_SIZE 512
+
+#define lengthof(X) (sizeof(X) / sizeof(*(X)))
+
+main(argc, argv) char **argv;
+{
+	struct sockaddr_in addr = {AF_INET, htons(8604), htonl(INADDR_ANY)};
+	struct pollfd ppeers[SOCKETS_MAX] = {0};
+	int peers[SOCKETS_MAX] = {0}, client, i, j, written, readed;
+	char buf[BUFFER_SIZE] = {0};
+
+	for (
+		argc > 1 && (addr.sin_port = htons(atoi(argv[1]))),
+		argc > 2 && inet_pton(AF_INET, argv[1], &addr.sin_addr) == -1 && err(1, "inet_pton()"),
+		(peers[0] = socket(AF_INET, SOCK_STREAM, 0)) == -1 && err(1, "socket()"),
+		setsockopt(peers[0], SOL_SOCKET, SO_REUSEADDR, &(int){1}, sizeof(int)) == -1 && err(1, "setsockopt()"),
+		bind(peers[0], (void *)&addr, sizeof(addr)) == -1 && err(1, "bind()"),
+		listen(peers[0], 16) == -1 && err(1, "listen()"),
+		signal(SIGPIPE, SIG_IGN);
+	;)
+	{
+		for (written = i = 0; i < lengthof(peers) ? (peers[i] && ((ppeers[written++] = (struct pollfd){peers[i], POLLIN}), 0), 1) : 0; ++i)
+			if (i + 1 == lengthof(peers))
+				for (
+				client = 0, j = 1, poll(ppeers, written, -1) == -1 && err(1, "poll");
+				ppeers[0].revents & POLLIN &&
+				(client ? client : (client = accept(peers[0], 0, 0))) == -1
+				?	(warn("accept()"), 0)
+				:	(
+					j < lengthof(peers)
+					?	(!peers[j] ? ((peers[j] = client), 0) : 1)
+					:	1
+				);
+				++j
+				)
+					if (j + 1 == lengthof(peers))
+						warnx("dropping %d as peer list is full", client),
+						close(client);
+		for (i = 1; i < written; ++i)
+			if (ppeers[i].revents & POLLIN)
+				for (
+				readed = read(ppeers[i].fd, buf, sizeof(buf)),
+				j = 1;
+				j < lengthof(peers)
+				?	(
+					readed == -1 || !readed
+					?	(
+						ppeers[i].fd == peers[j]
+						?	(close(peers[j]), peers[j] = 0)
+						:	1
+					)
+					:	(peers[j] && ppeers[i].fd != peers[j] && write(peers[j], buf, readed), 1)
+				)
+				:	0;
+				++j
+				);
+	}
+}