[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

[or-cvs] Finish making new (v1) controller logic and multiplexing lo...



Update of /home/or/cvsroot/control/python
In directory moria:/tmp/cvs-serv21811/python

Modified Files:
	TorCtl.py TorCtl0.py TorCtl1.py TorExample.py 
Log Message:
Finish making new (v1) controller logic and multiplexing logic work in Python and Java controllers. Try out example code a bit.

Index: TorCtl.py
===================================================================
RCS file: /home/or/cvsroot/control/python/TorCtl.py,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- TorCtl.py	19 Jun 2005 22:38:31 -0000	1.3
+++ TorCtl.py	24 Jun 2005 18:03:27 -0000	1.4
@@ -7,8 +7,8 @@
 TorCtl -- Library to control Tor processes.  See TorCtlDemo.py for example use.
 """
 
-import TorCtl0
-import TorCtl1
+import struct
+import sys
 
 class TorCtlError(Exception):
     "Generic error raised by TorControl code."
@@ -97,10 +97,11 @@
 
         return evtype, args
 
-    def handle1(self, evbody):
+    def handle1(self, lines):
         """Dispatcher: called from Connection when an event is received."""
-        evtype, args = self.decode1(evbody)
-        self._map1.get(evtype, self.unknownEvent)(evtype, *args)
+        for code, msg, data in lines:
+            evtype, args = self.decode1(msg)
+            self._map1.get(evtype, self.unknownEvent)(evtype, *args)
 
     def decode1(self, body):
         """Unpack an event message into a type/arguments-tuple tuple."""
@@ -165,7 +166,7 @@
         """
         raise NotImplemented
 
-    def streamStatus(self, status, circID, target, circID="0"):
+    def streamStatus(self, status, streamID, target, circID="0"):
         """Called when a stream status changes if listening to STREAMSTATUS
            events.  'status' is a member of STREAM_STATUS; streamID is a
            numeric stream ID, and 'target' is the destination of the stream.
@@ -200,6 +201,35 @@
         """DOCDOC"""
         raise NotImplemented
 
+class DebugEventHandler(EventHandler):
+    """Trivial event handler: dumps all events to stdout."""
+    def __init__(self, out=None):
+        if out is None:
+            out = sys.stdout
+        self._out = out
+
+    def handle0(self, body):
+        evtype, args = self.decode0(body)
+        print >>self._out,EVENT_TYPE.nameOf[evtype],args
+
+    def handle1(self, lines):
+        for code, msg, data in lines:
+            print >>self._out, msg
+
+def detectVersion(s):
+    s.sendall("\x00\x00\r\n")
+    m = s.recv(4)
+    v0len, v0type = struct.unpack("!HH", m)
+    if v0type == '\x00\x00':
+        s.recv(v0len)
+        return 0
+    if '\n' not in m:
+        while 1:
+            c = s.recv(1)
+            if c == '\n':
+                break
+    return 1
+
 def parseHostAndPort(h):
     """Given a string of the form 'address:port' or 'address' or
        'port' or '', return a two-tuple of (address, port)
@@ -221,6 +251,15 @@
 
     return host, port
 
+def get_connection(sock):
+    v = detectVersion(sock)
+    if v == 0:
+        import TorCtl0
+        return TorCtl0.Connection(sock)
+    else:
+        import TorCtl1
+        return TorCtl1.Connection(sock)
+
 def secret_to_key(secret, s2k_specifier):
     c = ord(s2k_specifier[8])
     EXPBIAS = 6

Index: TorCtl0.py
===================================================================
RCS file: /home/or/cvsroot/control/python/TorCtl0.py,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- TorCtl0.py	19 Jun 2005 22:38:31 -0000	1.1
+++ TorCtl0.py	24 Jun 2005 18:03:27 -0000	1.2
@@ -20,7 +20,6 @@
     "MSG_TYPE", "EVENT_TYPE", "CIRC_STATUS", "STREAM_STATUS",
     "OR_CONN_STATUS", "SIGNAL", "ERR_CODES",
     "TorCtlError", "ProtocolError", "ErrorReply", "Connection", "EventHandler",
-    "DebugEventHandler", "parseHostAndPort"
     ]
 
 class _Enum:
