Example #1
0
    def _addsvc(cls, svc):
        if svc.name in cls._svcs_dict:
            raise llbc.error('service name repeat, name: {}'.format(svc.name))
        elif hasattr(cls, svc.name):
            raise llbc.error('service name is used to Service class attribute, name: {}'.format(svc.name))

        cls._svcs_list.append(svc)
        cls._svcs_dict[svc.name] = svc
Example #2
0
    def __init__(self, ty, svc, handler):
        if not self.is_validate_handler_type(ty):
            raise llbc.error('invalidate handler type: {}'.format(ty))
        elif svc is None or (handler is None or not callable(handler)):
            raise llbc.error('service[{}] invalidate or handler[{}] invalidate'.format(svc, handler))

        self._ty = ty
        self._svc = _ref(svc)
        self._handler = handler
Example #3
0
    def registerencoder(self, opcode, encoder):
        """
        Register specific opcode's encoder(only available in CODEC_BINARY codec mode).
        """
        if not hasattr(encoder, 'encode') or not callable(encoder.encode):
            raise llbc.error('invalid encoder, opcode: {}, encoder: {}'.format(opcode, encoder))
        elif encoder in self._encoders:
            raise llbc.error('encoder duplicate registered, opcode: {}, encoder: {}'.format(opcode, encoder))

        self._encoders.update({encoder:opcode})
Example #4
0
    def _addsvc(cls, svc):
        if svc.name in cls._svcs_dict:
            raise llbc.error('service name repeat, name: {}'.format(svc.name))
        elif hasattr(cls, svc.name):
            raise llbc.error(
                'service name is used to Service class attribute, name: {}'.
                format(svc.name))

        cls._svcs_list.append(svc)
        cls._svcs_dict[svc.name] = svc
Example #5
0
    def __init__(self, ty, svc, handler):
        if not self.is_validate_handler_type(ty):
            raise llbc.error('invalidate handler type: {}'.format(ty))
        elif svc is None or (handler is None or not callable(handler)):
            raise llbc.error(
                'service[{}] invalidate or handler[{}] invalidate'.format(
                    svc, handler))

        self._ty = ty
        self._svc = _ref(svc)
        self._handler = handler
Example #6
0
    def registerfacade(self, facade):
        """
        Register facade.
            facade methods(all methods are optional):
                oninitialize(self, ev): service initialize handler.
                    ev.svc: service object.
                ondestroy(self, ev): service destroy handler.
                    ev.svc: service object.
                onupdate(self, ev): service per-frame update handler.
                    ev.svc: service object.
                onidle(self, ev): service per-frame idle handler.
                    ev.svc: service object.
                    ev.idletime: idle time, float type, in seconds.
                onsessioncreate(self, ev): session create handler.
                    ev.svc: service object.
                    ev.islisten: is listen session or not.
                    ev.session_id: session Id.
                    ev.local_ip: local ip address.
                    ev.local_port: local port number.
                    ev.peer_ip: peer ip address.
                    ev.peer_port: peer port number.
                onsessiondestroy(self, ev): session destroy handler.
                    ev.svc: service object.
                    ev.session_id: session Id.
                onasyncconnresult(self, ev): async-connect result handler.
                    ev.svc: service object.
                    ev.peer_ip: peer ip address.
                    ev.peer_port: peer port number.
                    ev.connected: connected flag.
                    ev.reason: reason describe.
                onprotoreport(self, ev): protocol report.
                    ev.svc: service object.
                    ev.report_layer: which layer protocol reported.
                    ev.report_level: report event level(DEBUG, INFO, WARN, ERROR).
                    ev.report_msg: report message.
                    ev.session_id: report session_id(optional, maybe is 0).
                onunhandledpacket(self, ev): unhandled packet.
                    ev.svc: service object.
                    ev.opcode: packet opcode.
        """
        if hasattr(facade, '__bases__') and llbc.ischild(facade, type):
            raise llbc.error('facade could not be type(or derived from type) instance, facade:{}'.format(facade))
        elif isinstance(facade, type):
            raise llbc.error('facade could not be class type object, facade: {}'.format(facade))
        else:
            if isinstance(facade, _types.FunctionType):
                raise llbc.error('facade could not be a function, facade: {}'.format(facade))
            elif isinstance(facade, _types.MethodType):
                raise llbc.error('facade could not be a method(included bound and unbound), facade: {}'.format(facade))

        llbc.inl.RegisterFacade(self._c_obj, facade)
        self._facades.update({facade.__class__: facade})
