def register(protocol: int, rid: int, callback): """ 注册DCOM服务回调函数 :param protocol: 协议号 :param rid: 服务号 :param callback: 回调函数.格式: func(pipe: int, src_ia: int, req: bytearray) (bytearray, int) :return: 返回值是应答和错误码.错误码为0表示回调成功,否则是错误码 """ log.info('register.protocol:%d rid:%d', protocol, rid) rid += protocol << 16 _services[rid] = callback
def service_callback(protocol: int, pipe: int, src_ia: int, rid: int, req: bytearray) -> (bytearray, int): """ 回调资源号rid对应的函数 """ log.info('service callback.rid:%d', rid) rid += protocol << 16 if rid not in _services: log.warn('service callback failed!can not find new rid:%d', rid) return None, SYSTEM_ERROR_INVALID_RID return _services[rid](pipe, src_ia, req)
def rx_ack_frame(protocol: int, pipe: int, src_ia: int, frame: Frame): """ 接收到ACK帧时处理函数 """ _lock.acquire() log.info('rx ack frame.src ia:0x%x', src_ia) for item in _items: if _check_item_and_deal_ack_frame(protocol, pipe, src_ia, frame, item): break _lock.release()
def send(protocol: int, pipe: int, dst_ia: int, frame: Frame): """ 发送数据 """ if frame is None: return load_param = get_load_param() if not load_param.is_allow_send(pipe): log.warn('send failed!pipe:0x%x is not allow send.token:%d', pipe, frame.control_word.token) return log.info('send frame.token:%d protocol:%d pipe:0x%x dst ia:0x%x', frame.control_word.token, protocol, pipe, dst_ia) load_param.send(protocol, pipe, dst_ia, frame_to_bytes(frame))
def send_rst_frame(protocol: int, pipe: int, dst_ia: int, error_code: int, rid: int, token: int): """ 发送错误码 """ log.info('send rst frame:0x%x!token:%d protocol:%d pipe:0x%x dst ia:0x%x', error_code, token, protocol, pipe, dst_ia) frame = Frame() frame.control_word.code = CODE_RST frame.control_word.block_flag = 0 frame.control_word.rid = rid frame.control_word.token = token frame.control_word.payload_len = 1 frame.payload.append((error_code | 0x80) & 0xff) send(protocol, pipe, dst_ia, frame)
def block_send(protocol: int, pipe: int, dst_ia: int, frame: BlockFrame): """ 块传输发送数据 """ if frame is None: return load_param = get_load_param() if not load_param.is_allow_send(pipe): log.warn('block send failed!pipe:0x%x is not allow send.token:%d', pipe, frame.control_word.token) return log.info('block send frame.token:%d protocol:%d pipe:0x%x dst ia:0x%x offset:%d', frame.control_word.token, protocol, pipe, dst_ia, frame.block_header.offset) load_param.send(protocol, pipe, dst_ia, block_frame_to_bytes(frame))
def _send_frame(protocol: int, pipe: int, dst_ia: int, code: int, rid: int, token: int, data: bytearray): if len(data) > SINGLE_FRAME_SIZE_MAX: block_tx(protocol, pipe, dst_ia, code, rid, token, data) return frame = Frame() frame.control_word.code = code frame.control_word.block_flag = 0 frame.control_word.rid = rid frame.control_word.token = token frame.control_word.payload_len = len(data) frame.payload.extend(data) log.info('send frame.token:%d', token) send(protocol, pipe, dst_ia, frame)
def call(protocol: int, pipe: int, dst_ia: int, rid: int, timeout: int, req: bytearray) -> (bytearray, int): """ RPC同步调用 :param protocol: 协议号 :param pipe: 通信管道 :param dst_ia: 目标ia地址 :param rid: 服务号 :param timeout: 超时时间,单位:ms.为0表示不需要应答 :param req: 请求数据.无数据可填bytearray()或者None :return: 返回值是应答字节流和错误码.错误码非SYSTEM_OK表示调用失败 """ log.info('call.protocol:%d pipe:0x%x dst ia:0x%x rid:%d timeout:%d', protocol, pipe, dst_ia, rid, timeout) code = CODE_CON if timeout > 0 else CODE_NON if not req: req = bytearray() token = get_token() _send_frame(protocol, pipe, dst_ia, code, rid, token, req) if code == CODE_NON: return bytearray(), SYSTEM_OK item = _Item() item.protocol = protocol item.pipe = pipe item.timeout = timeout * 1000 item.req = req item.start_time = get_time() item.dst_ia = dst_ia item.rid = rid item.token = token item.code = code item.retry_num = 0 item.last_retry_timestamp = get_time() _lock.acquire() _items.append(item) _lock.release() while True: if item.is_rx_ack: break log.info('call resp.result:%d len:%d', item.result, len(item.resp)) return item.resp, item.result
def _check_item_and_deal_ack_frame(protocol: int, pipe: int, src_ia: int, frame: Frame, item: _Item) -> bool: if item.protocol != protocol or item.pipe != pipe or item.dst_ia != src_ia or item.rid != frame.control_word.rid \ or item.token != frame.control_word.token: return False log.info('deal ack frame.token:%d', item.token) _items.remove(item) if item.ack_callback: # 回调方式 item.ack_callback(frame.payload, SYSTEM_OK) else: # 同步调用 item.is_rx_ack = True item.result = SYSTEM_OK item.resp = frame.payload return True
def call_async(protocol: int, pipe: int, dst_ia: int, rid: int, timeout: int, req: bytearray, ack_callback: Callable[[bytearray, int], None]): """ RPC异步调用 :param protocol: 协议号 :param pipe: 通信管道 :param dst_ia: 目标ia地址 :param rid: 服务号 :param timeout: 超时时间,单位:ms.为0表示不需要应答 :param req: 请求数据.无数据可填bytearray()或者None :param ack_callback: 回调函数.原型func(resp: bytearray, error: int).参数是应答字节流和错误码.错误码非SYSTEM_OK表示调用失败 """ code = CODE_CON if timeout == 0 or not callable(ack_callback): code = CODE_NON if not req: req = bytearray() token = get_token() log.info( 'call async.token:%d protocol:%d pipe:0x%x dst ia:0x%x rid:%d timeout:%d', token, protocol, pipe, dst_ia, rid, timeout) _send_frame(protocol, pipe, dst_ia, code, rid, token, req) if code == CODE_NON: return item = _Item() item.ack_callback = ack_callback item.protocol = protocol item.pipe = pipe item.timeout = timeout * 1000 item.req = req item.start_time = get_time() item.dst_ia = dst_ia item.rid = rid item.token = token item.code = code item.retry_num = 0 item.last_retry_timestamp = get_time() _lock.acquire() _items.append(item) _lock.release()