@@ -429,6 +428,16 @@
         """Send the signal 'sig' to the Tor process; 'sig' must be a member of
            SIGNAL.
         """
+        try:
+            sig = sig.upper()
+        except AttributeError:
+            pass
+        sig = { "HUP" : 0x01, "RELOAD" : 0x01,
+                "INT" : 0x02, "SHUTDOWN" : 0x02,
+                "DUMP" : 0x0A, "USR1" : 0x0A,
+                "USR2" : 0x0C, "DEBUG" : 0x0C,
+                "TERM" : 0x0F, "HALT" : 0x0F
+                }.get(sig,sig)
         self._sendAndRecv(MSG_TYPE.SIGNAL,struct.pack("B",sig))
 
     def map_address(self, kvList):
@@ -479,13 +488,3 @@
         """Tell Tor about a new descriptor in 'descriptor'."""
         self._sendAndRecv(MSG_TYPE.POSTDESCRIPTOR,descriptor)
 
-class DebugEventHandler(EventHandler):
-    """Trivial event handler: dumps all events to stdout."""
-    def __init__(self, out=None):
-        if out is None:
-            out = sys.stdout
-        self._out = out
-
-    def handle(self, body):
-        evtype, args = self.decode(body)
-        print >>self._out,EVENT_TYPE.nameOf[evtype],args

Index: TorCtl1.py
===================================================================
RCS file: /home/or/cvsroot/control/python/TorCtl1.py,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- TorCtl1.py	19 Jun 2005 22:38:31 -0000	1.1
+++ TorCtl1.py	24 Jun 2005 18:03:27 -0000	1.2
@@ -11,6 +11,7 @@
 import threading
 import types
 import Queue
+import TorCtl
 
 def _quote(s):
     return re.sub(r'([\r\n\\\"])', r'\\\1', s)
@@ -43,17 +44,6 @@
     else:
         return "\r\n".join(lines)
 
-def _parseKV(body,sep=" ",term="\n"):
-    """Helper: parse a key/value list of the form [key sep value term]* .
-       Return a list of (k,v)."""
-    res = []
-    for line in body.split(term):
-        if not line: continue
-        k, v = line.split(sep,1)
-        res.append((k,v))
-    return res
-
-
 def _read_reply(f,debugFile=None):
     lines = []
     while 1:
@@ -61,18 +51,17 @@
         if debugFile:
             debugFile.write("    %s\n" % line)
         if len(line)<4:
-            raise ProtocolError("Badly formatted reply line: Too short")
+            raise TorCtl.ProtocolError("Badly formatted reply line: Too short")
         code = line[:3]
         tp = line[3]
-        s = line[3:]
-        if s == "-":
-            lines.append((tp, s, None))
-        elif s == " ":
-            lines.append((tp, s, None))
+        s = line[4:]
+        if tp == "-":
+            lines.append((code, s, None))
+        elif tp == " ":
+            lines.append((code, s, None))
             return lines
-        elif s != "+":
-            raise ProtocolError("Badly formatted reply line: unknown type %r",
-                                s)
+        elif tp != "+":
+            raise TorCtl.ProtocolError("Badly formatted reply line: unknown type %r"%tp)
         else:
             more = []
             while 1:
@@ -82,10 +71,10 @@
                 if line in (".\r\n", ".\n"):
                     break
                 more.append(line)