Example #7
0
    def registerencoder(self, opcode, encoder):
        """
        Register specific opcode's encoder(only available in CODEC_BINARY codec mode).
        """
        if not hasattr(encoder, 'encode') or not callable(encoder.encode):
            raise llbc.error('invalid encoder, opcode: {}, encoder: {}'.format(
                opcode, encoder))
        elif encoder in self._encoders:
            raise llbc.error(
                'encoder duplicate registered, opcode: {}, encoder: {}'.format(
                    opcode, encoder))

        self._encoders.update({encoder: opcode})
Example #8
0
 def __init__(self, ob):
     ob_type = pyllbcObservable.ObserverType
     if callable(ob):
         if type(ob) == MethodType:
             if not ob.__self__:
                 raise llbc.error('observer is MethodType, but method unbound')
             self.type = ob_type.Method
             self.ref = ref(ob.__self__)
             self.func = ob.im_func
         else:
             self.type = ob_type.Callable
             self.ref = ref(ob)
     else:
         raise llbc.error('observer not callable, observer: {}'.format(ob))
Example #9
0
 def __setattr__(cls, key, value):
     if key in cls._svcs_dict:
         raise llbc.error(
             'attribute [{}] already used by service name, could not override'
             .format(key))
     else:
         super(pyllbcServiceMetaCls, cls).__setattr__(key, value)
Example #10
0
    def send(self,
             session_id,
             data,
             opcode=None,
             status=0,
             extData1=0,
             extData2=0,
             extData3=0):
        """
        Send data to specific session
        """
        cls = self.__class__
        svc_type = self._svctype
        if svc_type == cls.NORMAL:
            if opcode is None:
                opcode = self._encoders.get(data.__class__)
                if opcode is None:
                    raise llbc.error(
                        'will send data not specific opcode(forgot use "@llbc.forsend" decorator?), '
                        'data: {}, type: {}'.format(data, data.__class__))
        else:
            opcode = 0

        # Support using packet as session_id to send packet.
        if isinstance(session_id, Packet):
            session_id = session_id.session_id

        llbc.inl.SendData(self._c_obj, session_id, opcode, data, status,
                          extData1, extData2, extData3)
Example #11
0
    def schedule2(self, duetime, period, fmtstr='%Y-%m-%d %H:%M:%S'):
        """
        Schedule timer, arguments is datetime type object, str type object, or numeric type object,
            if duetime type is datetime type object, will use it as expire time.
            if duetime type is str type, will convert to datetime type to use.
            if duetime type is numeric type, will as timestamp to use, as seconds.
        If not specified the tzinfo, llbc will automatic use local tzinfo to fill.
        """
        if isinstance(duetime, unicode):
            duetime = duetime.decode('utf-8')
        if isinstance(duetime, str):
            duetime = _dt.strptime(duetime, fmtstr)

        if isinstance(duetime, _dt):
            ts = _time.mktime(
                duetime.timetuple()) + duetime.microsecond / 1000000.0
        else:
            ts = duetime

        now = _time.time()
        if ts < now:
            raise llbc.error(
                'duetime[{}] < nowtime[{}], schedule timer failed'.format(
                    duetime, _dt.fromtimestamp(now)))

        self.schedule(int((ts - now) * 1000), int(period * 1000))
Example #12
0
 def __init__(self, ob):
     ob_type = pyllbcObservable.ObserverType
     if callable(ob):
         if type(ob) == MethodType:
             if not ob.__self__:
                 raise llbc.error(
                     'observer is MethodType, but method unbound')
             self.type = ob_type.Method
             self.ref = ref(ob.__self__)
             self.func = ob.im_func
         else:
             self.type = ob_type.Callable
             self.ref = ref(ob)
     else:
         raise llbc.error(
             'observer not callable, observer: {}'.format(ob))
