nc.py is now functional enough for basic client use
authorTero Marttila <terom@fixme.fi>
Sat, 26 Sep 2009 22:09:24 +0300
changeset 55 99c4344a35ce
parent 54 e7c136812b0d
child 56 07ed878c847b
nc.py is now functional enough for basic client use
examples/nc.py
--- a/examples/nc.py	Sat Sep 26 21:52:06 2009 +0300
+++ b/examples/nc.py	Sat Sep 26 22:09:24 2009 +0300
@@ -19,6 +19,8 @@
 # global event_base
 ev_base = base.event_base()
 
+# buffer size to use, 4k - perhaps slightly smaller
+BUFSIZE = 4 * 1024
 
 def parse_argv (argv) :
     global options
@@ -113,6 +115,29 @@
             # yay
             yield sock
 
+
+def client_connect_next (sock_iter) :
+    """
+        Attempt to run the given connect operation, on the given iterable of sockets.
+    """
+
+    for sock in sock_iter :
+        # pend for writing
+        log_debug("client_connect_next: cb_event(%d, EV_WRITE, on_connect, %r)", sock.fd, sock)
+        ev = cb_event(ev_base, sock.fd, EV_WRITE, on_connect, sock, sock_iter)
+
+        # wait specified timeout
+        log_debug("client_connect_next: %r: add(%s)", ev, options.timeout)
+        ev.add(options.timeout)
+
+        # ok
+        break
+
+    else :
+        # fail, ran out of addresses to try
+        log_err("client_connect_next: ran out of addresses to try")
+
+
 def on_connect (ev, events, sock, sock_iter) :
     """
         Outbound connect EV_WRITE callback, i.e. connection failed or was established
@@ -140,29 +165,79 @@
 
 
     # ok, connected
-    log_info("on_connect: connected")
+    client_connected(sock)
 
 
-def client_connect_next (sock_iter) :
+def client_connected (sock) :
     """
-        Attempt to run the given connect operation, on the given iterable of sockets.
+        Connection established, start shovelling data
     """
 
-    for sock in sock_iter :
-        # pend for writing
-        log_debug("client_connect_next: cb_event(%d, EV_WRITE, on_connect, %r)", sock.fd, sock)
-        ev = cb_event(ev_base, sock.fd, EV_WRITE, on_connect, sock, sock_iter)
+    log_info("Client connected to %s (from %s)", sock.getpeername(), sock.getsockname())
+    
+    # go!
+    start_sock(sock, sys.stdin.fileno(), sys.stdout.fileno())
 
-        # wait specified timeout
-        log_debug("client_connect_next: %r: add(%s)", ev, options.timeout)
-        ev.add(options.timeout)
 
-        # ok
-        break
+def start_sock (sock, fd_in, fd_out) :
+    """
+        Start shipping data between sock and fin/fout.
+    """
+
+    # event for each
+    ev_in = cb_event(ev_base, fd_in, EV_READ, on_read_in, sock, fd_in)
+    ev_out = cb_event(ev_base, sock.fd, EV_READ, on_read_sock, sock, fd_out)
+
+    ev_in.add()
+    ev_out.add()
+
+
+def on_read_in (ev, events, sock, fd_in) :
+    """
+        Data readable on ev.fd, ship to sock
+    """
+    
+    # no timeouts yet
+    assert events & EV_READ
+    
+    # try and read
+    buf = os.read(fd_in, BUFSIZE)
+
+    if buf :
+        # pass on
+        assert sock.write(buf) == len(buf)
+
+        # keep going
+        ev.add()
 
     else :
-        # fail, ran out of addresses to try
-        log_err("client_connect_next: ran out of addresses to try")
+        # EOF
+        sock.shutdown(SHUT_WR)
+
+
+def on_read_sock (ev, events, sock, fd_out) :
+    """
+        Data readable on sock, ship to fd_out
+    """
+    
+    # no timeouts yet
+    assert events & EV_READ
+
+    # try and read
+    buf = sock.read(BUFSIZE)
+
+    if buf :
+        # pass on
+        assert os.write(fd_out, buf) == len(buf)
+
+        # keep going
+        ev.add()
+
+    else :
+        # EOF
+        os.close(fd_out)
+        
+        log_info("EOF from %s", sock.getpeername())
 
 def run_client (host, port) :
     """