summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNick Mathewson <nickm@torproject.org>2005-03-31 05:11:32 +0000
committerNick Mathewson <nickm@torproject.org>2005-03-31 05:11:32 +0000
commitc7ef516c43928853795f3dab6858ad065220618b (patch)
treec83707a6c01ee898be4a48bfd7d357c9477a7911
parenta25033c7d87ce6a70c223bf9a6241986013a8208 (diff)
downloadtor-c7ef516c43928853795f3dab6858ad065220618b.tar.gz
tor-c7ef516c43928853795f3dab6858ad065220618b.zip
Add more functionality; fix syntax.
svn:r3922
-rwxr-xr-xcontrib/TorControl.py105
1 files changed, 94 insertions, 11 deletions
diff --git a/contrib/TorControl.py b/contrib/TorControl.py
index 155603644d..60ef345827 100755
--- a/contrib/TorControl.py
+++ b/contrib/TorControl.py
@@ -13,7 +13,9 @@ class _Enum:
setattr(self,name,idx)
self.nameOf[idx] = name
idx += 1
-
+class _Enum2:
+ def __init__(self, **args):
+ self.__dict__.update(args)
MSG_TYPE = _Enum(0x0000,
["ERROR",
@@ -39,10 +41,10 @@ MSG_TYPE = _Enum(0x0000,
"CLOSECIRCUIT",
])
-assert MSG_TYPE.SAVECONF = 0x0008
-assert MSG_TYPE.CLOSECIRCUIT = 0x0014
+assert MSG_TYPE.SAVECONF == 0x0008
+assert MSG_TYPE.CLOSECIRCUIT == 0x0014
-EVENT_TYPE = _ENUM(0x0001,
+EVENT_TYPE = _Enum(0x0001,
["CIRCSTATUS",
"STREAMSTATUS",
"ORCONNSTATUS",
@@ -50,6 +52,25 @@ EVENT_TYPE = _ENUM(0x0001,
"WARN",
"NEWDESC"])
+CIRC_STATUS = _Enum(0x00,
+ ["LAUNCHED",
+ "BUILT",
+ "EXTENDED",
+ "FAILED",
+ "CLOSED"])
+STREAM_STATUS = _Enum(0x00,
+ ["SENT_CONNECT",
+ "SENT_RESOLVE",
+ "SUCCEEDED",
+ "FAILED",
+ "CLOSED",
+ "NEW_CONNECT",
+ "NEW_RESOLVE",
+ "DETACHED"])
+OR_CONN_STATUS = _Enum(0x00,
+ ["LAUNCHED","CONNECTED","FAILED","CLOSED"])
+SIGNAL = _Enum2(HUP=0x01,INT=0x02,USR1=0x0A,USR2=0x0C,TERM=0x0F)
+
ERR_CODES = {
0x0000 : "Unspecified error",
0x0001 : "Internal error",
@@ -104,6 +125,13 @@ def _unpack_msg(msg):
else:
return None,4+length,msg
+def _minLengthToPack(bytes):
+ whole,left = divmod(bytes,65535)
+ if left:
+ return whole*(65535+4)+4+left
+ else:
+ return whole*(65535+4)
+
def unpack_msg(msg):
"returns as for _unpack_msg"
tp,body,rest = _unpack_msg(msg)
@@ -116,28 +144,34 @@ def unpack_msg(msg):
realType,realLength = struct.unpack("!HL", body[:6])
# Okay; could the message _possibly_ be here?
- minPackets,minSlop = divmod(realLength+6,65535)
- minLength = (minPackets*(65535+4))+4+minSlop
+ minLength = _minLengthToPack(realLength+6)
if len(msg) < minLength:
return None, minLength, msg
# Okay; optimistically try to build up the msg.
soFar = [ body[6:] ]
lenSoFarLen = len(body)-6
- while rest and lenSoFar < realLength:
- ln, tp = struct.unpack("!HH" rest[:4])
+ while len(rest)>=4 and lenSoFar < realLength:
+ ln, tp = struct.unpack("!HH", rest[:4])
if tp != MSG_TYPE.FRAGMENT:
raise ProtocolError("Missing FRAGMENT message")
soFar.append(rest[4:4+ln])
lenSoFar += ln
- rest = rest[4+ln:]
+ if 4+ln > len(rest):
+ rest = ""
+ leftInPacket = 4+ln-len(rest)
+ else:
+ rest = rest[4+ln:]
+ leftInPacket=0
if lenSoFar == realLength:
return realType, "".join(soFar), rest
elif lenSoFar > realLength:
raise ProtocolError("Bad fragmentation: message longer than declared")
else:
- return None, len(msg)+(realLength-lenSoFar), msg
+ inOtherPackets = realLength-lenSoFar-leftInPacket
+ minLength = _minLengthToPack(inOtherPackets)
+ return None, len(msg)+leftInPacket+inOtherPackets, msg
def receive_message(s):
length, tp, body = _receive_msg(s)
@@ -259,7 +293,56 @@ def extend_circuit(s, circid, hops):
msg = struct.pack("!L",circid) + ",".join(hops) + "\0"
send_message(s,MSG_TYPE.EXTENDCIRCUIT,msg)
tp, body = receive_reply(s,[MSG_TYPE.DONE])
- return body
+ if len(body) != 4:
+ raise ProtocolError("Extendcircuit reply too short or long")
+ return struct.unpack("!L",body)
+
+def redirect_stream(s, streamid, newtarget):
+ msg = struct.pack("!L",streamid) + newtarget + "\0"
+ tp,body = receive_reply(s,[MSG_TYPE.DONE])
+
+def _unterminate(s):
+ if s[-1] == '\0':
+ return s[:-1]
+ else:
+ return s
+
+def unpack_event(body):
+ if len(body)<2:
+ raise ProtocolError("EVENT body too short.")
+ evtype = struct.unpack("!H", body[:2])
+ body = body[2:]
+ if evtype == EVENT_TYPE.CIRCUITSTATUS:
+ if len(body)<5:
+ raise ProtocolError("CIRCUITSTATUS event too short.")
+ status,ident = struct.unpack("!BL", body[:5])
+ path = _unterminate(body[5:]).split(",")
+ args = status, ident, path
+ elif evtype == EVENT_TYPE.STREAMSTATUS:
+ if len(body)<5:
+ raise ProtocolError("CIRCUITSTATUS event too short.")
+ status,ident = struct.unpack("!BL", body[:5])
+ target = _unterminate(body[5:])
+ args = status, ident, target
+ elif evtype == EVENT_TYPE.ORCONNSTATUS:
+ if len(body)<2:
+ raise ProtocolError("CIRCUITSTATUS event too short.")
+ status = ord(body[0])
+ target = _unterminate(body[1:])
+ args = status, target
+ elif evtype == EVENT_TYPE.BANDWIDTH:
+ if len(body)<8:
+ raise ProtocolError("BANDWIDTH event too short.")
+ read, written = struct.unpack("!LL",body[:8])
+ args = read, written
+ elif evtype == EVENT_TYPE.WARN:
+ args = (_unterminate(body),)
+ elif evtype == EVENT_TYPE.NEWDESC:
+ args = (_unterminate(body).split(","),)
+ else:
+ args = (body,)
+
+ return evtype, args
def listen_for_events(s):
while(1):