Example #13
0
    def set_header_desc(header_desc):
        """
        Set packet header describe.
        """
        if not isinstance(header_desc, llbc.PacketHeaderDesc):
            raise llbc.error('set header desc failed, type error, given type: {}'.format(type(header_desc)))

        llbc.inl.SetPacketHeaderDesc(header_desc._cobj)
Example #14
0
    def add_part(self, part_desc):
        if not isinstance(part_desc, _llbc.PacketHeaderPartDesc):
            raise _llbc.error('part desc type error, type: {}'.format(type(part_desc)))

        _inl.PacketHeaderDesc_AddPart(self._cobj, part_desc._cobj)
        self._parts[part_desc.serial_no] = part_desc

        self._update_bookkeeping()
Example #15
0
    def __init__(self, svcname, svctype=llbc.inl.SVC_TYPE_NORMAL):
        """
        Create new service
        :param svctype: the service type, see service type enumeration.
        :param svcname: the service name, must be not empty.
        """
        if isinstance(svcname, unicode):
            svcname = svcname.encode('utf-8')

        if not isinstance(svcname, str):
            raise llbc.error('service name must str type')
        elif not svcname:
            raise llbc.error('service name must be not empty')

        if self.isgonetolimit():
            raise llbc.error('service count is gone to limit')

        self._svcname = svcname
        self._svctype = svctype

        self._addsvc(self)
        self._c_obj = llbc.inl.NewService(self, svctype, svcname)
        self._svcid = llbc.inl.GetServiceId(self._c_obj)

        self._encoders = {}
        self._facades = {}

        cobj = self._c_obj
        self._fps = llbc.inl.GetServiceFPS(cobj)
        self._frameinterval = llbc.inl.GetServiceFrameInterval(cobj)

        self._last_schedule_time = 0
        self._started = False

        self._terminating = False
        self._terminated = False

        self._subscribe_exc_handlers = dict(
        )  # key: opcode, value: exception handler
        self._presubscribe_exc_handlers = dict(
        )  # key: opcode, value: exception handler

        self._dft_subscribe_exc_handler = None
        self._dft_presubscribe_exc_handler = None
Example #16
0
    def schedule(cls, schedule_time=0, idle_sleep=True):
        """
        Service mainloop
        :param schedule_time: specific schedule time, in seconds, if less than or equal to 0, schedule or return immediately.
        :param idle_sleep: at one schedule operation, if service check has idle time, will sleep if idle_sleep set to True, otherwise not sleep.
        """
        if cls._scheduling:
            raise llbc.error('Service in scheduling, not allow to reschedule')
        cls._scheduling = True

        svcs = cls._svcs_list
        schedule_interval = 1.0 / cls.MAX_FPS
        svc_mainloop = llbc.inl.ServiceMainLoop
        update_timers = llbc.inl.PyTimerUpdateAllTimers
        inst_errhooker = llbc.inl.InstallErrHooker
        uninst_errhooker = llbc.inl.UninstallErrHooker
        clear_hookederrors = llbc.inl.ClearHookedErrors

        try:
            inst_errhooker()
            cls._procwilldelsvcs()

            if schedule_time > 0:
                schedule_beg = _pyllbc_time()

            while True:
                if idle_sleep:
                    scheduleonce_beg = _pyllbc_time()

                clear_hookederrors()
                try:
                    for svc in svcs:
                        if not svc._started:
                            continue

                        svc_beg = _pyllbc_time()
                        if svc_beg - svc._last_schedule_time >= svc._frameinterval:
                            cobj = svc._c_obj
                            try:
                                svc_mainloop(cobj)
                            except Exception, e:
                                frame_exc_handler = cls._frame_exc_handler
                                if frame_exc_handler is not None:
                                    tb = _sys.exc_info()[2]
                                    frame_exc_handler(svc, tb, e)
                                else:
                                    raise
                            finally:
                                svc._last_schedule_time = svc_beg

                        if cls._procpendingdeschedule():
                            return

                    update_timers()
                    if cls._procpendingdeschedule():
                        return
Example #17
0
    def set_header_desc(header_desc):
        """
        Set packet header describe.
        """
        if not isinstance(header_desc, llbc.PacketHeaderDesc):
            raise llbc.error(
                'set header desc failed, type error, given type: {}'.format(
                    type(header_desc)))

        llbc.inl.SetPacketHeaderDesc(header_desc._cobj)
Example #18
0
def pyllbc_extractreg(wrapped, ty):
    """
    Extract wrapped class/function library register info data, if not exist, will create it.
    """
    if not isinstance(wrapped, (TypeType, ClassType)):
        raise llbc.error('@forsend/@forrecv/@handler/@prehandler/@unify_prehandler/@exc_handler/@exc_prehandler/@bindto decorator ' \
                'must decorate class type object, could not decorate {}'.format(type(wrapped)))

    RegCls = llbc.inl.SvcRegInfo

    libkey = '__pyllbcreg__'
    if not hasattr(wrapped, libkey):
        setattr(wrapped, libkey, RegCls(wrapped))

    reg = getattr(wrapped, libkey)
    if reg.regtype == RegCls.UnSpecific:
        reg.regtype = ty
    elif ty != RegCls.UnSpecific and ty != reg.regtype:
        raise llbc.error('conflict to use @handler/@prehandler/@unify_prehandler/@exc_handler/@exc_prehandler \
                and @forsend/@forrecv decorator in the same class: {}'.format(wrapped))

    return reg
Example #19
0
    def __init__(self, svcname, svctype=llbc.inl.SVC_TYPE_NORMAL):
        """
        Create new service
        :param svctype: the service type, see service type enumeration.
        :param svcname: the service name, must be not empty.
        """
        if not isinstance(svcname, str):
            raise llbc.error('service name must str type')
        elif not svcname:
            raise llbc.error('service name must be not empty')

        if self.isgonetolimit():
            raise llbc.error('service count is gone to limit')

        self._svcname = svcname
        self._svctype = svctype

        self._addsvc(self)
        self._c_obj = llbc.inl.NewService(self, svctype)

        self._encoders = {}
        self._facades = {}

        cobj = self._c_obj
        self._fps = llbc.inl.GetServiceFPS(cobj)
        self._frameinterval = llbc.inl.GetServiceFrameInterval(cobj)

        self._last_schedule_time = 0
        self._started = False

        self._terminating = False
        self._terminated = False

        self._subscribe_exc_handlers = dict()  # key: opcode, value: exception handler
        self._presubscribe_exc_handlers = dict()  # key: opcode, value: exception handler

        self._dft_subscribe_exc_handler = None 
        self._dft_presubscribe_exc_handler = None
Example #20
0
 def set_default_presubscribe_exc_handler(self, dft_exc_handler):
     """
     Set the packet pre-handler's default exception handler.
     handler proto-type:
         the_packet_exception_handler(packet, traceback_obj, exception_value)
             packet: the packet object.
             traceback_obj: the traceback type instance.
             error_value: the exception value.
     """
     if dft_exc_handler is None:
         self._dft_presubscribe_exc_handler = None
     elif not callable(dft_exc_handler):
         raise llbc.error('{} not callable'.format(dft_exc_handler))
     else:
         self._dft_presubscribe_exc_handler = dft_exc_handler
Example #21
0
 def set_default_presubscribe_exc_handler(self, dft_exc_handler):
     """
     Set the packet pre-handler's default exception handler.
     handler proto-type:
         the_packet_exception_handler(packet, traceback_obj, exception_value)
             packet: the packet object.
             traceback_obj: the traceback type instance.
             error_value: the exception value.
     """
     if dft_exc_handler is None:
         self._dft_presubscribe_exc_handler = None
     elif not callable(dft_exc_handler):
         raise llbc.error('{} not callable'.format(dft_exc_handler))
     else:
         self._dft_presubscribe_exc_handler = dft_exc_handler
