import sys import base64 import json from twisted.protocols.basic import LineReceiver from twisted.internet import defer from util import PappyException """ comm.py Handles creating a listening server bound to localhost that other processes can use to interact with the proxy. """ debug = False class CommServer(LineReceiver): MAX_LENGTH=sys.maxint def __init__(self): self.delimiter = '\n' self.action_handlers = { 'ping': self.action_ping, 'get_request': self.action_get_request, 'get_response': self.action_get_response, 'submit': self.action_submit_request, } def lineReceived(self, line): line = line.strip() if line == '': return #try: command_data = json.loads(line) command = command_data['action'] valid = False if command in self.action_handlers: valid = True result = {'success': True} func_defer = self.action_handlers[command](command_data) func_defer.addCallback(self.action_result_handler, result) func_defer.addErrback(self.action_error_handler, result) if not valid: raise PappyException('%s is an invalid command' % command_data['action']) # except PappyException as e: # return_data = {'success': False, 'message': str(e)} # self.sendLine(json.dumps(return_data)) def action_result_handler(self, data, result): result.update(data) self.sendLine(json.dumps(result)) def action_error_handler(self, error, result): if debug: print error.getTraceback() return_data = {'success': False, 'message': str(error.getErrorMessage())} result.update(result) error.trap(Exception) self.sendLine(json.dumps(return_data)) return True def action_ping(self, data): return defer.succeed({'ping': 'pong'}) @defer.inlineCallbacks def action_get_request(self, data): from .http import Request try: reqid = data['reqid'] req = yield Request.load_request(reqid) except KeyError: raise PappyException("Request with given ID does not exist") dat = json.loads(req.to_json()) defer.returnValue(dat) @defer.inlineCallbacks def action_get_response(self, data): from .http import Request, Response try: reqid = data['reqid'] req = yield Request.load_request(reqid) except KeyError: raise PappyException("Request with given ID does not exist, cannot fetch associated response.") if req.response: rsp = yield Response.load_response(req.response.rspid) dat = json.loads(rsp.to_json()) else: dat = {} defer.returnValue(dat) @defer.inlineCallbacks def action_submit_request(self, data): from .http import Request from .plugin import active_intercepting_macros message = base64.b64decode(data['full_message']) req = Request(message) req.host = data['host'].encode('utf-8') req.port = data['port'] req.is_ssl = data['is_ssl'] yield Request.submit_request(req, save_request=True, intercepting_macros=active_intercepting_macros()) if 'tags' in data: req.tags = set(data['tags']) yield req.async_deep_save() retdata = {} retdata['request'] = json.loads(req.to_json()) if req.response: retdata['response'] = json.loads(req.response.to_json()) defer.returnValue(retdata)