-            lines.append((tp, s, _unescape_dots("".join(more)))
+            lines.append((code, s, _unescape_dots("".join(more))))
 
 class Connection:
-        """A Connection represents a connection to the Tor process."""
+    """A Connection represents a connection to the Tor process."""
     def __init__(self, sock, file=None):
         """Create a Connection to communicate with the Tor process over the
            socket 'sock'.
@@ -142,7 +131,7 @@
             assert lines
             if lines[0][0][0] == "6":
                 if self._handler is not None:
-                    self._handler.handle1(body)
+                    self._handler.handle1(lines)
             else:
                 cb = self._queue.get()
                 cb(lines)
@@ -151,7 +140,7 @@
         """Helper: Send a command 'msg' to Tor, and wait for a command
            in response.  If the response type is in expectedTypes,
            return a list of (tp,body,extra) tuples.  If it is an
-           error, raise ErrorReply.  Otherwise, raise ProtocolError.
+           error, raise ErrorReply.  Otherwise, raise TorCtl.ProtocolError.
         """
         # This condition will get notified when we've got a result...
         condition = threading.Condition()
@@ -178,6 +167,7 @@
             if self._debugFile:
                 self._debugFile.write(">>> %s" % msg)
             self._s.write(msg)
+            self._s.flush()
         finally:
             self._sendLock.release()
 
@@ -194,9 +184,9 @@
         lines = result[0]
         for tp, msg, _ in lines:
             if tp[0] in '45':
-                raise ErrorReply("%s %s"%(tp, msg))
+                raise TorCtl.ErrorReply("%s %s"%(tp, msg))
             if tp not in expectedTypes:
-                raise ProtocolError("Unexpectd message type %r"%tp)
+                raise TorCtl.ProtocolError("Unexpectd message type %r"%tp)
 
         return lines
 
@@ -204,7 +194,7 @@
         """Send an authenticating secret to Tor.  You'll need to call this
            method before Tor can start.
         """
-        hexstr = binascii.b2a_hex(MSG_TYPE.AUTH,secret)
+        hexstr = binascii.b2a_hex(secret)
         self._sendAndRecv("AUTHENTICATE %s\r\n"%hexstr)
 
     def get_option(self, name):
@@ -215,6 +205,7 @@
             name = " ".join(name)
         lines = self._sendAndRecv("GETCONF %s\r\n" % name)
 
+        r = []
         for _,line,_ in lines:
             try:
                 key, val = line.split("=", 1)
@@ -252,7 +243,7 @@
             try:
                 k,rest = msg.split("=",1)
             except ValueError:
-                raise ProtocolError("Bad info line %r",msg)
+                raise TorCtl.ProtocolError("Bad info line %r",msg)
             if more:
                 d[k] = more
             else:
@@ -292,7 +283,7 @@
                 e = "ERR"
             evs.append(e)
 
-        self._sendAndRecv("SETEVENTS %s"\r\n," ".join(evs))
+        self._sendAndRecv("SETEVENTS %s\r\n" % " ".join(evs))
 
     def save_conf(self):
         """Flush all configuration changes to disk.
@@ -308,7 +299,7 @@
                 0x0A : "USR1",
                 0x0C : "USR2",
                 0x0F : "TERM" }.get(sig,sig)
-        seld._sendAndRecv("SIGNAL %s\r\n"%sig)
+        self._sendAndRecv("SIGNAL %s\r\n"%sig)
 
     def map_address(self, kvList):
         if not kvList:
@@ -320,7 +311,7 @@
             try:
                 key, val = line.split("=", 1)
             except ValueError:
-                raise ProtocolError("Bad address line %r",v)
+                raise TorCtl.ProtocolError("Bad address line %r",v)
             r.append((key,val))
         return r
 
@@ -335,7 +326,7 @@
         tp,msg,_ = lines[0]
         m = re.match(r'EXTENDED (\S*)', msg)
         if not m:
-            raise ProtocolError("Bad extended line %r",msg)
+            raise TorCtl.ProtocolError("Bad extended line %r",msg)
         return m.group(1)
 
     def redirect_stream(self, streamid, newtarget):