Example #22
0
def pyllbc_extractreg(wrapped, ty):
    """
    Extract wrapped class/function library register info data, if not exist, will create it.
    """
    if not isinstance(wrapped, (TypeType, ClassType, FunctionType)):
        raise llbc.error('@forsend/@forrecv/@handler/@prehandler/@unify_prehandler/@exc_handler/@exc_prehandler/@bindto decorator ' \
                'must decorate class type object or function type object, could not decorate {}'.format(type(wrapped)))

    RegCls = llbc.inl.SvcRegInfo

    libkey = '__pyllbcreg__'
    if not hasattr(wrapped, libkey):
        setattr(wrapped, libkey, RegCls(wrapped))

    reg = getattr(wrapped, libkey)
    if reg.regtype == RegCls.UnSpecific:
        reg.regtype = ty
    elif ty != RegCls.UnSpecific and ty != reg.regtype:
        raise llbc.error(
            'conflict to use @handler/@prehandler/@unify_prehandler/@exc_handler/@exc_prehandler \
                and @forsend/@forrecv decorator in the same class: {}'.format(
                wrapped))

    return reg
Example #23
0
    def schedule(cls):
        """
        Service mainloop
        """
        if cls._scheduling:
            raise llbc.error('Service in scheduling, not allow to reschedule')
        cls._scheduling = True

        svcs = cls._svcs_list
        schedule_interval = 1.0 / cls.MAX_FPS
        svc_mainloop = llbc.inl.ServiceMainLoop
        update_timers = llbc.inl.PyTimerUpdateAllTimers
        inst_errhooker = llbc.inl.InstallErrHooker
        uninst_errhooker = llbc.inl.UninstallErrHooker
        clear_hookederrors = llbc.inl.ClearHookedErrors

        try:
            inst_errhooker()
            cls._procwilldelsvcs()
            while True:
                clear_hookederrors()
                schedule_beg = _pyllbc_time()
                try:
                    for svc in svcs:
                        if not svc._started:
                            continue
    
                        svc_beg = _pyllbc_time()
                        if svc_beg - svc._last_schedule_time >= svc._frameinterval:
                            cobj = svc._c_obj
                            try:
                                svc_mainloop(cobj)
                            except Exception, e:
                                frame_exc_handler = cls._frame_exc_handler
                                if frame_exc_handler is not None:
                                    tb = _sys.exc_info()[2]
                                    frame_exc_handler(svc, tb, e)
                                else:
                                    raise
                            finally:
                                svc._last_schedule_time = svc_beg

                        if cls._procpendingdeschedule():
                            return
                        
                    update_timers()
                    if cls._procpendingdeschedule():
                        return
Example #24
0
 def set_frame_exc_handler(cls, exc_handler):
     """
     Set service per-frame exception handler(class method).
     handler can be function or method or callable object.
     handler method proto-type:
         the_frame_exception_handler(service_obj, traceback_obj, exception_value)
             service_obj: the service instance, this params maybe None if raised in timer.
             traceback_obj: the traceback type instance.
             error_value: the exception value.
     """
     if exc_handler is None:
         cls._frame_exc_handler = None
     elif not callable(exc_handler):
         raise llbc.error('{} not callable'.format(exc_handler))
     else:
         cls._frame_exc_handler = exc_handler
Example #25
0
 def set_presubscribe_exc_handler(self, opcode, exc_handler):
     """
     Set the packet pre-handler's exception handler.
     handler proto-type:
         the_packet_exception_handler(packet, traceback_obj, exception_value)
             packet: the packet object.
             traceback_obj: the traceback type instance.
             error_value: the exception value.
     """
     if exc_handler is None:
         if opcode in self._presubscribe_exc_handlers:
             del self._presubscribe_exc_handlers[opcode]
     elif not callable(exc_handler):
         raise llbc.error('{} not callable'.format(exc_handler))
     else:
         self._presubscribe_exc_handlers[opcode] = exc_handler
