#!/usr/bin/python
# rawz - raw zephyr using only batteries (sockets, mostly)
import socket
import struct
import re
import time
def zbytes(bytes):
return ("0x" + "%02X" * len(bytes)) % struct.unpack("B" * len(bytes), bytes)
def zascii(data):
return " ".join([zbytes(s) for s in re.findall("..?.?.?", data)])
def zlong(val):
return zascii(struct.pack(">L", val))
def zshort(val):
return zascii(struct.pack(">H", val))
def getservbyname(serv, proto, fallback):
try:
return socket.getservbyname(serv, proto)
except socket.error:
return fallback
class zsetup:
def __init__(self):
# we can't actually bounce through a remote zhm anymore
# but if we don't have a local one, we can just *be* one
self.localaddr = socket.gethostbyname(socket.gethostname())
if os.getenv("ZSERVER"):
self.zsendto_addr = os.getenv("ZSERVER")
self.zsendto_addr = socket.gethostbyname(self.zsendto_addr)
self.zsendto_port = getservbyname("zephyr-clt", "udp", 2103)
self.bindto = (self.localaddr, getservbyname("zephyr-hm", "udp", 2104))
else:
# ok, use the local zhm
self.zsendto_addr = "127.0.0.1"
self.zsendto_port = getservbyname("zephyr-hm", "udp", 2104)
self.bindto = ("127.0.0.1", 0)
# uid setup stuff
self.uidinc = 0
self.oldtime = None
def zpacket(self, uid, zclass, inst, opcode, sender, recip, default, msg):
if not uid:
newtime = long(time.time())
if self.oldtime != newtime:
self.uidinc = 0
self.uidinc += 1
uid = struct.pack(">4s L L", socket.inet_aton(self.localaddr), newtime, self.uidinc)
self.oldtime = newtime
zfields = ["ZEPH0.2",
zlong(17),
zlong(0), # UNSAFE
zascii(uid),
zshort(0), # no response port
zlong(0), # no auth
zlong(0), # authlen = 0
"", # no authdata
zclass,
inst,
opcode,
sender,
recip,
default,
zlong(0), # no checksum
"", # no fragmentation
zascii(uid),
msg]
return "\0".join(zfields)
def zinit(self, retsock=[]):
if retsock:
return retsock[0]
zsock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
zsock.bind(self.bindto)
retsock.append(zsock)
return zsock
def zsend(self, packet):
print "sending to", (self.zsendto_addr, self.zsendto_port)
return self.zinit().sendto(packet, (self.zsendto_addr, self.zsendto_port))
def addrealm(s):
return s + "@ATHENA.MIT.EDU"
import sys,os
if __name__ == "__main__":
prog, who, what = sys.argv
z = zsetup()
zpack = z.zpacket(None, "MESSAGE", "PERSONAL", "", addrealm(who) , addrealm(who) , "strings!", what)
print zpack.split("\0")
z.zsend(zpack)