pvl.socket: better logging
authorTero Marttila <terom@paivola.fi>
Sun, 13 Jan 2013 02:11:30 +0200
changeset 118 4f9bcf1e53e0
parent 117 58aebcd35e1a
child 119 40b5375d4a27
pvl.socket: better logging
pvl/socket.py
--- a/pvl/socket.py	Sun Jan 13 02:11:12 2013 +0200
+++ b/pvl/socket.py	Sun Jan 13 02:11:30 2013 +0200
@@ -8,16 +8,21 @@
 socket = __import__('socket')
 
 import select
+import errno
 
 import urlparse
 
 import logging; log = logging.getLogger('pvl.socket')
 
-URL = {
-    'tcp':  (0,                 socket.SOCK_STREAM  ), # AF_UNSPEC
-    'udp':  (0,                 socket.SOCK_DGRAM   ), # AF_UNSPEC
-    'unix': (socket.AF_UNIX,    None                ), # socktype is given
-}
+# order matters!
+URL = (
+    # scheme    family              socktype
+    ( 'unix',   (socket.AF_UNIX,    None                )   ), # socktype is given
+    ( 'tcp',    (0,                 socket.SOCK_STREAM  )   ), # AF_UNSPEC
+    ( 'udp',    (0,                 socket.SOCK_DGRAM   )   ), # AF_UNSPEC
+)
+
+URL_SCHEMES = dict(URL)
 
 def parse (str, port=None, scheme='tcp', unix=socket.SOCK_DGRAM) :
     """
@@ -26,13 +31,13 @@
         For AF_UNIX, the path is in host, and port is empty, and the socktype is the given unix=... value.
     """
    
-    family, socktype = URL[scheme]
+    family, socktype = URL_SCHEMES[scheme]
     url = urlparse.urlparse(str)
     
     # TODO: UNIX?
     if url.scheme and url.netloc :
         # proper url
-        family, socktype = URL[url.scheme]
+        family, socktype = URL_SCHEMES[url.scheme]
 
         return family, socktype, url.hostname, url.port or port
 
@@ -56,6 +61,7 @@
 
     if family == socket.AF_UNIX :
         raise ValueError("XXX: AF_UNIX is not yet supported", str)
+
     else : # AF_UNSPEC
         return connect_inet(host, port, family=family, socktype=socktype)
  
@@ -103,7 +109,7 @@
     else :
         raise Exception("Unable to connect: %s:%s: %s" % (host, port, error))
 
-def reverse (self, sockaddr, numeric_host=False, numeric_port=True) :
+def reverse (sockaddr, numeric_host=False, numeric_port=True) :
     """
         Resolve given sockaddr, returning (host, port).
     """
@@ -118,6 +124,27 @@
 
     return socket.getnameinfo(sockaddr, flags)
 
+def socket_str (sock) :
+    peer = sock.getpeername()
+    
+    # lookup scheme
+    for scheme, (family, socktype) in URL :
+        if family and family != sock.family :
+            continue
+        elif socktype and socktype != sock.type :
+            continue
+        else :
+            break
+    else :
+        scheme = None
+
+    host, port = reverse(peer)
+    
+    if scheme :
+        return "{scheme}://{host}:{port}".format(scheme=scheme, host=host, port=port)
+    else :
+        return "{host}:{port}".format(host=host, port=port)
+
 def nonblocking (call, *args, **kwargs) :
     """
         Call the given function, which read/writes on a nonblocking file, and return None if it would have blocked.
@@ -163,13 +190,14 @@
         
         buf = nonblocking(self.sock.recv, block)
 
+        log.debug("%s: %s", self, buf)
+
         # eof?
-        if not buf :
+        if buf :
+            return buf
+        else :
             raise EOFError()
 
-        # ok
-        return buf
-
     def peek (self) :
         """
             Peek at data in buffer.
@@ -216,6 +244,8 @@
         # in case we had \r\n
         line = line.rstrip('\r')
 
+        log.debug("%s: %s", self, line)
+
         return line
     
     def readlines (self) :
@@ -238,6 +268,9 @@
 
     __iter__ = readlines
 
+    def __str__ (self) :
+        return socket_str(self.sock)
+
 class WriteStream (object) :
     """
         Writable stream, supporting non-blocking/buffered writes.
@@ -311,10 +344,18 @@
             Write out line.
         """
 
-        self.write(str(line) + eol)
+        log.debug("%s: %s", self, line)
+
+        self.write(str(line))
+        self.write(eol)
     
     def __call__ (self, *lines) :
         for line in lines :
             self.writeline(line)
         
         # TODO: flush
+
+    def __str__ (self) :
+        return socket_str(self.sock)
+
+