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 os, gc
import os, gc, shlex, shutil
from core import pycore
from core.api import coreapi
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):
''' 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.
'''
daemon_threads = True
@ -218,14 +219,11 @@ class CoreServer(SocketServer.ThreadingMixIn, SocketServer.TCPServer):
break
finally:
self._sessionslock.release()
return found
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.
'''
daemon_threads = True
@ -235,7 +233,7 @@ class CoreUdpServer(SocketServer.ThreadingMixIn, SocketServer.UDPServer):
''' Server class initialization takes configuration data and calls
the SocketServer constructor
'''
self.mainserver = mainserver # tcpserver is the main server
self.mainserver = mainserver
SocketServer.UDPServer.__init__(self, server_address,
RequestHandlerClass)
@ -246,6 +244,7 @@ class CoreUdpServer(SocketServer.ThreadingMixIn, SocketServer.UDPServer):
class CoreAuxServer(SocketServer.ThreadingMixIn, SocketServer.TCPServer):
''' An auxiliary TCP server.
'''
@ -275,7 +274,6 @@ class CoreAuxServer(SocketServer.ThreadingMixIn, SocketServer.TCPServer):
class CoreRequestHandler(SocketServer.BaseRequestHandler):
''' The SocketServer class uses the RequestHandler class for servicing
requests, mainly through the handle() method. The CoreRequestHandler
@ -494,17 +492,17 @@ class CoreRequestHandler(SocketServer.BaseRequestHandler):
try:
replies = msghandler(msg)
self.dispatchreplies(replies)
self.dispatchreplies(replies,msg)
except Exception, e:
self.warn("%s: exception while handling msg:\n%s\n%s" %
(threading.currentThread().getName(), msg,
traceback.format_exc()))
# Added to allow the API2 handler to define a different behavior when replying
# Added to allow the auxiliary handlers to define a different behavior when replying
# to messages from clients
def dispatchreplies(self, replies):
''' Dispatch replies to a handled message.
def dispatchreplies(self, replies, msg):
'''
Dispatch replies by CORE to message msg previously received from the client.
'''
for reply in replies:
if self.debug:
@ -525,6 +523,7 @@ class CoreRequestHandler(SocketServer.BaseRequestHandler):
except Exception, e:
self.warn("Error sending reply data: %s" % e)
def handle(self):
''' Handle a new connection request from a client. Dispatch to the
recvmsg() method for receiving data into CORE API messages, and
@ -1139,10 +1138,10 @@ class CoreRequestHandler(SocketServer.BaseRequestHandler):
if ex:
try:
self.info("executing '%s'" % ex)
if isinstance(self.server, CoreUdpServer):
server = self.server.mainserver
elif isinstance(self.server, CoreApi2Server):
if not isinstance(self.server, CoreServer): # CoreUdpServer):
server = self.server.mainserver
# elif isinstance(self.server, CoreAuxServer):
# server = self.server.mainserver
else:
server = self.server
if msg.flags & coreapi.CORE_API_STR_FLAG:
@ -1575,3 +1574,140 @@ class CoreDatagramRequestHandler(CoreRequestHandler):
''' Use sendto() on the connectionless UDP socket.
'''
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_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.CORE_NODE_EMANE, pycore.nodes.EmaneNode)
#
# UDP server startup
#
def startudp(mainserver, server_address):
''' Start a thread running a UDP server on the same host,port for
connectionless requests.
@ -121,13 +121,14 @@ def cored(cfg = None):
try:
server = CoreServer((host, port), CoreRequestHandler, cfg)
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))
sys.stderr.flush()
sys.exit(1)
closeonexec(server.fileno())
sys.stdout.write("main server started, listening on: %s:%s\n" % (host, port))
sys.stdout.flush()
udpserver = startudp(server, (host,port))
closeonexec(udpserver.fileno())
@ -200,8 +201,8 @@ def getMergedConfig(filename):
'daemonize' : 'False',
'debug' : 'False',
'execfile' : None,
'aux_request_handler' : None
}
'aux_request_handler' : None,
}
usagestr = "usage: %prog [-h] [options] [args]\n\n" + \
"CORE daemon v.%s instantiates Linux network namespace " \