console: Update socket timeout functionality for Macs

This adjusts the original timeout code to use getsockopt(..., SO_NWRITE) to get
the number of sent but not acknowledged bytes. This is supported on all
BSD-derived/POSIX compliant systems since 4.3 BSD, but apparently Linux is the
sole outlier and only supports the fcntl() method.

Change-Id: I6ad4cb8d3f5e04d70bfbfa855de133674087814b
diff --git a/mdt/console.py b/mdt/console.py
index 5e31fcb..d01aa76 100644
--- a/mdt/console.py
+++ b/mdt/console.py
@@ -53,7 +53,7 @@
         self.channel = channel
         self.inputfile = inputfile
         self.has_tty = False
-        self.linux = os.uname()[0] == 'Linux'
+        self.uname = os.uname()
 
     def _updateWindowSize(self, signum, stackFrame):
         if self.has_tty:
@@ -61,15 +61,20 @@
             self.channel.resize_pty(columns, rows, 0, 0)
 
     def _socketSendQueueLevel(self):
-        # Only supported on Linux
-        if not self.linux:
-            return 0
-
         import fcntl
+        import socket
         import struct
+
         SIOCOUTQ = 0x5411
+        SO_NWRITE = 0x1024
         sock = self.channel.get_transport().sock
-        return struct.unpack("I", fcntl.ioctl(sock.fileno(), SIOCOUTQ, '\0\0\0\0'))[0]
+
+        # Only Linux doesn't support SO_NWRITE, which has been available since 4.3 BSD. O.o
+        if uname == "Linux":
+            return struct.unpack("I", fcntl.ioctl(sock.fileno(), SIOCOUTQ, '\0\0\0\0'))[0]
+
+        return sock.getsockopt(socket.SOL_SOCKET, SO_NWRITE)
+
 
     def run(self):
         import termios
@@ -108,24 +113,26 @@
         try:
             self.channel.settimeout(0)
             self.channel.get_transport().set_keepalive(KEEP_ALIVE_SECONDS)
-            timeouts = 0
-            tx_level = 0
+            timeout_count = 0
+            initial_tx_level = 0
 
             while True:
                 read, write, exception = select.select([self.channel,
                                                         self.inputfile],
                                                        [], [], KEEP_ALIVE_SECONDS + 1)
-                timeout = not read and not write and not exception
-                if self.linux and timeout:
-                    timeouts += 1
-                    if timeouts == 1:
-                        tx_level = self._socketSendQueueLevel()
+
+                select_timedout = not read and not write and not exception
+                if select_timedout:
+                    timeout_count += 1
+
+                    if timeout_count == 1:
+                        initial_tx_level = self._socketSendQueueLevel()
                     else:
                         current_tx_level = self._socketSendQueueLevel()
-                        if current_tx_level and current_tx_level >= tx_level:
+                        if current_tx_level and current_tx_level >= initial_tx_level:
                             raise SocketTimeoutError(socket.timeout())
                 else:
-                    timeouts = 0
+                    timeout_count = 0
 
                 # data from device to host
                 if self.channel in read: