changeset 1961:d14630883b1d

Implement CMD_TCP_CON command
author doragasu <doragasu@hotmail.com>
date Sun, 03 May 2020 12:40:03 -0700
parents f79e16d8baa4
children 16d46ff1f620
files megawifi.c
diffstat 1 files changed, 77 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/megawifi.c	Sun May 03 12:39:05 2020 -0700
+++ b/megawifi.c	Sun May 03 12:40:03 2020 -0700
@@ -10,6 +10,7 @@
 #include <sys/socket.h>
 #include <unistd.h>
 #include <netinet/in.h>
+#include <netdb.h>
 #endif
 #include <errno.h>
 #include <fcntl.h>
@@ -185,6 +186,7 @@
 	}
 }
 
+
 static void start_reply(megawifi *mw, uint8_t cmd)
 {
 	mw_putc(mw, STX);
@@ -239,6 +241,78 @@
 	end_reply(mw);
 }
 
+static void cmd_tcp_con(megawifi *mw, uint32_t size)
+{
+	struct addrinfo hints;
+	struct addrinfo *res = NULL;
+	char dst_port[6];
+	char src_port[6];
+	char host[MAX_RECV_SIZE - 13];
+	int s;
+
+	int err;
+
+	uint8_t channel = mw->transmit_buffer[16];
+	if (!channel || channel > 15 || mw->sock_fds[channel - 1] >= 0) {
+		start_reply(mw, CMD_ERROR);
+		end_reply(mw);
+		return;
+	}
+	channel--;
+
+	strncpy(dst_port, (char*)&mw->transmit_buffer[4], 5);
+	dst_port[5] = '\0';
+	// TODO src_port is unused
+	strncpy(src_port, (char*)&mw->transmit_buffer[10], 5);
+	src_port[5] = '\0';
+	strncpy(host, (char*)&mw->transmit_buffer[17], MAX_RECV_SIZE - 14);
+	host[MAX_RECV_SIZE - 14] = '\0';
+
+	memset(&hints, 0, sizeof(hints));
+	hints.ai_family = AF_INET;
+	hints.ai_flags = AI_NUMERICSERV;
+	hints.ai_socktype = SOCK_STREAM;
+
+	if ((err = getaddrinfo(host, dst_port, &hints, &res)) != 0) {
+		printf("getaddrinfo failed: %s\n", gai_strerror(err));
+		start_reply(mw, CMD_ERROR);
+		end_reply(mw);
+		return;
+	}
+
+	s = socket(AF_INET, SOCK_STREAM, 0);
+	if (s < 0) {
+		goto err;
+	}
+
+	// Should this be handled in a separate thread to avoid blocking emulation?
+	if (connect(s, res->ai_addr, res->ai_addrlen) != 0) {
+		goto err;
+	}
+
+#ifndef _WIN32
+	//FIXME: Set nonblocking on Windows too
+	fcntl(s, F_SETFL, O_NONBLOCK);
+#endif
+	mw->sock_fds[channel] = s;
+	mw->channel_state[channel] = SOCKST_TCP_EST;
+	mw->channel_flags |= 1 << (channel + 1);
+	printf("Connection established on ch %d with %s:%s\n", channel + 1, host, dst_port);
+
+	if (res) {
+		freeaddrinfo(res);
+	}
+	start_reply(mw, CMD_OK);
+	end_reply(mw);
+	return;
+
+err:
+	freeaddrinfo(res);
+	printf("Connection to %s:%s failed, %s\n", host, dst_port, strerror(errno));
+	start_reply(mw, CMD_ERROR);
+	end_reply(mw);
+}
+
 static void process_command(megawifi *mw)
 {
 	uint32_t command = mw->transmit_buffer[0] << 8 | mw->transmit_buffer[1];
@@ -303,6 +377,9 @@
 		start_reply(mw, CMD_OK);
 		end_reply(mw);
 		break;
+	case CMD_TCP_CON:
+		cmd_tcp_con(mw, size);
+		break;
 	case CMD_TCP_BIND:{
 		if (size < 7){
 			start_reply(mw, CMD_ERROR);