#!/usr/bin/python3
-
+#
+# Hippotat - Asinine IP Over HTTP program
+# ./hippotat - client main program
+#
+# Copyright 2017 Ian Jackson
+#
+# GPLv3+
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program, in the file GPLv3. If not,
+# see <http://www.gnu.org/licenses/>.
+
+#@ import sys; sys.path.append('@PYBUILD_INSTALL_DIR@')
from hippotatlib import *
import twisted.web
import io
class GeneralResponseConsumer(twisted.internet.protocol.Protocol):
- def __init__(self, cl, req, desc):
+ def __init__(self, cl, req, resp, desc):
self._cl = cl
self._req = req
self._desc = desc
self._log(DBG.HTTP_CTRL, 'connectionMade')
class ResponseConsumer(GeneralResponseConsumer):
- def __init__(self, cl, req):
- super().__init__(cl, req, 'RC')
+ def __init__(self, cl, req, resp):
+ super().__init__(cl, req, resp, 'RC')
ssddesc = '[%s] %s' % (id(req), self._desc)
self._ssd = SlipStreamDecoder(ssddesc, partial(queue_inbound, cl.ipif))
self._log(DBG.HTTP_CTRL, '__init__')
self._handleexception()
def connectionLost(self, reason):
- self._log(DBG.HTTP_CTRL, 'connectionLost ' + str(reason))
+ reason_msg = 'connectionLost ' + str(reason)
+ self._log(DBG.HTTP_CTRL, reason_msg)
if not reason.check(twisted.web.client.ResponseDone):
- self.latefailure()
+ self._latefailure(reason_msg)
return
try:
self._log(DBG.HTTP, 'ResponseDone')
class ErrorResponseConsumer(GeneralResponseConsumer):
def __init__(self, cl, req, resp):
- super().__init__(cl, req, 'ERROR-RC')
+ super().__init__(cl, req, resp, 'ERROR-RC')
self._resp = resp
self._m = b''
try:
'req_ok %d %s %s' % (resp.code, repr(resp.phrase), str(resp)),
idof=req)
if resp.code == 200:
- rc = ResponseConsumer(cl, req)
+ rc = ResponseConsumer(cl, req, resp)
else:
rc = ErrorResponseConsumer(cl, req, resp)
# later, by ResponsConsumer or ErrorResponsConsumer
try:
cl.log(DBG.HTTP_CTRL, 'req_err ' + str(err), idof=req)
+ cl.running_reported = False
if isinstance(err, twisted.python.failure.Failure):
err = err.getTraceback()
- print('[%#x] %s' % (id(req), err), file=sys.stderr)
+ print('%s[%#x] %s' % (cl.desc, id(req), err.strip('\n').replace('\n',' / ')),
+ file=sys.stderr)
if not isinstance(cl.outstanding[req], int):
raise RuntimeError('[%#x] previously %s' %
(id(req), cl.outstanding[req]))
d = mime_translate(d)
+ token = authtoken_make(cl.c.secret)
+
crlf = b'\r\n'
lf = b'\n'
mime = (b'--b' + crlf +
b'Content-Type: text/plain; charset="utf-8"' + crlf +
b'Content-Disposition: form-data; name="m"' + crlf + crlf +
str(cl.c.client) .encode('ascii') + crlf +
- cl.c.password + crlf +
+ token + crlf +
str(cl.c.target_requests_outstanding)
.encode('ascii') + crlf +
str(cl.c.http_timeout) .encode('ascii') + crlf +
clients = [ ]
-def process_cfg(putative_servers, putative_clients):
+def process_cfg(_opts, putative_servers, putative_clients):
global clients
for ss in putative_servers.values():
sections = cfg_process_client_common(c,ss,cs,ci)
if not sections: continue
+ log_debug_config('processing client [%s %s]' % (ss, cs))
+
def srch(getter,key): return cfg_search(getter,key,sections)
c.http_timeout += srch(cfg.getint, 'http_timeout_grace')
c.max_queue_time = srch(cfg.getint, 'max_queue_time')
c.vroutes = srch(cfg.get, 'vroutes')
+ try: c.ifname = srch(cfg_get_raw, 'ifname_client')
+ except NoOptionError: pass
+
try: c.url = srch(cfg.get,'url')
except NoOptionError:
cfg_process_saddrs(c, ss)