From 36f1db884d653f077bdafab908cbbf65833e8772 Mon Sep 17 00:00:00 2001 From: itraviv Date: Thu, 4 Aug 2016 16:07:04 +0300 Subject: 1) changed class name to 'scapy_service' 2) changed returned values to be dictionaries instead of arrays --- .../stl/services/scapy_server/scapy_server.py | 49 ++++++--- .../services/scapy_server/zmq_for_scapy_server.py | 118 +++++++++++++++++++++ .../scapy_server/zmq_for_scapy_server_test.py | 14 +++ 3 files changed, 166 insertions(+), 15 deletions(-) create mode 100755 scripts/automation/trex_control_plane/stl/services/scapy_server/zmq_for_scapy_server.py create mode 100755 scripts/automation/trex_control_plane/stl/services/scapy_server/zmq_for_scapy_server_test.py (limited to 'scripts/automation/trex_control_plane/stl/services/scapy_server') diff --git a/scripts/automation/trex_control_plane/stl/services/scapy_server/scapy_server.py b/scripts/automation/trex_control_plane/stl/services/scapy_server/scapy_server.py index 2460b584..ca09333c 100755 --- a/scripts/automation/trex_control_plane/stl/services/scapy_server/scapy_server.py +++ b/scripts/automation/trex_control_plane/stl/services/scapy_server/scapy_server.py @@ -1,6 +1,8 @@ import os -stl_pathname = os.path.abspath(os.path.join(os.pardir, os.pardir, 'trex_control_plane','stl','trex_stl_lib')) +import sys +stl_pathname = os.path.abspath(os.path.join(os.pardir, os.pardir)) +sys.path.append(stl_pathname) import trex_stl_lib from trex_stl_lib.api import * from copy import deepcopy @@ -31,7 +33,9 @@ f.write(a) f.close() """ -class scapy_server: +class ScapyException(Exception): pass + +class scapy_service: #---------------------------------------------------------------------------------------------------- class scapyRegex: @@ -183,7 +187,7 @@ class scapy_server: fieldDict[f] = self.scapyRegex(f).stringRegex() return fieldDict - def show2toDict(self,pkt): + def show2_to_dict(self,pkt): old_stdout = sys.stdout sys.stdout = mystdout = StringIO() pkt.show2() @@ -195,8 +199,14 @@ class scapy_server: protocol_fields = listedShow2Data[i+1] protocol_fields = protocol_fields.split('\n')[1:-1] protocol_fields = [f.strip() for f in protocol_fields] + protocol_fields_dict = {} + for f in protocol_fields: + field_data = f.split('=') + if len(field_data)!= 1 : + field_name = field_data[0].strip() + protocol_fields_dict[field_name] = field_data[1].strip() layer_name = re.sub(r'\W+', '',listedShow2Data[i]) #clear layer name to include only alpha-numeric - show2Dict[layer_name] = protocol_fields + show2Dict[layer_name] = protocol_fields_dict return show2Dict #pkt_desc as string @@ -207,12 +217,12 @@ class scapy_server: total_protocols = len(pkt_protocols) res = {} for i in range(total_protocols): - fields = [] + fields = {} for field in scapy_pkt.fields_desc: size = field.get_size_bytes() if field.name is 'load': size = len(scapy_pkt) - fields.append([field.name, field.offset, size]) + fields[field.name]=[field.offset, size] layer_name = pkt_protocols[i].partition('(')[0] #clear layer name to include only alpha-numeric layer_name = re.sub(r'\W+', '',layer_name) res[layer_name] = fields @@ -224,17 +234,20 @@ class scapy_server: def build_pkt(self,pkt_descriptor): pkt = eval(pkt_descriptor) - show2data = self.show2toDict(pkt) + show2data = self.show2_to_dict(pkt) bufferData = str(pkt) #pkt buffer bufferData = binascii.b2a_base64(bufferData) pkt_offsets = self.get_all_pkt_offsets(pkt_descriptor) - res = [show2data,bufferData,pkt_offsets] + res = {} + res['show2'] = show2data + res['buffer'] = bufferData + res['offsets'] = pkt_offsets return res #input: container #output: md5 encoded in base64 - def getMD5(self,container): + def get_md5(self,container): container = json.dumps(container) m = hashlib.md5() m.update(container.encode('ascii')) @@ -245,8 +258,8 @@ class scapy_server: def get_all(self): fields=self.get_all_fields() db=self.get_all_db() - fields_md5 = self.getMD5(fields) - db_md5 = self.getMD5(db) + fields_md5 = self.get_md5(fields) + db_md5 = self.get_md5(db) res = {} res['db'] = db res['fields'] = fields @@ -258,18 +271,24 @@ class scapy_server: def check_update(self,db_md5,field_md5): fields=self.get_all_fields() db=self.get_all_db() - current_db_md5 = self.getMD5(db) - current_field_md5 = self.getMD5(fields) + current_db_md5 = self.get_md5(db) + current_field_md5 = self.get_md5(fields) res = [] if field_md5 == current_field_md5: if db_md5 == current_db_md5: return True else: - raise Exception("Protocol DB is not up to date") + raise ScapyException("Protocol DB is not up to date") else: - raise Exception("Fields DB is not up to date") + raise ScapyException("Fields DB is not up to date") def get_version(self): return {'built_by':'itraviv','version':'v1.0'} + def supported_methods(self,method_name): + if method_name in dir(scapy_service): + return True + return False + + diff --git a/scripts/automation/trex_control_plane/stl/services/scapy_server/zmq_for_scapy_server.py b/scripts/automation/trex_control_plane/stl/services/scapy_server/zmq_for_scapy_server.py new file mode 100755 index 00000000..82118bb9 --- /dev/null +++ b/scripts/automation/trex_control_plane/stl/services/scapy_server/zmq_for_scapy_server.py @@ -0,0 +1,118 @@ +# +# Hello World server in Python +# Binds REP socket to tcp://*:5555 +# Expects b"Hello" from client, replies with b"World" +# + +import time +import sys +sys.path.append(sys.path.append('/auto/srg-sce-swinfra-usr/emb/users/itraviv/trex/trex-core/scripts/external_libs/pyzmq-14.5.0/python2/fedora18/64bit')) +sys.path.append(sys.path.append('/auto/srg-sce-swinfra-usr/emb/users/itraviv/trex/trex-core/scripts/automation/trex_control_plane/stl/')) +import zmq +import inspect +from scapy_server import * + +server_file_name = 'zmq_server_hello_world_server' + +context = zmq.Context() +socket = context.socket(zmq.REP) +socket.bind("tcp://*:5555") + + +class ParseException(Exception): pass +class InvalidRequest(Exception): pass +class MethodNotFound(Exception): pass +class InvalidParams(Exception): pass +#def error_response() + +class Scapy_wrapper: + def __init__(self): + self.scapy_master = scapy_service() + + def parse_req_msg(self,JSON_req): + try: + req = json.loads(JSON_req) + req_id='null' + if (type(req)!= type({})): + raise ParseException(req_id) + json_rpc_keys = ['jsonrpc','id','method'] + if ((set(req.keys())!=set(json_rpc_keys)) and (set(req.keys())!=set(json_rpc_keys+['params']))) : + if 'id' in req.keys(): + req_id = req['id'] + raise InvalidRequest(req_id) + req_id = req['id'] + if not (self.scapy_master.supported_methods(req['method'])): + raise MethodNotFound(req_id) + scapy_method = eval("self.scapy_master."+req['method']) + arg_num_for_method = len(inspect.getargspec(scapy_method)[0]) + if (arg_num_for_method>1) : + if not ('params' in req.keys()): + raise InvalidRequest(req_id) + params_len = len(req['params'])+1 # +1 because "self" is considered parameter in args for method + if not (params_len==arg_num_for_method): + raise InvalidParams(req_id) + return req['method'],req['params'],req_id + else: + return req['method'],[],req_id + except ValueError: + raise ParseException(req_id) + + def create_error_response(self,error_code,error_msg,req_id='null'): + return {"jsonrpc": "2.0", "error": {"code": error_code, "message:": error_msg}, "id": req_id} + + def create_success_response(self,result,req_id='null'): + return {"jsonrpc": "2.0", "result": result, "id": req_id } + + def getException(self): + return sys.exc_info() + + def metaraise(self,exc_info): + raise exc_info[0], exc_info[1], exc_info[2] + + + def error_handler(self,exception_obj): + try: + self.metaraise(exception_obj) + except ParseException as e: + response = self.create_error_response(-32700,'Parse error',e.message) + except InvalidRequest as e: + response = self.create_error_response(-32600,'Invalid Request',e.message) + except MethodNotFound as e: + response = self.create_error_response(-32601,'Method not found',e.message) + except InvalidParams as e: + response = self.create_error_response(-32603,'Invalid params',e.message) + except SyntaxError as e: + response = self.create_error_response(-32097,'SyntaxError') + except Exception as e: + response = self.create_error_response(-32098,'Scapy Server: '+str(e.message),req_id) + finally: + return response + + +scapy_wrapper = Scapy_wrapper() +try: + while True: + # Wait for next request from client + message = socket.recv() +# print("Received request: %s" % message) +# print ("message type is: %s" % type(message)) +# print("message is now: %s" % message) + try: + method,params,req_id = scapy_wrapper.parse_req_msg(message) + if len(params)>0: + result = eval('scapy_wrapper.scapy_master.'+method+'(*'+str(params)+')') + else: + result = eval('scapy_wrapper.scapy_master.'+method+'()') + response = scapy_wrapper.create_success_response(result,req_id) + except: + print 'got exception' + e = scapy_wrapper.getException() + response = scapy_wrapper.error_handler(e) + finally: + json_response = json.dumps(response) + time.sleep(1) + + # Send reply back to client + socket.send(json_response) +except KeyboardInterrupt: + print('Ctrl+C pressed') diff --git a/scripts/automation/trex_control_plane/stl/services/scapy_server/zmq_for_scapy_server_test.py b/scripts/automation/trex_control_plane/stl/services/scapy_server/zmq_for_scapy_server_test.py new file mode 100755 index 00000000..8f7f7b01 --- /dev/null +++ b/scripts/automation/trex_control_plane/stl/services/scapy_server/zmq_for_scapy_server_test.py @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + -- cgit 1.2.3-korg