Example #26
0
 def set_presubscribe_exc_handler(self, opcode, exc_handler):
     """
     Set the packet pre-handler's exception handler.
     handler proto-type:
         the_packet_exception_handler(packet, traceback_obj, exception_value)
             packet: the packet object.
             traceback_obj: the traceback type instance.
             error_value: the exception value.
     """
     if exc_handler is None:
         if opcode in self._presubscribe_exc_handlers:
             del self._presubscribe_exc_handlers[opcode]
     elif not callable(exc_handler):
         raise llbc.error('{} not callable'.format(exc_handler))
     else:
         self._presubscribe_exc_handlers[opcode] = exc_handler
Example #27
0
 def set_frame_exc_handler(cls, exc_handler):
     """
     Set service per-frame exception handler(class method).
     handler can be function or method or callable object.
     handler method proto-type:
         the_frame_exception_handler(service_obj, traceback_obj, exception_value)
             service_obj: the service instance, this params maybe None if raised in timer.
             traceback_obj: the traceback type instance.
             error_value: the exception value.
     """
     if exc_handler is None:
         cls._frame_exc_handler = None
     elif not callable(exc_handler):
         raise llbc.error('{} not callable'.format(exc_handler))
     else:
         cls._frame_exc_handler = exc_handler
Example #28
0
        def wrapper(*call_varargs, **call_kwargs):
            call_args = _get_call_args(arg_names, vararg_name, kw_name, call_varargs, call_kwargs)
            k, item = None, None
            try:
                for k in validator:
                    if k == vararg_name:
                        for item in call_args[k]:
                            assert validator[k](item)
                    elif k == kw_name:
                        for item in call_args[k].itervalues():
                            assert validator[k](item)
                    else:
                        item = call_args[k]
                        assert validator[k](item)
            except:
                raise error('{}() parameter validation failed, param: {}, value: {}({})'
                        .format(func.func_name, k, item, item.__class__.__name__))

            return func(*call_varargs, **call_kwargs)
Example #29
0
        def wrapper(*call_varargs, **call_kwargs):
            call_args = _get_call_args(arg_names, vararg_name, kw_name,
                                       call_varargs, call_kwargs)
            k, item = None, None
            try:
                for k in validator:
                    if k == vararg_name:
                        for item in call_args[k]:
                            assert validator[k](item)
                    elif k == kw_name:
                        for item in call_args[k].itervalues():
                            assert validator[k](item)
                    else:
                        item = call_args[k]
                        assert validator[k](item)
            except:
                raise error(
                    '{}() parameter validation failed, param: {}, value: {}({})'
                    .format(func.func_name, k, item, item.__class__.__name__))

            return func(*call_varargs, **call_kwargs)
Example #30
0
    def send(self, session_id, data, opcode=None, status=0, parts=None):
        """
        Send data to specific session
        """
        cls = self.__class__
        svc_type = self._svctype
        if svc_type == cls.NORMAL:
            if opcode is None:
                opcode = self._encoders.get(data.__class__)
                if opcode is None:
                    raise llbc.error('will send data not specific opcode(forgot use "@llbc.forsend" decorator?), '
                            'data: {}, type: {}'.format(data, data.__class__))
        else:
            opcode = 0
        
        # Support using packet as session_id to send packet.
        if isinstance(session_id, Packet):
            session_id = session_id.session_id

        if parts is None:
            llbc.inl.SendData(self._c_obj, session_id, opcode, data, status)
        else:
            llbc.inl.SendData(self._c_obj, session_id, opcode, data, status, parts)
Example #31
0
    def schedule2(self, duetime, period, fmtstr='%Y-%m-%d %H:%M:%S'):
        """
        Schedule timer, arguments is datetime type object, str type object, or numeric type object,
            if duetime type is datetime type object, will use it as expire time.
            if duetime type is str type, will convert to datetime type to use.
            if duetime type is numeric type, will as timestamp to use, as seconds.
        If not specified the tzinfo, llbc will automatic use local tzinfo to fill.
        """
        if isinstance(duetime, unicode):
            duetime = duetime.decode('utf-8')
        if isinstance(duetime, str):
            duetime = _dt.strptime(duetime, fmtstr)

        if isinstance(duetime, _dt):
            ts = _time.mktime(duetime.timetuple()) + duetime.microsecond / 1000000.0
        else:
            ts = duetime

        now = _time.time()
        if ts < now:
            raise llbc.error('duetime[{}] < nowtime[{}], schedule timer failed'.format(duetime, _dt.fromtimestamp(now)))

        self.schedule(int((ts - now) * 1000), int(period * 1000))
