mirror of
				https://github.com/mintty/wsltty.git
				synced 2025-10-31 07:04:00 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			227 lines
		
	
	
		
			7.7 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
			
		
		
	
	
			227 lines
		
	
	
		
			7.7 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
| diff --git a/src/wslbridge2-backend.cpp b/src/wslbridge2-backend.cpp
 | |
| index 8b86cc6..63a19e5 100644
 | |
| --- a/src/wslbridge2-backend.cpp
 | |
| +++ b/src/wslbridge2-backend.cpp
 | |
| @@ -17,6 +17,7 @@
 | |
|  #include <sys/wait.h>
 | |
|  #include <unistd.h>
 | |
|  #include <wordexp.h>
 | |
| +#include <limits.h> // PIPE_BUF
 | |
|  
 | |
|  #include <string>
 | |
|  #include <vector>
 | |
| @@ -196,6 +197,7 @@ int main(int argc, char *argv[])
 | |
|  
 | |
|          ssize_t readRet = 0, writeRet = 0;
 | |
|          char data[1024]; /* Buffer to hold raw data from pty */
 | |
| +        assert(sizeof data <= PIPE_BUF);
 | |
|  
 | |
|          do
 | |
|          {
 | |
| @@ -206,8 +208,85 @@ int main(int argc, char *argv[])
 | |
|              if (fds[0].revents & POLLIN)
 | |
|              {
 | |
|                  readRet = recv(ioSockets.inputSock, data, sizeof data, 0);
 | |
| -                if (readRet > 0)
 | |
| -                    writeRet = write(mfd_dp, data, readRet);
 | |
| +                char * s = data;
 | |
| +                int len = readRet;
 | |
| +                writeRet = 1;
 | |
| +                while (writeRet > 0 && len > 0)
 | |
| +                {
 | |
| +                    if (!*s)
 | |
| +                    {
 | |
| +                        // dispatch NUL escaped inband information
 | |
| +                        s++;
 | |
| +                        len--;
 | |
| +
 | |
| +                        if (len < 9 && s + 9 >= data + sizeof data)
 | |
| +                        {
 | |
| +                            // make room for additional loading
 | |
| +                            memcpy(data, s, len);
 | |
| +                            s = data;
 | |
| +                        }
 | |
| +
 | |
| +                        // ensure 1 more byte is loaded to dispatch on
 | |
| +                        if (!len)
 | |
| +                        {
 | |
| +                            readRet = recv(ioSockets.inputSock, s, 1, 0);
 | |
| +                            if (readRet > 0)
 | |
| +                            {
 | |
| +                                len += readRet;
 | |
| +                            }
 | |
| +                            else
 | |
| +                            {
 | |
| +                                writeRet = -1;
 | |
| +                                break;
 | |
| +                            }
 | |
| +                        }
 | |
| +                        if (*s == 2)
 | |
| +                        {
 | |
| +                            // STX: escaped NUL
 | |
| +                            s++;
 | |
| +                            len--;
 | |
| +                            writeRet = write(mfd_dp, "", 1);
 | |
| +                        }
 | |
| +                        else if (*s == 16)
 | |
| +                        {
 | |
| +                            // DLE: terminal window size change
 | |
| +                            s++;
 | |
| +                            len--;
 | |
| +                            // ensure 8 more bytes are loaded for winsize
 | |
| +                            while (readRet > 0 && len < 8)
 | |
| +                            {
 | |
| +                                readRet = recv(ioSockets.inputSock, s + len, 8 - len, 0);
 | |
| +                                if (readRet > 0)
 | |
| +                                {
 | |
| +                                    len += readRet;
 | |
| +                                }
 | |
| +                            }
 | |
| +                            if (readRet <= 0)
 | |
| +                            {
 | |
| +                                writeRet = -1;
 | |
| +                                break;
 | |
| +                            }
 | |
| +                            struct winsize * winsp = (struct winsize *)s;
 | |
| +                            s += 8;
 | |
| +                            len -= 8;
 | |
| +                            winsp->ws_xpixel = 0;
 | |
| +                            winsp->ws_ypixel = 0;
 | |
| +                            ret = ioctl(mfd, TIOCSWINSZ, winsp);
 | |
| +                            if (ret != 0)
 | |
| +                                perror("ioctl(TIOCSWINSZ)");
 | |
| +                        }
 | |
| +                    }
 | |
| +                    else
 | |
| +                    {
 | |
| +                        int n = strnlen(s, len);
 | |
| +                        writeRet = write(mfd_dp, s, n);
 | |
| +                        if (writeRet > 0)
 | |
| +                        {
 | |
| +                            s += writeRet;
 | |
| +                            len -= writeRet;
 | |
| +                        }
 | |
| +                    }
 | |
| +                }
 | |
|              }
 | |
|  
 | |
|              /* Resize window when buffer received in control socket */
 | |
| diff --git a/src/wslbridge2.cpp b/src/wslbridge2.cpp
 | |
| index 300ad57..3ba9096 100644
 | |
| --- a/src/wslbridge2.cpp
 | |
| +++ b/src/wslbridge2.cpp
 | |
| @@ -43,19 +43,41 @@ union IoSockets
 | |
|  /* global variable */
 | |
|  static volatile union IoSockets g_ioSockets = { 0 };
 | |
|  
 | |
| +#define dont_debug_inband
 | |
| +#define dont_use_controlsocket
 | |
| +
 | |
|  static void resize_window(int signum)
 | |
|  {
 | |
| +#ifdef use_controlsocket
 | |
| +#warning this may crash for unknown reason, maybe terminate the backend
 | |
|      struct winsize winp;
 | |
| +    ioctl(STDIN_FILENO, TIOCGWINSZ, &winp);
 | |
|  
 | |
|      /* Send terminal window size to control socket */
 | |
| -    ioctl(STDIN_FILENO, TIOCGWINSZ, &winp);
 | |
|      send(g_ioSockets.controlSock, (char *)&winp, sizeof winp, 0);
 | |
| +#else
 | |
| +    static char wins[2 + sizeof(struct winsize)] = {0, 16};
 | |
| +    static struct winsize * winsp = (struct winsize *)&wins[2];
 | |
| +    ioctl(STDIN_FILENO, TIOCGWINSZ, winsp);
 | |
| +
 | |
| +#ifdef debug_inband
 | |
| +    /* Send terminal window size inband, visualized as ESC sequence */
 | |
| +    char resizesc[55];
 | |
| +    //sprintf(resizesc, "\e_8;%u;%u\a", winsp->ws_row, winsp->ws_col);
 | |
| +    sprintf(resizesc, "^[_8;%u;%u^G", winsp->ws_row, winsp->ws_col);
 | |
| +    send(g_ioSockets.inputSock, resizesc, strlen(resizesc), 0);
 | |
| +#else
 | |
| +    /* Send terminal window size inband, with NUL escape */
 | |
| +    send(g_ioSockets.inputSock, wins, sizeof wins, 0);
 | |
| +#endif
 | |
| +#endif
 | |
|  }
 | |
|  
 | |
|  static void* send_buffer(void *param)
 | |
|  {
 | |
|      int ret;
 | |
|      char data[1024];
 | |
| +    assert(sizeof data <= PIPE_BUF);
 | |
|  
 | |
|      while (1)
 | |
|      {
 | |
| @@ -65,8 +87,33 @@ static void* send_buffer(void *param)
 | |
|              closesocket(g_ioSockets.inputSock);
 | |
|              break;
 | |
|          }
 | |
| -        if (!send(g_ioSockets.inputSock, data, ret, 0))
 | |
| -            break;
 | |
| +            char * s = data;
 | |
| +            int len = ret;
 | |
| +            while (ret > 0 && len > 0)
 | |
| +            {
 | |
| +                if (!*s)
 | |
| +                {
 | |
| +                    // send NUL STX
 | |
| +#ifdef debug_inband
 | |
| +                    ret = send(g_ioSockets.inputSock, (void*)"nul", 3, 0);
 | |
| +#else
 | |
| +                    static char NUL_STX[] = {0, 2};
 | |
| +                    ret = send(g_ioSockets.inputSock, NUL_STX, 2, 0);
 | |
| +#endif
 | |
| +                    s++;
 | |
| +                    len--;
 | |
| +                }
 | |
| +                else
 | |
| +                {
 | |
| +                    int n = strnlen(s, len);
 | |
| +                    ret = send(g_ioSockets.inputSock, s, n, 0);
 | |
| +                    if (ret > 0)
 | |
| +                    {
 | |
| +                        s += ret;
 | |
| +                        len -= ret;
 | |
| +                    }
 | |
| +                }
 | |
| +            }
 | |
|      }
 | |
|  
 | |
|      pthread_exit(&ret);
 | |
| @@ -480,16 +527,6 @@ int main(int argc, char *argv[])
 | |
|          g_ioSockets.controlSock = win_local_accept(controlSock);
 | |
|      }
 | |
