tio icon indicating copy to clipboard operation
tio copied to clipboard

Support connecting to UNIX/TCP sockets

Open heroin-moose opened this issue 3 years ago • 8 comments

Connecting to UNIX sockets comes in be handy with QEMU, for example. Like when you have a bunch of VMs and want to connect to a serial console:

$ tio ~/VM/vm1.console

Quick POC shows that everything works, I'm able to read/write to a serial console with a simple diff:

diff --git a/src/tty.c b/src/tty.c
index 8c7bfa7..65c0289 100644
--- a/src/tty.c
+++ b/src/tty.c
@@ -1085,10 +1085,19 @@ int tty_connect(void)
     struct timeval tv;
     struct timeval *tv_p = &tv;
     bool ignore_stdin = false;
+    struct sockaddr_un addr;
 
-    /* Open tty device */
-    fd = open(option.tty_device, O_RDWR | O_NOCTTY | O_NONBLOCK);
-    if (fd < 0)
+    memset(&addr, 0, sizeof(addr));
+    addr.sun_family = AF_UNIX;
+    strncpy(addr.sun_path, option.tty_device, sizeof(addr.sun_path) - 1);
+
+    fd = socket(AF_UNIX, SOCK_STREAM, 0);
+    if (fd == -1) {
+	tio_error_printf("Cannot allocate socket (%s)", strerror(errno));
+	exit(EXIT_FAILURE);
+    }
+
+    if (connect(fd, (struct sockaddr *)&addr, sizeof(addr)) == -1)
     {
         tio_error_printf_silent("Could not open tty device (%s)", strerror(errno));
         goto error_open;
@@ -1098,7 +1107,9 @@ int tty_connect(void)
     if (!isatty(fd))
     {
         tio_error_printf("Not a tty device");
+#if 0
         exit(EXIT_FAILURE);;
+#endif
     }
 
     /* Lock device file */
@@ -1139,7 +1150,9 @@ int tty_connect(void)
     if (tcgetattr(fd, &tio_old) < 0)
     {
         tio_error_printf_silent("Could not get port settings (%s)", strerror(errno));
+#if 0
         goto error_tcgetattr;
+#endif
     }
 
 #ifdef HAVE_IOSSIOSPEED
@@ -1169,7 +1182,9 @@ int tty_connect(void)
     if (status == -1)
     {
         tio_error_printf_silent("Could not apply port settings (%s)", strerror(errno));
+#if 0
         goto error_tcsetattr;
+#endif
     }
 
     /* Set arbitrary baudrate (only works on supported platforms) */
@@ -1178,7 +1193,9 @@ int tty_connect(void)
         if (setspeed(fd, option.baudrate) != 0)
         {
             tio_error_printf_silent("Could not set baudrate speed (%s)", strerror(errno));
+#if 0
             goto error_setspeed;
+#endif
         }
     }
 
@@ -1394,9 +1411,11 @@ int tty_connect(void)
 
     return TIO_SUCCESS;
 
+#if 0
 error_setspeed:
 error_tcsetattr:
 error_tcgetattr:
+#endif
 error_read:
     tty_disconnect();
 error_open:

However it's necessary not call all TTY-related or else everything goes boom. I suspect that it's best to factor out two functions , one for each method. Anyway, if you are okay with the idea, I'll make a proper merge request.

heroin-moose avatar Oct 24 '22 09:10 heroin-moose

I'm a bit undecided on the feature of letting tio be able to connect to sockets. I mean, if you want to connect to a UNIX socket you could easily do so with nc -U <socket>. Of course, that will give you a raw connection and you won't have any of tio's features available (line time stamping, hex mode, local echo, mappings, auto connect, etc.).

That being said, tio already supports redirecting serial I/O to a socket using e.g. tio --socket unix:test-socket-0. Likewise tio could be used to connect to the same socket via a similar syntax tio unix:test-socket-0, tio inet:192.168.0.42:3333, etc. This way tio can be used end to end for sharing serial ports.

On the other hand, there is the principle of letting one tool do one thing well, namely connecting to serial ports.

lundmar avatar Oct 25 '22 11:10 lundmar

Sadly nc -U <socket> can't handle complex TTY features, can't handle escapes, echoes back passwords and so on. It is possible to run minicom -D unix#test.sock or socat with right flags, but I was thinking about replacing minicom with tio so this feature kinda felt natural. But of course I understand that this is not the primary focus of tio.

heroin-moose avatar Oct 25 '22 19:10 heroin-moose

After some more consideration I think it makes sense to support connecting to a socket as that will make tio be able to both serve a serial port via a socket and connect to it - it will be an end to end solution. In short we will be able to do the following:

Host serial port on socket: tio --socket unix:/tmp/tio-socket-0 /dev/ttyUSB0

Connect to same socket: tio unix:/tmp/tio-socket-0

However, getting there is a bit more involved. I'm making a TODO list here, mostly for my own reference.

Besides a bit of refactoring the following changes spring to mind:

  • Socket mode and type of socket should be activated via device name prefix. For example:
    • UNIX socket: tio unix:<filename>
    • TCPv4 socket: tio inet:<ip>:<port>
    • TCPv6 socket: tio inet6:<ip>:<port>
    • If no port number defined default to 3333
  • Mapping flags INLCR, IGNCR, ICRNL needs implementation for socket mode
  • Error messages should just say "device" instead of "tty device" etc.
  • Remove other tty'isms (tty_write() should be device_write() etc.)
  • In session key commands that do not work in socket mode should either not be listed or print an error messages if used.
  • All non-tty features should continue work (auto-connect etc.)
  • Shell completion script needs update
  • Man page needs update

lundmar avatar Oct 26 '22 18:10 lundmar

It would be really great to have unix socket support. nc -U ... is barely functional and minicom is a bit dated and limited. Key use case is of course QEMU.

pernu avatar Mar 17 '23 20:03 pernu

Wonderful! Given your list of changes, can you update the issue title to also mention TCP? I came here to request that only to see you already considered it part of this request :)

Habbie avatar Mar 27 '23 17:03 Habbie

I'm not sure if this should be a separate issue, but if TCP support is planned, could RFC 2217 be a feature alongside TCP? TLDR on RFC2217: it's an extension to telnet that allows a client to specify COM port parameters to a server. Example being the client wanting to change the baud rate on a console server in real time. And I don't know of a real world use, but maybe UDP too, instead of just TCP.

Zorbatron avatar Jan 05 '24 06:01 Zorbatron

@Zorbatron That is possible but first things first. It can be added if there is a demand for it.

lundmar avatar Jan 05 '24 20:01 lundmar

RFC 2217 would definitely be the way to go for TCP connections, would allow connecting to ser2net, proprietary TCP serial gateways, etc.. I would certainly love it!

vifino avatar May 21 '24 13:05 vifino