Cleaned up for checking in to NRL repo

This commit is contained in:
Rod A Santiago 2016-09-14 17:15:16 -07:00
parent ae4a4b903e
commit b239b906bd
3 changed files with 162 additions and 25 deletions

View file

@ -11,7 +11,7 @@
import SocketServer, sys, threading, time, traceback import SocketServer, sys, threading, time, traceback
import os, gc import os, gc, shlex, shutil
from core import pycore from core import pycore
from core.api import coreapi from core.api import coreapi
from core.misc.utils import hexdump, cmdresult, mutedetach, closeonexec from core.misc.utils import hexdump, cmdresult, mutedetach, closeonexec
@ -19,12 +19,13 @@ from core.misc.xmlsession import opensessionxml, savesessionxml
''' '''
Defines server classes and request handlers for TCP and UDP. Also defined here is a TCP based Defines server classes and request handlers for TCP and UDP. Also defined here is a TCP based auxiliary server class for supporting externally defined handlers.
''' '''
class CoreServer(SocketServer.ThreadingMixIn, SocketServer.TCPServer): class CoreServer(SocketServer.ThreadingMixIn, SocketServer.TCPServer):
''' The main server - a TCP server class, manages sessions and spawns request handlers for ''' TCP server class, manages sessions and spawns request handlers for
incoming connections. incoming connections.
''' '''
daemon_threads = True daemon_threads = True
@ -218,14 +219,11 @@ class CoreServer(SocketServer.ThreadingMixIn, SocketServer.TCPServer):
break break
finally: finally:
self._sessionslock.release() self._sessionslock.release()
return found return found
class CoreUdpServer(SocketServer.ThreadingMixIn, SocketServer.UDPServer): class CoreUdpServer(SocketServer.ThreadingMixIn, SocketServer.UDPServer):
''' A UDP server class, manages sessions and spawns request handlers for ''' UDP server class, manages sessions and spawns request handlers for
incoming connections. incoming connections.
''' '''
daemon_threads = True daemon_threads = True
@ -235,7 +233,7 @@ class CoreUdpServer(SocketServer.ThreadingMixIn, SocketServer.UDPServer):
''' Server class initialization takes configuration data and calls ''' Server class initialization takes configuration data and calls
the SocketServer constructor the SocketServer constructor
''' '''
self.mainserver = mainserver # tcpserver is the main server self.mainserver = mainserver
SocketServer.UDPServer.__init__(self, server_address, SocketServer.UDPServer.__init__(self, server_address,
RequestHandlerClass) RequestHandlerClass)
@ -246,6 +244,7 @@ class CoreUdpServer(SocketServer.ThreadingMixIn, SocketServer.UDPServer):
class CoreAuxServer(SocketServer.ThreadingMixIn, SocketServer.TCPServer): class CoreAuxServer(SocketServer.ThreadingMixIn, SocketServer.TCPServer):
''' An auxiliary TCP server. ''' An auxiliary TCP server.
''' '''
@ -275,7 +274,6 @@ class CoreAuxServer(SocketServer.ThreadingMixIn, SocketServer.TCPServer):
class CoreRequestHandler(SocketServer.BaseRequestHandler): class CoreRequestHandler(SocketServer.BaseRequestHandler):
''' The SocketServer class uses the RequestHandler class for servicing ''' The SocketServer class uses the RequestHandler class for servicing
requests, mainly through the handle() method. The CoreRequestHandler requests, mainly through the handle() method. The CoreRequestHandler
@ -494,17 +492,17 @@ class CoreRequestHandler(SocketServer.BaseRequestHandler):
try: try:
replies = msghandler(msg) replies = msghandler(msg)
self.dispatchreplies(replies) self.dispatchreplies(replies,msg)
except Exception, e: except Exception, e:
self.warn("%s: exception while handling msg:\n%s\n%s" % self.warn("%s: exception while handling msg:\n%s\n%s" %
(threading.currentThread().getName(), msg, (threading.currentThread().getName(), msg,
traceback.format_exc())) traceback.format_exc()))
# Added to allow the auxiliary handlers to define a different behavior when replying
# Added to allow the API2 handler to define a different behavior when replying
# to messages from clients # to messages from clients
def dispatchreplies(self, replies): def dispatchreplies(self, replies, msg):
''' Dispatch replies to a handled message. '''
Dispatch replies by CORE to message msg previously received from the client.
''' '''
for reply in replies: for reply in replies:
if self.debug: if self.debug:
@ -525,6 +523,7 @@ class CoreRequestHandler(SocketServer.BaseRequestHandler):
except Exception, e: except Exception, e:
self.warn("Error sending reply data: %s" % e) self.warn("Error sending reply data: %s" % e)
def handle(self): def handle(self):
''' Handle a new connection request from a client. Dispatch to the ''' Handle a new connection request from a client. Dispatch to the
recvmsg() method for receiving data into CORE API messages, and recvmsg() method for receiving data into CORE API messages, and
@ -1139,10 +1138,10 @@ class CoreRequestHandler(SocketServer.BaseRequestHandler):
if ex: if ex:
try: try:
self.info("executing '%s'" % ex) self.info("executing '%s'" % ex)
if isinstance(self.server, CoreUdpServer): if not isinstance(self.server, CoreServer): # CoreUdpServer):
server = self.server.mainserver
elif isinstance(self.server, CoreApi2Server):
server = self.server.mainserver server = self.server.mainserver
# elif isinstance(self.server, CoreAuxServer):
# server = self.server.mainserver
else: else:
server = self.server server = self.server
if msg.flags & coreapi.CORE_API_STR_FLAG: if msg.flags & coreapi.CORE_API_STR_FLAG:
@ -1575,3 +1574,140 @@ class CoreDatagramRequestHandler(CoreRequestHandler):
''' Use sendto() on the connectionless UDP socket. ''' Use sendto() on the connectionless UDP socket.
''' '''
self.request[1].sendto(data, self.client_address) self.request[1].sendto(data, self.client_address)
class BaseAuxRequestHandler(CoreRequestHandler):
'''
This is the superclass for auxiliary handlers in CORE. A concrete auxiliary handler class
must, at a minimum, define the recvmsg(), sendall(), and dispatchreplies() methods.
See SockerServer.BaseRequestHandler for parameter details.
'''
def __init__(self, request, client_address, server):
self.msghandler = {
coreapi.CORE_API_NODE_MSG: self.handlenodemsg,
coreapi.CORE_API_LINK_MSG: self.handlelinkmsg,
coreapi.CORE_API_EXEC_MSG: self.handleexecmsg,
coreapi.CORE_API_REG_MSG: self.handleregmsg,
coreapi.CORE_API_CONF_MSG: self.handleconfmsg,
coreapi.CORE_API_FILE_MSG: self.handlefilemsg,
coreapi.CORE_API_IFACE_MSG: self.handleifacemsg,
coreapi.CORE_API_EVENT_MSG: self.handleeventmsg,
coreapi.CORE_API_SESS_MSG: self.handlesessionmsg,
}
self.handlerthreads = []
self.nodestatusreq = {}
self.master = False
self.session = None
self.verbose = bool(server.mainserver.cfg['verbose'].lower() == "true")
self.debug = bool(server.mainserver.cfg['debug'].lower() == "true")
SocketServer.BaseRequestHandler.__init__(self, request,
client_address, server)
def setup(self):
''' New client has connected to the auxiliary server.
'''
if self.verbose:
self.info("new auxiliary server client: %s:%s" % self.client_address)
def handle(self):
'''
The handler main loop
'''
port = self.request.getpeername()[1]
self.session = self.server.mainserver.getsession(sessionid = port,
useexisting = False)
self.session.connect(self)
while True:
try:
msgs = self.recvmsg()
if msgs:
for msg in msgs:
self.session.broadcast(self, msg)
self.handlemsg(msg)
except EOFError:
break;
except IOError, e:
self.warn("IOError in CoreAuxRequestHandler: %s" % e)
break;
def finish(self):
'''
Disconnect the client
'''
if self.session:
self.session.disconnect(self)
return SocketServer.BaseRequestHandler.finish(self)
'''
=======================================================================
Concrete AuxRequestHandler classes must redefine the following methods
=======================================================================
'''
def recvmsg(self):
'''
Receive data from the client in the supported format. Parse, transform to CORE API format and
return transformed messages.
EXAMPLE:
return self.handler.request.recv(siz)
'''
pass
return None
def dispatchreplies(self, replies, msg):
'''
Dispatch CORE 'replies' to a previously received message 'msg' from a client.
Replies passed to this method follow the CORE API. This method allows transformation to
the form supported by the auxiliary handler and within the context of 'msg'.
Add transformation and transmission code here.
EXAMPLE:
transformed_replies = stateful_transform (replies, msg) # stateful_transform method needs to be defined
if transformed_replies:
for reply in transformed_replies:
try:
self.request.sendall(reply)
except Exception, e:
if self.debug:
self.info("-"*60)
traceback.print_exc(file=sys.stdout)
self.info("-"*60)
raise e
'''
pass
def sendall(self, data):
'''
CORE calls this method when data needs to be asynchronously sent to a client. The data is
in CORE API format. This method allows transformation to the required format supported by this
handler prior to transmission.
EXAMPLE:
msgs = self.transform(data) # transform method needs to be defined
if msgs:
for msg in msgs:
try:
self.request.sendall(reply)
except Exception, e:
if self.debug:
self.info("-"*60)
traceback.print_exc(file=sys.stdout)
self.info("-"*60)
raise e
'''
pass