|  
 | |
| -    /* Capture window resize signal and send buffer to control socket */
 | |
| -    {
 | |
| -    struct sigaction act;
 | |
| -    memset(&act, 0, sizeof act);
 | |
| -    act.sa_handler = resize_window;
 | |
| -    act.sa_flags = SA_RESTART;
 | |
| -    ret = sigaction(SIGWINCH, &act, NULL);
 | |
| -    assert(ret == 0);
 | |
| -    }
 | |
| -
 | |
|      /* Create thread to send input buffer to input socket */
 | |
|      pthread_t tidInput;
 | |
|      ret = pthread_create(&tidInput, nullptr, send_buffer, nullptr);
 | |
| @@ -502,6 +539,17 @@ int main(int argc, char *argv[])
 | |
|  
 | |
|      termState.enterRawMode();
 | |
|  
 | |
| +    /* Create thread to send window size through control socket */
 | |
| +    struct sigaction act = {};
 | |
| +    act.sa_handler = resize_window;
 | |
| +    act.sa_flags = SA_RESTART;
 | |
| +    ret = sigaction(SIGWINCH, &act, NULL);
 | |
| +    assert(ret == 0);
 | |
| +
 | |
| +    /* Notify initial size in case it's changed since starting */
 | |
| +    //resize_window(0);
 | |
| +    kill(getpid(), SIGWINCH);
 | |
| +
 | |
|      /*
 | |
|       * wsltty#254: WORKAROUND: Terminates input thread forcefully
 | |
|       * when output thread exits. Need some inter-thread syncing.
 |