Example #32
0
 def _startcheck(self):
     if self._started:
         raise llbc.error('service object already started')
     elif self._terminating:
         raise llbc.error('service object terminating')
Example #33
0
 def __setattr__(cls, key, value):
     if key in cls._svcs_dict:
         raise llbc.error('attribute [{}] already used by service name, could not override'.format(key))
     else:
         super(pyllbcServiceMetaCls, cls).__setattr__(key, value)
Example #34
0
 def _startcheck(self):
     if self._started:
         raise llbc.error('service object already started')
     elif self._terminating:
         raise llbc.error('service object terminating')
Example #35
0
    def registerfacade(self, facade):
        """
        Register facade.
            facade methods(all methods are optional):
                oninitialize(self, ev): service initialize handler.
                    ev.svc: service object.
                ondestroy(self, ev): service destroy handler.
                    ev.svc: service object.
                onstart(self, ev): service start handler.
                    ev.svc: service object.
                onstop(self, ev): service stop handler.
                    ev.svc: service object.
                onupdate(self, ev): service per-frame update handler.
                    ev.svc: service object.
                onidle(self, ev): service per-frame idle handler.
                    ev.svc: service object.
                    ev.idletime: idle time, float type, in seconds.
                onsessioncreate(self, ev): session create handler.
                    ev.svc: service object.
                    ev.islisten: is listen session or not.
                    ev.session_id: session Id.
                    ev.local_ip: local ip address.
                    ev.local_port: local port number.
                    ev.peer_ip: peer ip address.
                    ev.peer_port: peer port number.
                onsessiondestroy(self, ev): session destroy handler.
                    ev.svc: service object.
                    ev.session_id: session Id.
                    ev.reason: destroy reason.
                    ev.destroyed_from_service: destroyed from service flag.
                    ev.local_ip: local ip address.
                    ev.local_port: local port number.
                    ev.peer_ip: peer ip address.
                    ev.peer_port: peer port number.
                    ev.socket: socket file descripter.
                    ev.errno: error number(only available when ev.destroyed_from_service is True).
                    ev.sub_errno: sub error number(only available when ev.destroyed_from_service is True).
                onasyncconnresult(self, ev): async-connect result handler.
                    ev.svc: service object.
                    ev.peer_ip: peer ip address.
                    ev.peer_port: peer port number.
                    ev.connected: connected flag.
                    ev.reason: reason describe.
                onprotoreport(self, ev): protocol report.
                    ev.svc: service object.
                    ev.report_layer: which layer protocol reported.
                    ev.report_level: report event level(DEBUG, INFO, WARN, ERROR).
                    ev.report_msg: report message.
                    ev.session_id: report session_id(optional, maybe is 0).
                onunhandledpacket(self, ev): unhandled packet.
                    ev.svc: service object.
					ev.session_id: packet session Id.
                    ev.opcode: packet opcode.
					ev.packet: packet object.
        """
        if hasattr(facade, '__bases__') and llbc.ischild(facade, type):
            raise llbc.error(
                'facade could not be type(or derived from type) instance, facade:{}'
                .format(facade))
        elif isinstance(facade, type):
            raise llbc.error(
                'facade could not be class type object, facade: {}'.format(
                    facade))
        else:
            if isinstance(facade, _types.FunctionType):
                raise llbc.error(
                    'facade could not be a function, facade: {}'.format(
                        facade))
            elif isinstance(facade, _types.MethodType):
                raise llbc.error(
                    'facade could not be a method(included bound and unbound), facade: {}'
                    .format(facade))

        llbc.inl.RegisterFacade(self._c_obj, facade)
        self._facades.update({facade.__class__: facade})