@@ -359,4 +350,3 @@
     def post_descriptor(self, desc):
         self._sendAndRecv("+POSTDESCRIPTOR\r\n%s"%_escape_dots(desc))
 
-    

Index: TorExample.py
===================================================================
RCS file: /home/or/cvsroot/control/python/TorExample.py,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- TorExample.py	15 Jun 2005 15:18:22 -0000	1.2
+++ TorExample.py	24 Jun 2005 18:03:27 -0000	1.3
@@ -8,18 +8,25 @@
 from TorCtl import *
 
 def getConnection(daemon=1):
-    if sys.argv[1] == '--host':
-        hostport = sys.argv[2]
-        del sys.argv[1:3]
-    elif sys.argv[1].startswith("--host="):
-        hostport = sys.argv[1][7:]
-        del sys.argv[1]
-    else:
-        hostport = "localhost:9100"
+    hostport = "localhost:9100"
+    verbose = 0
+    while sys.argv[1][0] == '-':
+        if sys.argv[1] == '--host':
+            hostport = sys.argv[2]
+            del sys.argv[1:3]
+        elif sys.argv[1].startswith("--host="):
+            hostport = sys.argv[1][7:]
+            del sys.argv[1]
+        elif sys.argv[1] in ('-v', '--verbose'):
+            verbose = 1
+            del sys.argv[1]
+
     host,port = parseHostAndPort(hostport)
     s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
     s.connect((host,port))
-    conn = Connection(s)
+    conn = get_connection(s)
+    if verbose and hasattr(conn, "debug"):
+        conn.debug(sys.stdout)
     th = conn.launchThread(daemon)
     conn.authenticate("")
     return conn
@@ -32,6 +39,7 @@
     fn = globals().get("run_"+cmd)
     if fn is None:
         print "Unrecognized command:",cmd
+        return
     fn()
 
 def run_set_config():
@@ -51,9 +59,9 @@
 def run_get_config():
     conn = getConnection()
     opts = conn.get_option(sys.argv[1:])
-    for k in sys.argv[1:]:
+    for k,v in opts:
         print "KEY:",k
-        print "VALUE:",opts.get(k)
+        print "VALUE:",v
 
 def run_get_info():
     conn = getConnection()
@@ -63,44 +71,17 @@
         print "VALUE:",opts.get(k)
 
 def run_listen():
-    m = { "circ": "CIRCSTATUS",
-          "stream": "STREAMSTATUS",
-          "orconn": "ORCONNSTATUS",
-          "bw": "BANDWIDTH",
-          "newdesc": "NEWDESC",
-          "info": "INFO_MSG",
-          "notice": "NOTICE_MSG",
-          "warn": "WARN_MSG",
-          "error": "ERR_MSG",
-          }
     conn = getConnection(daemon=0)
     events = []
-    for kw in sys.argv[1:]:
-        try:
-            events.append(EVENT_TYPE.get(m[kw]))
-        except KeyError:
-            print "Unrecognized event %r; recognized events are: %s"%(
-                kw, ", ".join(m.keys()))
-    if not events:
-        return
-
     conn.setEventHandler(DebugEventHandler())
-    conn.listenForEvents(events)
+    conn.set_events(sys.argv[1:])
 
 def run_signal():
     conn = getConnection()
-    m = { 'reload': "HUP", 'shutdown': "INT", 'dump': "USR1",
-          'debug': "USR2", 'halt': 'TERM' }
     if len(sys.argv)<2:
         print "Syntax: signal [signal]"
         return
-    try:
-        sig = SIGNAL.get(m[sys.argv[1]])
-    except KeyError:
-        print "Unrecognized signal %r. Options are %s"%(
-            sys.argv[1], ", ".join(m.keys()))
-
-    conn.signal(sig)
+    conn.send_signal(sys.argv[1])
 
 def run_authdemo():
     conn = getConnection()