View file

@ -62,4 +62,4 @@ emane_models = RfPipe, Ieee80211abg, CommEffect, Bypass
#emane_log_level = 2 #emane_log_level = 2
emane_realtime = True emane_realtime = True
aux_request_handler = core.addons.api2.CoreApi2RequestHandler:12222 aux_request_handler = core.addons.api2handler.CoreApi2RequestHandler:12222

View file

@ -67,9 +67,9 @@ coreapi.add_node_class("CORE_NODE_TUNNEL",
coreapi.add_node_class("CORE_NODE_EMANE", coreapi.add_node_class("CORE_NODE_EMANE",
coreapi.CORE_NODE_EMANE, pycore.nodes.EmaneNode) coreapi.CORE_NODE_EMANE, pycore.nodes.EmaneNode)
#
# UDP server startup
#
def startudp(mainserver, server_address): def startudp(mainserver, server_address):
''' Start a thread running a UDP server on the same host,port for ''' Start a thread running a UDP server on the same host,port for
connectionless requests. connectionless requests.
@ -121,13 +121,14 @@ def cored(cfg = None):
try: try:
server = CoreServer((host, port), CoreRequestHandler, cfg) server = CoreServer((host, port), CoreRequestHandler, cfg)
except Exception, e: except Exception, e:
sys.stderr.write("error starting server on: %s:%s\n\t%s\n" % \ sys.stderr.write("error starting main server on: %s:%s\n\t%s\n" % \
(host, port, e)) (host, port, e))
sys.stderr.flush() sys.stderr.flush()
sys.exit(1) sys.exit(1)
closeonexec(server.fileno()) closeonexec(server.fileno())
sys.stdout.write("main server started, listening on: %s:%s\n" % (host, port)) sys.stdout.write("main server started, listening on: %s:%s\n" % (host, port))
sys.stdout.flush() sys.stdout.flush()
udpserver = startudp(server, (host,port)) udpserver = startudp(server, (host,port))
closeonexec(udpserver.fileno()) closeonexec(udpserver.fileno())
@ -200,8 +201,8 @@ def getMergedConfig(filename):
'daemonize' : 'False', 'daemonize' : 'False',
'debug' : 'False', 'debug' : 'False',
'execfile' : None, 'execfile' : None,
'aux_request_handler' : None 'aux_request_handler' : None,
} }
usagestr = "usage: %prog [-h] [options] [args]\n\n" + \ usagestr = "usage: %prog [-h] [options] [args]\n\n" + \
"CORE daemon v.%s instantiates Linux network namespace " \ "CORE daemon v.%s instantiates Linux network namespace " \