Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support connecting to UNIX/TCP sockets #175

Open
heroin-moose opened this issue Oct 24, 2022 · 8 comments
Open

Support connecting to UNIX/TCP sockets #175

heroin-moose opened this issue Oct 24, 2022 · 8 comments

Comments

@heroin-moose
Copy link

heroin-moose commented Oct 24, 2022

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.

@lundmar
Copy link
Member

lundmar commented Oct 25, 2022

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.

@heroin-moose
Copy link
Author

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.

@lundmar
Copy link
Member

lundmar commented Oct 26, 2022

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

@pernu
Copy link

pernu commented Mar 17, 2023

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.

@Habbie
Copy link
Contributor

Habbie commented Mar 27, 2023

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 :)

@lundmar lundmar changed the title Support connecting to UNIX sockets Support connecting to UNIX/TCP sockets Mar 27, 2023
@Zorbatron
Copy link

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.

@lundmar
Copy link
Member

lundmar commented Jan 5, 2024

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

@vifino
Copy link

vifino commented May 21, 2024

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!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Development

No branches or pull requests

6 participants