#!/usr/bin/python3
+import sys
+import os
+
import twisted
+import twisted.internet
+import twisted.internet.endpoints
+from twisted.internet import reactor
+from twisted.web.server import NOT_DONE_YET
+from twisted.logger import LogLevel
+
+import ipaddress
+from ipaddress import AddressValueError
#import twisted.web.server import Site
#from twisted.web.resource import Resource
-from twisted.web.server import NOT_DONE_YET
-from twisted.internet import reactor
from optparse import OptionParser
from configparser import ConfigParser
from configparser import NoOptionError
-import ipaddress
import collections
clients = { }
-def ipaddress(input):
+def ipaddr(input):
try:
r = ipaddress.IPv4Address(input)
except AddressValueError:
# [relay]
[server]
-ipif = userv root ipif %(host),%(relay),%(mtu),slip %(network)
+ipif = userv root ipif %(host)s,%(relay)s,%(mtu)s,slip %(network)s
addrs = 127.0.0.1 ::1
port = 80
#---------- "router" ----------
-def route(packet. daddr):
+def route(packet, daddr):
try: client = clients[daddr]
except KeyError: dclient = None
if dclient is not None:
dclient.queue_outbound(packet)
- else if daddr = host or daddr not in network:
+ elif daddr == host or daddr not in network:
queue_inbound(packet)
- else if daddr = relay:
+ elif daddr == relay:
log_discard(packet, saddr, daddr, 'relay')
else:
log_discard(packet, saddr, daddr, 'no client')
global ipif
ipif = IpifProcessProtocol()
reactor.spawnProcess(ipif,
- '/bin/sh',['-c', ipif_command],
+ '/bin/sh',['sh','-c', ipif_command],
childFDs={0:'w', 1:'r', 2:2})
def queue_inbound(packet):
# now request is an unfinished request, or None
try: (queuetime, packet) = self._pq[0]
- except: IndexError:
+ except IndexError:
# no packets, oh well
break
class IphttpResource(twisted.web.resource.Resource):
def render_POST(self, request):
# find client, update config, etc.
- ci = ipaddress(request.args['i'])
+ ci = ipaddr(request.args['i'])
c = clients[ci]
pw = request.args['pw']
if pw != c.pw: raise ValueError('bad password')
def start_http():
resource = IphttpResource()
sitefactory = twisted.web.server.Site(resource)
- for addrspec in cfg.get('server','addresses').split():
+ for addrspec in cfg.get('server','addrs').split():
try:
addr = ipaddress.IPv4Address(addrspec)
endpointfactory = twisted.internet.endpoints.TCP4ServerEndpoint
try:
host = cfg.get('virtual','host')
except NoOptionError:
- host = network.hosts().next()
+ host = next(network.hosts())
try:
relay = cfg.get('virtual','relay')
- except OptionError:
+ except NoOptionError:
for search in network.hosts():
- if search = host: continue
+ if search == host: continue
relay = search
break
for cs in cfg.sections():
if not (':' in cs or '.' in cs): continue
- ci = ipaddress(cs)
+ ci = ipaddr(cs)
if ci not in network:
raise ValueError('client %s not in network' % ci)
if ci in clients:
raise ValueError('multiple client cfg sections for %s' % ci)
clients[ci] = Client(ci, cs)
+ global mtu
+ mtu = cfg.get('virtual','mtu')
+
iic_vars = { }
for k in ('host','relay','mtu','network'):
iic_vars[k] = globals()[k]
ipif_command = cfg.get('server','ipif', vars=iic_vars)
+def crash_on_critical(event):
+ if event.get('log_level') >= LogLevel.critical:
+ print('crashing: ', twisted.logger.formatEvent(event), file=sys.stderr)
+ #print('crashing!', file=sys.stderr)
+ #os._exit(1)
+ try: reactor.stop()
+ except twisted.internet.error.ReactorNotRunning: pass
+
def startup():
+ global cfg
+
op = OptionParser()
op.add_option('-c', '--config', dest='configfile',
default='/etc/hippottd/server.conf')
(opts, args) = op.parse_args()
if len(args): op.error('no non-option arguments please')
+ twisted.logger.globalLogPublisher.addObserver(crash_on_critical)
+
cfg = ConfigParser()
cfg.read_string(defcfg)
- cfg.read_file(opts['configfile'])
+ cfg.read(opts.configfile)
process_cfg()
start_ipif()
start_http()
+
+startup()
+reactor.run()