def handle_read(self): if _debug: MSTPDirector._debug("handle_read") try: msg, addr = self.socket.recvfrom(512) if _debug: MSTPDirector._debug(" - received %d octets ", len(msg)) pdu = PDU(msg,destination=int(str(self.address))) mstp_src = pdu.get() pdu.pduSource = Address(mstp_src) if _debug: MSTPDirector._debug("Received MSTP PDU={}".format(str(pdu))) # send the PDU up to the client deferred(self._response, pdu) except socket.timeout as err: if _debug: MSTPDirector._debug(" - socket timeout: %s", err) except socket.error as err: if err.args[0] == 11: pass else: if _debug: MSTPDirector._debug(" - socket error: %s", err) # pass along to a handler self.handle_error(err) except Exception as e: MSTPDirector._error('Exception in handle_read: {}'.format(e))
def main(): print "test start" s = MyServer() c = MyClient() d = Debug("packet") bind(c,d,s) c.request("hi") pdu = PDU("hello", source = 1, destination = 2) pdu.debug_contents()
def complete(self, iocb): MiddleMan._debug('complete %r', iocb) # if this has completed successfully, pass it up if iocb.ioState == COMPLETED: self.response(PDU(str(iocb.ioResponse) + '\n')) # if this aborted, pass that up too elif iocb.ioState == ABORTED: self.response(PDU(repr(iocb.ioError) + '\n')) else: raise RuntimeError, "invalid state: %r" % (iocb.ioState, )
def callback(self, iocb): """Callback when an iocb is completed by a local controller and the result needs to be sent back to the client.""" if _debug: IOServer._debug("callback %r", iocb) # make sure it's one of ours if not self.remoteIOCB.has_key(iocb): IOServer._warning("IOCB not owned by server: %r", iocb) return # get the client information clientID, clientAddr = self.remoteIOCB[iocb] # we're done with this del self.remoteIOCB[iocb] # build a response if iocb.ioState == COMPLETED: response = (1, clientID, iocb.ioResponse) elif iocb.ioState == ABORTED: response = (2, clientID, iocb.ioError) else: raise RuntimeError, "IOCB invalid state" if _debug: _commlog.debug("<<< %s: S %s %r" % (_strftime(), clientAddr, response)) response = cPickle.dumps(response, 1) # send it to the client self.request(PDU(response, destination=clientAddr))
def confirmation(self, pdu): if _debug: MiddleMan._debug('confirmation %r', pdu) # turn it back into something to print data = repr(pdu.pduData) + '\n' self.response(PDU(data))
def indication(self, pdu): if _debug: MiddleMan._debug('indication %r', pdu) # no data means EOF, stop if not pdu.pduData: director.disconnect(server_addr) return # pass it along self.request(PDU(pdu.pduData, destination=server_addr))
def indication(self, pdu): if _debug: MiddleMan._debug("indication %r", pdu) global server_address # no data means EOF, stop if not pdu.pduData: stop() return # pass it along self.request(PDU(pdu.pduData, destination=server_address))
def indication(self, pdu): if _debug: MiddleMan._debug("indication %r", pdu) global server_address # no data means EOF, stop if not pdu.pduData: # ask the director (downstream peer) to close the connection self.clientPeer.disconnect(server_address) return # pass it along self.request(PDU(pdu.pduData, destination=server_address))
def indication(self, add_actor=None, del_actor=None, actor_error=None, error=None): global args if add_actor: if _debug: WritePropertyASE._debug("indication add_actor=%r", add_actor) # it's connected, maybe say hello if args.hello: self.elementService.indication(PDU(b'hello\n', destination=add_actor.peer)) if del_actor: if _debug: WritePropertyASE._debug("indication del_actor=%r", del_actor) if actor_error: if _debug: WritePropertyASE._debug("indication actor_error=%r error=%r", actor_error, error)
def indication(self, req): """Got a request from the application.""" if _debug: ModbusClient._debug("indication %r", req) # encode it as a generic MPDU mpdu = MPDU() req.encode(mpdu) if _debug: ModbusClient._debug(" - mpdu: %r", mpdu) # encode it as a PDU pdu = PDU() mpdu.encode(pdu) if _debug: ModbusClient._debug(" - pdu: %r", pdu) # pass it along to the device self.request(pdu)
def indication(self, resp): """This is a response from the application.""" if _debug: ModbusServer._debug("indication %r", resp) # encode as a generic MPDU mpdu = MPDU() resp.encode(mpdu) if _debug: ModbusServer._debug(" - mpdu: %r", mpdu) # encode as a generic PDU pdu = PDU() mpdu.encode(pdu) if _debug: ModbusServer._debug(" - pdu: %r", pdu) # return the response to the device self.request(pdu)
def complete(self, iocb): if _debug: WritePropertyClient._debug('complete %r', iocb) # pull out the original request pdu pdu = iocb.request_pdu # do something for success if iocb.ioResponse: # should be an ack if not isinstance(iocb.ioResponse, SimpleAckPDU): response_str = "not an ack: " + repr(iocb.ioResponse) + '\r\n' else: response_str = "ack" + '\r\n' # do something for error/reject/abort if iocb.ioError: response_str = "error: " + repr(iocb.ioError) + '\r\n' # send it back to the client self.request(PDU(response_str.encode('utf-8'), destination=pdu.pduSource))
def indication(self, server, pdu): if _debug: MSTPMultiplexer._debug("indication %r %r", server, pdu) # check for a broadcast message if pdu.pduDestination.addrType == Address.localBroadcastAddr: dest = 255 if _debug: MSTPMultiplexer._debug(" - requesting local broadcast: %r", dest) # interface might not support broadcasts if not dest: return elif pdu.pduDestination.addrType == Address.localStationAddr: dest = pdu.pduDestination if _debug: MSTPMultiplexer._debug(" - requesting local station: %r", dest) else: raise RuntimeError("invalid destination address type") self.directPort.indication(PDU(pdu, destination=dest))
def new_iocb(self, clientAddr, iocbid, controllerName, args, kwargs): """Called when the server receives a new request.""" if _debug: IOServer._debug("new_iocb %r %r %r %r %r", clientAddr, iocbid, controllerName, args, kwargs) # look for a controller controller = _local_controllers.get(controllerName, None) if not controller: # create a nice error message err = RuntimeError("no local controller '%s'" % (controllerName, )) # build an abort response response = (2, iocbid, err) if _debug: _commlog.debug("<<< %s: S %s %r" % (_strftime(), clientAddr, response)) response = cPickle.dumps(response, 1) # send it to the server self.request(PDU(response, destination=clientAddr)) else: # create an IOCB iocb = IOCB(*args, **kwargs) if _debug: IOServer._debug(" - local IOCB %r bound to remote %r", iocb.ioID, iocbid) # save a reference to it self.remoteIOCB[iocb] = (iocbid, clientAddr) # make sure we're notified when it completes iocb.add_callback(self.callback) # pass it along controller.request_io(iocb)
def process_io(self, iocb): """Package up the local IO request and send it to the server.""" if _debug: IOProxyServer._debug("process_io %r", iocb) # save a reference in our dictionary self.localIOCB[iocb.ioID] = iocb # start a default timer if one hasn't already been set if not iocb.ioTimeout: iocb.set_timeout( SERVER_TIMEOUT, RuntimeError("no response from " + iocb.ioServerRef)) # build a message request = (0, iocb.ioID, iocb.ioControllerRef, iocb.args, iocb.kwargs) if _debug: _commlog.debug("<<< %s: P %s %r" % (_strftime(), iocb.ioServerRef, request)) request = cPickle.dumps(request, 1) # send it to the server self.request(PDU(request, destination=(iocb.ioServerRef, PORT)))
def abort_io(self, iocb, err): """Called by a local client or a local controlled to abort a transaction.""" if _debug: IOProxyServer._debug("abort_io %r %r", iocb, err) # if it completed, leave it alone if iocb.ioState == COMPLETED: pass # if it already aborted, leave it alone elif iocb.ioState == ABORTED: pass elif self.localIOCB.has_key(iocb.ioID): # delete the dictionary reference del self.localIOCB[iocb.ioID] # build an abort request request = (2, iocb.ioID, err) if _debug: _commlog.debug("<<< %s: P %s %r" % (_strftime(), iocb.ioServerRef, request)) request = cPickle.dumps(request, 1) # send it to the server self.request(PDU(request, destination=(iocb.ioServerRef, PORT))) else: raise RuntimeError, "no reference to aborting iocb: %r" % ( iocb.ioID, ) # change the state iocb.ioState = ABORTED iocb.ioError = err # notify the client iocb.trigger()
class MiddleMan(Client, Server, Logging): def __init__(self): if _debug: MiddleMan._debug("__init__") Client.__init__(self) Server.__init__(self) # not connected self.connected = False def indication(self, pdu): if _debug: MiddleMan._debug('indication %r (connected %r)', pdu, self.connected) # no data means EOF, stop if not pdu.pduData: if _debug: MiddleMan._debug(' - flushing') # get the actor and tell it to flush and close director.get_actor(server_addr).flush() stop() return # empty lines are ignored if pdu.pduData == '\n': return # turn it into something to pickle try: data = eval(pdu.pduData[:-1]) if _debug: MiddleMan._debug(' - data: %r', data) except Exception, err: if _debug: MiddleMan._debug("eval exception: %r", err) return self.request(PDU(data, destination=server_addr))
def confirmation(self, pdu): if _debug: WritePropertyClient._debug('confirmation %r', pdu) global this_application # decode the bytes into a string and strip off the end-of-line args = pdu.pduData.decode('utf-8').strip().split() if _debug: WritePropertyClient._debug(" - args: %r", args) try: addr, obj_type, obj_inst, prop_id = args[:4] if obj_type.isdigit(): obj_type = int(obj_type) obj_inst = int(obj_inst) value = args[4] indx = None if len(args) >= 6: if args[5] != "-": indx = int(args[5]) if _debug: WritePropertyClient._debug(" - indx: %r", indx) priority = None if len(args) >= 7: priority = int(args[6]) if _debug: WritePropertyClient._debug(" - priority: %r", priority) # get the datatype datatype = get_datatype(obj_type, prop_id) if _debug: WritePropertyClient._debug(" - datatype: %r", datatype) # change atomic values into something encodeable, null is a special case if (value == 'null'): value = Null() elif issubclass(datatype, Atomic): if datatype is Integer: value = int(value) elif datatype is Real: value = float(value) elif datatype is Unsigned: value = int(value) value = datatype(value) elif issubclass(datatype, Array) and (indx is not None): if indx == 0: value = Integer(value) elif issubclass(datatype.subtype, Atomic): value = datatype.subtype(value) elif not isinstance(value, datatype.subtype): raise TypeError("invalid result datatype, expecting %s" % (datatype.subtype.__name__,)) elif not isinstance(value, datatype): raise TypeError("invalid result datatype, expecting %s" % (datatype.__name__,)) if _debug: WritePropertyClient._debug(" - encodeable value: %r %s", value, type(value)) # build a request request = WritePropertyRequest( objectIdentifier=(obj_type, obj_inst), propertyIdentifier=prop_id ) request.pduDestination = Address(addr) # save the value request.propertyValue = Any() try: request.propertyValue.cast_in(value) except Exception as error: WritePropertyClient._exception("WriteProperty cast error: %r", error) # optional array index if indx is not None: request.propertyArrayIndex = indx # optional priority if priority is not None: request.priority = priority if _debug: WritePropertyClient._debug(" - request: %r", request) # make an IOCB iocb = IOCB(request) if _debug: WritePropertyClient._debug(" - iocb: %r", iocb) # reference the original request so the response goes back to the # correct client iocb.request_pdu = pdu # add ourselves to be called back for the response iocb.add_callback(self.complete) # give it to the application this_application.request_io(iocb) except Exception as error: WritePropertyClient._exception("exception: %r", error) # send it back to the client error_str = "exception: " + str(error) + '\r\n' self.request(PDU(error_str.encode('utf-8'), destination=pdu.pduSource))
def main(): """ Main function, called when run as an application. """ global args, server_address # parse the command line arguments parser = ArgumentParser(description=__doc__) parser.add_argument( "host", nargs='?', help="address of host (default %r)" % (SERVER_HOST, ), default=SERVER_HOST, ) parser.add_argument( "port", nargs='?', type=int, help="server port (default %r)" % (SERVER_PORT, ), default=SERVER_PORT, ) parser.add_argument( "--hello", action="store_true", default=False, help="send a hello message", ) parser.add_argument( "--connect-timeout", nargs='?', type=int, help="idle connection timeout", default=CONNECT_TIMEOUT, ) parser.add_argument( "--idle-timeout", nargs='?', type=int, help="idle connection timeout", default=IDLE_TIMEOUT, ) args = parser.parse_args() if _debug: _log.debug("initialization") if _debug: _log.debug(" - args: %r", args) # extract the server address and port host = args.host port = args.port server_address = (host, port) if _debug: _log.debug(" - server_address: %r", server_address) # build the stack this_console = ConsoleClient() if _debug: _log.debug(" - this_console: %r", this_console) this_middle_man = MiddleMan() if _debug: _log.debug(" - this_middle_man: %r", this_middle_man) this_director = TCPClientDirector( connect_timeout=args.connect_timeout, idle_timeout=args.idle_timeout, ) if _debug: _log.debug(" - this_director: %r", this_director) bind(this_console, this_middle_man, this_director) bind(MiddleManASE(), this_director) # create a task manager for scheduled functions task_manager = TaskManager() if _debug: _log.debug(" - task_manager: %r", task_manager) # don't wait to connect deferred(this_director.connect, server_address) # send hello maybe if args.hello: deferred(this_middle_man.indication, PDU(b'Hello, world!\n')) if _debug: _log.debug("running") run() if _debug: _log.debug("fini")
def confirmation(self, pdu): if _debug: EchoMaster._debug('confirmation %r', pdu) self.request(PDU(pdu.pduData, destination=pdu.pduSource))
server = TestServer() bind(client, server) client.request('hi') # Add debugging into the middle of the stack # Upstream when traveling from server to client # Downstream when traveling from client to server d = Debug("middle") bind(client, d, server) client.request('Hi') #%% Protocol data units from bacpypes.comm import PDU pdu = PDU(b'hello') # Data portion of PDU only pdu.debug_contents() # Add source and destination information pdu = PDU(b'hello', source=1, destination=2) pdu.pduSource = 1 pdu.pduDestination = 2 pdu.debug_contents() # Encoding and decoding a PDU """THis process consists of consuming content from a PDU (data, source, destination) and generating content in the destination Think if Decoding a PDU like taking characters out of an array Encoding a PDU is like stacking characters into an array""" pdu = PDU(b'hello!!!', source=1, destination=2) pdu.debug_contents() pdu.get() # 104
def confirmation(self, pdu): if _debug: EchoMaster._debug('confirmation %r', pdu) # send it back down the stack self.request(PDU(pdu.pduData, destination=pdu.pduSource))