pvl/socket.py
author Tero Marttila <terom@paivola.fi>
Mon, 01 Apr 2013 16:27:30 +0300
changeset 8 2c9bc42255a2
parent 7 95d06ed3c395
child 14 80d9f73f379a
permissions -rw-r--r--
merge
7
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
     1
"""
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
     2
    A simple TCP client in the kind of syslog.fifo/file.
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
     3
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
     4
    Interface: fileno(), __iter__, __call__
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
     5
"""
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
     6
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
     7
# XXX: absolute import plz
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
     8
socket = __import__('socket')
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
     9
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    10
import select
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    11
import errno
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    12
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    13
import urlparse
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    14
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    15
import logging; log = logging.getLogger('pvl.socket')
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    16
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    17
# order matters!
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    18
URL = (
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    19
    # scheme    family              socktype
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    20
    ( 'unix',   (socket.AF_UNIX,    None                )   ), # socktype is given
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    21
    ( 'tcp',    (0,                 socket.SOCK_STREAM  )   ), # AF_UNSPEC
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    22
    ( 'udp',    (0,                 socket.SOCK_DGRAM   )   ), # AF_UNSPEC
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    23
)
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    24
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    25
URL_SCHEMES = dict(URL)
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    26
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    27
def parse (str, port=None, scheme='tcp', unix=socket.SOCK_DGRAM) :
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    28
    """
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    29
        Parse given string into (AF_*, SOCK_*, host, port).
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    30
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    31
        For AF_UNIX, the path is in host, and port is empty, and the socktype is the given unix=... value.
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    32
    """
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    33
   
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    34
    family, socktype = URL_SCHEMES[scheme]
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    35
    url = urlparse.urlparse(str)
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    36
    
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    37
    # TODO: UNIX?
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    38
    if url.scheme and url.netloc :
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    39
        # proper url
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    40
        family, socktype = URL_SCHEMES[url.scheme]
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    41
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    42
        return family, socktype, url.hostname, url.port or port
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    43
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    44
    elif url.scheme and url.path :
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    45
        # host:port
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    46
        return family, socktype, url.scheme, int(url.path)
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    47
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    48
    elif url.path :
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    49
        # host
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    50
        return family, socktype, url.path, port
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    51
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    52
    else :
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    53
        raise ValueError("unparseable connect URL: %s", str)
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    54
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    55
def connect (str, *args, **kwargs) :
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    56
    """
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    57
        Returns a connected socket for given parse()'d string.
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    58
    """
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    59
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    60
    family, socktype, host, port = parse(str, *args, **kwargs)
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    61
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    62
    if family == socket.AF_UNIX :
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    63
        raise ValueError("XXX: AF_UNIX is not yet supported", str)
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    64
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    65
    else : # AF_UNSPEC
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    66
        return connect_inet(host, port, family=family, socktype=socktype)
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    67
 
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    68
def connect_inet (host=None, port=None, family=socket.AF_UNSPEC, socktype=socket.SOCK_STREAM) :
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    69
    """
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    70
        Return a TCP/UDP socket connected to the given host/port using getaddrinfo.
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    71
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    72
        TODO: timeout?
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    73
    """
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    74
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    75
    log.debug("%s:%s: family=%s, socktype=%s", host, port, family, socktype)
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    76
    
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    77
    if host :
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    78
        flags = socket.AI_CANONNAME
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    79
    else :
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    80
        flags = 0
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    81
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    82
    addrinfo = socket.getaddrinfo(host, port, family, socktype, 0, flags)
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    83
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    84
    if not addrinfo :
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    85
        raise Exception("getaddrinfo: %s:%s: no results" % (host, port))
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    86
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    87
    for af, st, proto, name, addr in addrinfo :
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    88
        try :
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    89
            sock = socket.socket(af, st, proto)
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    90
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    91
        except socket.error as error :
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    92
            log.warning("%s:%s: socket: %s", host, port, error)
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    93
            continue
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    94
        
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    95
        log.debug("%s:%s: socket: %s", host, port, sock)
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    96
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    97
        try :
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    98
            sock.connect(addr)
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    99
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   100
        except socket.error as error :
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   101
            log.warning("%s:%s: connect: %s", host, port, error)
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   102
            continue
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   103
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   104
        log.debug("%s:%s: connect", host, port)
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   105
        log.info("%s", name)
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   106
        
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   107
        return sock
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   108
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   109
    else :
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   110
        raise Exception("Unable to connect: %s:%s: %s" % (host, port, error))
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   111
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   112
def reverse (sockaddr, numeric_host=False, numeric_port=True) :
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   113
    """
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   114
        Resolve given sockaddr, returning (host, port).
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   115
    """
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   116
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   117
    flags = 0
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   118
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   119
    if numeric_host :
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   120
        flags |= socket.NI_NUMERICHOST
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   121
    
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   122
    if numeric_port :
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   123
        flags |= socket.NI_NUMERICSERV
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   124
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   125
    return socket.getnameinfo(sockaddr, flags)
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   126
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   127
def socket_str (sock) :
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   128
    # get connected peer
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   129
    try :
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   130
        peer = sock.getpeername()
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   131
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   132
    except socket.error as ex :
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   133
        # fails if socket is not connected XXX: even after EOF on read..?
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   134
        return str(ex)
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   135
    
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   136
    # lookup scheme
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   137
    for scheme, (family, socktype) in URL :
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   138
        if family and family != sock.family :
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   139
            continue
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   140
        elif socktype and socktype != sock.type :
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   141
            continue
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   142
        else :
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   143
            break
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   144
    else :
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   145
        scheme = None
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   146
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   147
    host, port = reverse(peer)
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   148
    
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   149
    if scheme :
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   150
        return "{scheme}://{host}:{port}".format(scheme=scheme, host=host, port=port)
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   151
    else :
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   152
        return "{host}:{port}".format(host=host, port=port)
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   153
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   154
def nonblocking (call, *args, **kwargs) :
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   155
    """
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   156
        Call the given function, which read/writes on a nonblocking file, and return None if it would have blocked.
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   157
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   158
        Raises EOFError on SIGPIPE/EPIPE.
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   159
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   160
        # XXX: does python handle SIGPIPE for us?
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   161
    """
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   162
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   163
    try :
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   164
        return call(*args, **kwargs)
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   165
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   166
    except socket.error as ex :
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   167
        # block?
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   168
        if ex.errno == errno.EAGAIN or ex.errno == errno.EWOULDBLOCK:
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   169
            # empty
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   170
            return None
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   171
        
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   172
        elif ex.errno == errno.EPIPE :
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   173
            # XXX: write-eof?
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   174
            raise EOFError()
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   175
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   176
        else :
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   177
            raise
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   178
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   179
class ReadStream (object) :
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   180
    """
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   181
        Buffered stream, supporting non-blocking/line-based reads.
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   182
    """
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   183
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   184
    BLOCK=512
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   185
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   186
    def __init__ (self, sock, buffer=None) :
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   187
        """
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   188
            TODO: buffer    - maximum line length
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   189
        """
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   190
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   191
        self.sock = sock
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   192
        self._buf = ''
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   193
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   194
    def fileno (self) :
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   195
        return self.sock.fileno()
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   196
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   197
    def _read (self, block=BLOCK) :
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   198
        """
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   199
            Read up to n bytes from socket.
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   200
            
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   201
            Returns None if we would block.
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   202
            Raises EOFError on EOF.
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   203
        """
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   204
        
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   205
        buf = nonblocking(self.sock.recv, block)
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   206
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   207
        log.debug("%s: %s", self, buf)
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   208
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   209
        if buf is None :
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   210
            return None
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   211
        elif buf :
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   212
            return buf
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   213
        else :
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   214
            raise EOFError()
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   215
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   216
    def peek (self) :
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   217
        """
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   218
            Peek at data in buffer.
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   219
        """
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   220
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   221
        return self._buf
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   222
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   223
    def read (self) :
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   224
        """
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   225
            Read and return any available input.
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   226
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   227
            Returns None if blocking.
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   228
        """
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   229
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   230
        if self._buf :
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   231
            buf, self._buf = self._buf, ''
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   232
            
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   233
        else :
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   234
            buf = self._read()
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   235
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   236
        return buf
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   237
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   238
    def readline (self) :
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   239
        """
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   240
            Read and return next waiting line from input.
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   241
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   242
            Line is returned without trailing '\r\n' or '\n'.
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   243
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   244
            Returns None if there is no line available.
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   245
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   246
            XXX: trailing data in buf when _read() raises EOFError?
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   247
        """
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   248
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   249
        while '\n' not in self._buf :
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   250
            # read chunk
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   251
            read = self._read()
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   252
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   253
            if read is None :
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   254
                return None
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   255
            
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   256
            self._buf += read
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   257
        
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   258
        # split out one line
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   259
        line, self._buf = self._buf.split('\n', 1)
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   260
        
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   261
        # in case we had \r\n
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   262
        line = line.rstrip('\r')
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   263
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   264
        log.debug("%s: %s", self, line)
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   265
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   266
        return line
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   267
    
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   268
    def readlines (self) :
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   269
        """
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   270
            Read any available input, yielding lines.
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   271
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   272
            Returns None if thre is no more input available.
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   273
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   274
            Raises EOFError in the socket was closed.
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   275
        """
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   276
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   277
        while True :
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   278
            line = self.readline()
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   279
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   280
            if line is None :
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   281
                return
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   282
            else :
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   283
                yield line
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   284
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   285
    __iter__ = readlines
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   286
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   287
    def __str__ (self) :
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   288
        return socket_str(self.sock)
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   289
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   290
class WriteStream (object) :
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   291
    """
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   292
        Writable stream, supporting non-blocking/buffered writes.
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   293
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   294
        XXX: buffering is completely untested
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   295
    """
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   296
    
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   297
    EOL = '\n'
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   298
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   299
    def __init__ (self, sock, buffer=None) :
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   300
        """
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   301
            TODO:   buffer  - maximum outgoing buffer length
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   302
        """
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   303
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   304
        self.sock = sock
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   305
        self._buf = buffer
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   306
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   307
    def _write (self, buf) :
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   308
        """
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   309
            Write given data to socket, returning the number of bytes written, or None, if buffering is enabled.
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   310
        """
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   311
        
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   312
        send = nonblocking(self.sock.send, buf)
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   313
        
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   314
        # eof on write?
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   315
        if send is None :
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   316
            return None
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   317
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   318
        elif send :
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   319
            # ok, message (partially) written
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   320
            return send
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   321
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   322
        else :
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   323
            # XXX: zero-length send? how do we handle this? What does it actually mean?
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   324
            # handle as a wouldblock...
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   325
            return None
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   326
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   327
    def write (self, data) :
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   328
        """
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   329
            Write given data to socket.
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   330
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   331
            TODO: buffer small chunks -> select writable -> write?
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   332
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   333
            Buffers if not able to write, or raises EOFError (hah!)
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   334
        """
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   335
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   336
        if not self._buf :
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   337
            # write directly
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   338
            while data :
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   339
                write = self._write(data)
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   340
                
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   341
                if write :
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   342
                    # remaining data
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   343
                    data = data[write:]
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   344
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   345
                else :
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   346
                    # cannot write more
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   347
                    break
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   348
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   349
        if not data :
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   350
            # sent
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   351
            return
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   352
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   353
        if self._buf is None :
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   354
            # no write buffering, and socket buffer full!
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   355
            raise EOFError()
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   356
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   357
        # append to outgoing buffer
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   358
        self._buf += data
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   359
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   360
    def writeline (self, line, eol=EOL) :
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   361
        """
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   362
            Write out line.
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   363
        """
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   364
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   365
        log.debug("%s: %s", self, line)
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   366
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   367
        self.write(str(line))
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   368
        self.write(eol)
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   369
    
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   370
    def __call__ (self, *lines) :
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   371
        for line in lines :
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   372
            self.writeline(line)
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   373
        
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   374
        # TODO: flush
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   375
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   376
    def __str__ (self) :
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   377
        return socket_str(self.sock)
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   378
95d06ed3c395 pvl.socket: move from pvl-irker
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   379