Exemple #1
0
def secureInterruptHandlerScheduler(timer=None):
    try:
        # Execute CBF LIST from local cached config with timirqseq in sec
        scheduler(CFG_TIMER_IRQ[0], CFG_TIMER_IRQ[1])
    except Exception as e:
        console_write("[IRQ] TIMIRQ (cron) callback: {} error: {}".format(
            CFG_TIMER_IRQ[0], e))
Exemple #2
0
def profiling_info(label=""):
    """
    Runtime memory measurements
    """
    if cfgget('dbg'):
        console_write("{} [PROFILING INFO] - {} {}".format('~'*5, label, '~'*5))
        mem_info()
        console_write("~"*30)
Exemple #3
0
def secureInterruptHandlerSimple(timer=None):
    try:
        # Execute CBF from cached config
        state = execute_LM_function_Core(CFG_TIMER_IRQ[0].split(' '))
        if not state:
            console_write("[IRQ] TIMIRQ execute_LM_function_Core error: {}".format(CFG_TIMER_IRQ[0]))
    except Exception as e:
        console_write("[IRQ] TIMIRQ callback: {} error: {}".format(CFG_TIMER_IRQ[0], e))
Exemple #4
0
def set_emergency_buffer():
    emergency_buff_kb = cfgget('irqmembuf')
    if cfgget('extirq') or cfgget("timirq"):
        from micropython import alloc_emergency_exception_buf
        console_write("[IRQ] Interrupts was enabled, alloc_emergency_exception_buf={}".format(emergency_buff_kb))
        alloc_emergency_exception_buf(emergency_buff_kb)
    else:
        console_write("[IRQ] Interrupts disabled, skip alloc_emergency_exception_buf configuration.")
Exemple #5
0
def secureEventInterruptHandler(pin=None):
    """
    EVENT INTERRUPT CALLBACK FUNCTION WRAPPER
    """
    try:
        state = execute_LM_function_Core(CFG_EVIRQCBF.split(' '))
        if not state:
            console_write("[IRQ] EXTIRQ execute_LM_function_Core error: {}".format(CFG_EVIRQCBF))
    except Exception as e:
        console_write("[IRQ] EVENTIRQ callback: {} error: {}".format(CFG_EVIRQCBF, e))
Exemple #6
0
def deserialize_raw_input(raw_cron_input):
    datastruct = []
    try:
        datastruct = [
            tuple(cron.split('!')) for cron in raw_cron_input.split(';')
        ]
    except Exception as e:
        console_write(
            "deserialize_raw_input: input syntax error: {}".format(e))
    return datastruct
Exemple #7
0
def set_emergency_buffer():
    from micropython import alloc_emergency_exception_buf
    irqmembuf = cfgget('irqmembuf')
    emergency_buff_kb = irqmembuf if irqmembuf is not None and isinstance(
        irqmembuf, int) else 1000
    if cfgget('extirq') or cfgget("timirq"):
        console_write(
            "[IRQ] Interrupts was enabled, alloc_emergency_exception_buf={}".
            format(emergency_buff_kb))
        alloc_emergency_exception_buf(emergency_buff_kb)
    else:
        console_write(
            "[IRQ] Interrupts disabled, skip alloc_emergency_exception_buf configuration."
        )
Exemple #8
0
def __enableInterruptSimple():
    """
    SIMPLE TIMER INTERRUPT CONFIGURATION
    """
    # LOAD DATA FOR TIMER IRQ: cfgget("timirq")
    # CACHE TASK FOR CBF
    CFG_TIMER_IRQ[0] = cfgget('timirqcbf')
    if CFG_TIMER_IRQ[0].lower() != 'n/a':
        from machine import Timer
        # INIT TIMER IRQ with callback function wrapper
        timer = Timer(0)
        timer.init(period=int(cfgget("timirqseq")), mode=Timer.PERIODIC, callback=secureInterruptHandlerSimple)
    else:
        console_write("[IRQ] TIMIRQ: isenable: {} callback: {}".format(cfgget("timirq"), cfgget('timirqcbf')))
Exemple #9
0
 def __recovery(self, is_critic=False):
     """
     Handle memory errors here
     """
     self.reply_message("[HA] system recovery ...")
     collect()
     self.reply_message("[HA] gc-collect-memfree: {}".format(mem_free()))
     if is_critic:
         try:
             self.reply_message(
                 "[HA] Critical error - disconnect & hard reset")
             self.__safe_reboot_system()
         except Exception as e:
             console_write("==> [!!!][HA] Recovery error: {}".format(e))
Exemple #10
0
def setNTP_RTC():
    if WLAN(STA_IF).isconnected():
        for _ in range(4):
            try:
                # Sync with NTP server
                settime()
                # Get localtime + GMT
                (year, month, mday, hour, minute, second, weekday,
                 yearday) = localtime(time() + int(cfgget('gmttime')) * 3600)
                # Create RealTimeClock + Set RTC with time (+timezone)
                RTC().datetime((year, month, mday, 0, hour, minute, second, 0))
                # Print time
                console_write("NTP setup DONE: {}".format(localtime()))
                return True
            except Exception as e:
                console_write("NTP setup errer.:{}".format(e))
            sleep(0.5)
    else:
        console_write("NTP setup errer: STA not connected!")
    # Recursion to get actual time for cron execution
    if cfgget('cron'):
        console_write("[!] NTP setup retry due to cron is {}".format(
            cfgget('cron')))
        return setNTP_RTC()
    return False
Exemple #11
0
def __scheduler_trigger(cron_time_now,
                        check_time_now_sec_tuple,
                        scheduler_fragment,
                        sec_tolerance=2):
    """
    SchedulerCore logic
        cron time now format: WD, H, M, S
    """
    check_time = tuple(
        int(t.strip()) if t.strip() != '*' else t.strip()
        for t in scheduler_fragment[0].split(':'))
    # Cron actual time (now) parts summary in sec
    check_time_now_sec = check_time_now_sec_tuple[
        0] + check_time_now_sec_tuple[1] + check_time_now_sec_tuple[2]
    # Cron overall requested time in sec - hour in sec, minute in sec, sec
    check_time_scheduler_sec = int(check_time_now_sec_tuple[0] if check_time[1] == '*' else check_time[1] * 3600) \
                               + int(check_time_now_sec_tuple[1] if check_time[2] == '*' else check_time[2] * 60) \
                               + int(check_time_now_sec_tuple[2] if check_time[3] == '*' else check_time[3])

    # Time frame +/- corrections
    tolerance_min_sec = 0 if check_time_now_sec - sec_tolerance < 0 else check_time_now_sec - sec_tolerance
    tolerance_max_sec = check_time_now_sec + sec_tolerance

    task_id = "{}:{}|{}".format(check_time[0], check_time_scheduler_sec,
                                scheduler_fragment[1].replace(' ', ''))

    # Check WD - WEEK DAY
    if check_time[0] == '*' or check_time[0] == cron_time_now[0]:
        # Check H, M, S in sec format between tolerance range
        if tolerance_min_sec <= check_time_scheduler_sec <= tolerance_max_sec:
            __cron_task_cache_manager(check_time_now_sec, sec_tolerance)
            if check_time[3] == '*' or task_id not in LAST_CRON_TASKS:
                lm_state = execute_LM_function_Core(
                    scheduler_fragment[1].split())
                if not lm_state:
                    console_write(
                        "[CRON ERROR]NOW[{}]  {} <-> {}  CONF[{}] EXECUTE[{}] LM: {}"
                        .format(cron_time_now,
                                __convert_sec_to_time(tolerance_min_sec),
                                __convert_sec_to_time(tolerance_max_sec),
                                scheduler_fragment[0], lm_state,
                                scheduler_fragment[1]))

                # SAVE TASK TO CACHE
                if check_time[3] != '*':
                    # SAVE WHEN SEC not *
                    LAST_CRON_TASKS.append(task_id)
                return True
    return False
Exemple #12
0
def init_eventPIN():
    """
    EVENT INTERRUPT CONFIGURATION
    """
    global CFG_EVIRQCBF
    if cfgget('extirq') and cfgget('extirqcbf').lower() != 'n/a':
        CFG_EVIRQCBF = cfgget('extirqcbf')
        pin = get_pin_on_platform_by_key('pwm_4')
        console_write("[IRQ] EVENTIRQ ENABLED PIN: {} CBF: {}".format(pin, CFG_EVIRQCBF))
        # Init event irq with callback function wrapper
        from machine import Pin
        pin_obj = Pin(pin, Pin.IN, Pin.PULL_UP)
        pin_obj.irq(trigger=Pin.IRQ_RISING, handler=secureEventInterruptHandler)
    else:
        console_write("[IRQ] EVENTIRQ: isenable: {} callback: {}".format(cfgget('extirq'), CFG_EVIRQCBF))
Exemple #13
0
def secureInterruptHandler(timer=None):
    """
    TIMER INTERRUPT CALLBACK FUNCTION WRAPPER
    """
    try:
        if CFG_TIMIRQCBF.lower() != 'n/a':
            # Execute CBF from config
            state = execute_LM_function_Core(CFG_TIMIRQCBF.split(' '))
            if not state:
                console_write(
                    "[IRQ] TIMIRQ execute_LM_function_Core error: {}".format(
                        CFG_TIMIRQCBF))
    except Exception as e:
        console_write("[IRQ] TIMIRQ callback: {} error: {}".format(
            CFG_TIMIRQCBF, e))
 def __recovery(self, errlvl=0):
     """
     Handle memory errors here
     """
     self.reply_message("[HA] system recovery ...")
     if 'esp' in platform:
         collect()
         self.reply_message("[HA] gc-ollect-memfree: {}".format(mem_free()))
         if errlvl == 1:
             try:
                 self.reply_message(
                     "[HA] Critical error - disconnect & hard reset")
                 self.__safe_reboot_system()
             except Exception as e:
                 console_write("==> [!!!][HA] Recovery error: {}".format(e))
     else:
         console_write("[HA] recovery only available on esp - nodemcu")
Exemple #15
0
def __select_available_wifi_nw(sta_if, raw_essid, raw_pwd):
    """
    raw_essid: essid parameter, in case of multiple values separator is ;
    raw_pwd: essid pwd parameter,  in case of multiple values separator is ;
    return detected essid with corresponding password
    """
    for idx, essid in enumerate(raw_essid.split(';')):
        essid = essid.strip()
        # Scan wifi network - retry workaround
        for _ in range(0, 2):
            if essid in (wifispot[0].decode('utf-8')
                         for wifispot in sta_if.scan()):
                console_write(
                    '\t| - [NW: STA] ESSID WAS FOUND: {}'.format(essid))
                return essid, str(raw_pwd.split(';')[idx]).strip()
            sleep(1)
    return None, ''
Exemple #16
0
def enableInterrupt():
    """
    TIMER INTERRUPT CALLBACK FUNCTION CONFIG. WRAPPER
    - FIRST PRIORITY: SCHEDULER
    - SECOND PRIORITY: SIMPLE PERIODIC CALLBACK
    """
    console_write("[IRQ] TIMIRQ SETUP - TIMIRQ: {} SEQ: {}".format(cfgget("timirq"), cfgget("timirqseq")))
    console_write("|- [IRQ] CRON:{} CBF:{}".format(cfgget('cron'), cfgget('crontasks')))
    console_write("|- [IRQ] SIMPLE CBF:{}".format(cfgget('timirqcbf')))
    if cfgget("timirq"):
        # Configure advanced scheduler OR simple repeater
        if cfgget('cron') and cfgget('crontasks').lower() != 'n/a':
            console_write("|-- TIMER IRQ MODE: SCHEDULER")
            # ENABLE ADVANCED SCHEDULER (BASED ON SIMPLE TIMIRQ)
            __enableInterruptScheduler()
            return
        # ENABLE SIMPLE PERIODIC INTERRUPT
        console_write("|-- TIMER IRQ MODE: SIMPLE")
        __enableInterruptSimple()
Exemple #17
0
 def run(self):
     self.server_console(
         "[ socket server ] SERVER ADDR: telnet {} {}".format(
             cfgget("devip"), self.__port))
     try:
         cfgput('version', self.__socket_interpreter_version)
     except Exception as e:
         console_write(
             "Export system version to config failed: {}".format(e))
     self.__init_socket()
     self.__bind_and_accept()
     while True:
         try:
             # Evaluate incoming msg via InterpreterShell -> InterpreterCore "Console prompt"
             is_healthy = InterpreterShell_shell(self.__wait_for_message(),
                                                 SocketServerObj=self)
             if not is_healthy:
                 console_write(
                     "[EXEC-WARNING] InterpreterShell internal error.")
                 self.__recovery(is_critic=False)
         except OSError:
             # BrokenPipeError
             self.__reconnect()
         except Exception as e:
             console_write(
                 "[EXEC-ERROR] InterpreterShell error: {}".format(e))
             self.__recovery(is_critic=True)
         # Memory dimensioning dump
         self.server_console(
             '[X] AFTER INTERPRETER EXECUTION FREE MEM [byte]: {}'.format(
                 mem_free()))
Exemple #18
0
def profiling_info(label=""):
    """
    Runtime memory measurements
    """
    if cfgget('dbg'):
        console_write("{} [PROFILING INFO] - {} {}".format(
            '~' * 5, label, '~' * 5))
        try:
            mem_info()
        except Exception as e:
            console_write("MEM INFO QUERY ERROR: {}".format(e))
        console_write("~" * 30)
    else:
        console_write("[PROFILING INFO] SKIP dbg:{}".format(cfgget('dbg')))
Exemple #19
0
def bootup_hook():
    """
    Executes when system boots up.
    """
    console_write("[BOOT HOOKS] EXECUTION...")
    if cfgget('boothook') is not None and cfgget('boothook').lower() != 'n/a':
        for shell_cmd in (cmd.strip()
                          for cmd in tuple(cfgget('boothook').split(';'))
                          if len(cmd.split()) > 1):
            console_write("|-[BOOT HOOKS] SHELL EXEC: {}".format(shell_cmd))
            try:
                state = execute_LM_function_Core(shell_cmd.split())
                console_write("|-[BOOT HOOKS] state: {}".format(state))
            except Exception as e:
                console_write("|--[BOOT HOOKS] error: {}".format(e))
Exemple #20
0
def __set_wifi_dev_static_ip(sta_if):
    console_write("[NW: STA] Set device static IP.")
    stored_ip = cfgget('devip')
    if 'n/a' not in stored_ip.lower() and '.' in stored_ip:
        conn_ips = list(sta_if.ifconfig())
        # Check ip type before change, conn_ip structure: 10.0.1.X
        if conn_ips[0] != stored_ip and conn_ips[-1].split(
                '.')[0:3] == stored_ip.split('.')[0:3]:
            conn_ips[0] = stored_ip
            console_write("\t| [NW: STA] DEV. StaticIP: {}".format(stored_ip))
            try:
                # IP address, subnet mask, gateway and DNS server
                sta_if.ifconfig(tuple(conn_ips))
                return True  # was reconfigured
            except Exception as e:
                console_write(
                    "\t\t| [NW: STA] StaticIP conf. failed: {}".format(e))
        else:
            console_write("[NW: STA][SKIP] StaticIP conf.: {} ? {}".format(
                stored_ip, conn_ips[0]))
    else:
        console_write("[NW: STA] IP was not stored: {}".format(stored_ip))
    return False  # was not reconfigured
Exemple #21
0
def set_access_point(_essid, _pwd, _authmode=3):
    console_write("[NW: AP] SET AP MODE: {} - {} - auth mode: {}".format(
        _essid, _pwd, _authmode))

    sta_if = WLAN(STA_IF)
    if sta_if.isconnected():
        sta_if.active(False)

    ap_if = WLAN(AP_IF)
    ap_if.active(True)
    # Set WiFi access point name (formally known as ESSID) and WiFi authmode (2): WPA2
    try:
        console_write("[NW: AP] Configure")
        ap_if.config(essid=_essid, password=_pwd, authmode=_authmode)
    except Exception as e:
        console_write("[NW: AP] Config Error: {}".format(e))
    if ap_if.active() and str(ap_if.config('essid')) == str(
            _essid) and ap_if.config('authmode') == _authmode:
        cfgput("devip", ap_if.ifconfig()[0])
    console_write("\t|\t| [NW: AP] network config: " + str(ap_if.ifconfig()))
    set_uid_macaddr_hex(ap_if)
    return ap_if.active()
    def run(self):
        if "esp" in platform:
            self.server_console("[ socket server ] SERVER ADDR: telnet " +
                                str(cfgget("devip")) + " " + str(self.port))
        else:
            self.server_console(
                "[ socket server ] SERVER ADDR: telnet 127.0.0.1 " +
                str(self.port))

        try:
            cfgput('version', self.__socket_interpreter_version)
        except Exception as e:
            console_write(
                "Export system version to config failed: {}".format(e))
        self.__init_socket()
        self.__bind_and_accept()
        while True:
            try:
                # Evaluate incoming msg via InterpreterShell -> InterpreterCore "Console prompt"
                is_healthy, msg = InterpreterShell_shell(
                    self.__wait_for_message(), SocketServerObj=self)
                if not is_healthy:
                    console_write(
                        "[EXEC-WARNING] InterpreterShell internal error: {}".
                        format(msg))
                    self.__recovery(errlvl=0)
            except OSError:
                # BrokenPipeError
                self.__reconnect()
            except Exception as e:
                console_write(
                    "[EXEC-ERROR] InterpreterShell error: {}".format(e))
                self.__recovery(errlvl=1)
            # Memory dimensioning dump
            if mem_free is not None:
                self.server_console(
                    '[X] AFTER INTERPRETER EXECUTION FREE MEM [byte]: {}'.
                    format(mem_free()))
Exemple #23
0
def enableInterrupt():
    """
    TIMER INTERRUPT CONFIGURATION
    """
    global CFG_TIMIRQCBF
    CFG_TIMIRQCBF = cfgget('timirqcbf')
    if cfgget("timirq") and CFG_TIMIRQCBF.lower() != 'n/a':
        try:
            period_ms_usr = int(cfgget("timirqseq"))
        except Exception as e:
            console_write("[IRQ] TIMIRQ period query error: {}".format(e))
            period_ms_usr = 3000
        console_write("[IRQ] TIMIRQ ENABLED: SEQ: {} CBF: {}".format(
            period_ms_usr, CFG_TIMIRQCBF))
        from machine import Timer
        # Init timer irq with callback function wrapper
        timer = Timer(0)
        timer.init(period=period_ms_usr,
                   mode=Timer.PERIODIC,
                   callback=secureInterruptHandler)
    else:
        console_write("[IRQ] TIMIRQ: isenable: {} callback: {}".format(
            cfgget("timirq"), cfgget('timirqcbf')))
Exemple #24
0
Designed by Marcell Ban aka BxNxM
"""
#########################################################
#                         IMPORTS                       #
#########################################################

from socket import socket, AF_INET, SOCK_STREAM, SOL_SOCKET, SO_REUSEADDR
from time import sleep
from ConfigHandler import console_write, cfgget, cfgput
from InterpreterShell import shell as InterpreterShell_shell

try:
    from gc import collect, mem_free
except:
    console_write("[SIMULATOR MODE GC IMPORT]")
    from simgc import collect, mem_free

#########################################################
#                    SOCKET SERVER CLASS                #
#########################################################


class SocketServer:
    """
    Socket message data packet layer - send and receive
    Embedded command interpretation:
    - hello
    - version
    - exit
    - reboot
Exemple #25
0
def set_wifi(essid, pwd, timeout=60):
    console_write('[NW: STA] SET WIFI STA NW {}'.format(essid))

    # Disable AP mode
    ap_if = WLAN(AP_IF)
    if ap_if.active():
        ap_if.active(False)
    del ap_if

    # Set STA and Connect
    sta_if = WLAN(STA_IF)
    sta_if.active(True)
    if not sta_if.isconnected():
        # Multiple essid and pwd handling with retry mechanism
        essid, pwd = __select_available_wifi_nw(sta_if, essid, pwd)

        # Connect to the located wifi network
        if essid is not None:
            console_write('\t| [NW: STA] CONNECT TO NETWORK {}'.format(essid))
            # connect to network
            sta_if.connect(essid, pwd)
            # wait for connection, with timeout set
            while not sta_if.isconnected() and timeout > 0:
                console_write("\t| [NW: STA] Waiting for connection... " +
                              str(timeout) + "/60")
                timeout -= 1
                sleep(0.5)
            # Set static IP - here because some data comes from connection.
            if sta_if.isconnected() and __set_wifi_dev_static_ip(sta_if):
                sta_if.disconnect()
                del sta_if
                return set_wifi(essid, pwd)
        else:
            console_write(
                "\t| [NW: STA] Wifi network was NOT found: {}".format(essid))
            return False
        console_write("\t|\t| [NW: STA] network config: " +
                      str(sta_if.ifconfig()))
        console_write("\t|\t| [NW: STA] CONNECTED: " +
                      str(sta_if.isconnected()))
    else:
        console_write("\t| [NW: STA] ALREADY CONNECTED TO {}".format(essid))
    cfgput("devip", str(sta_if.ifconfig()[0]))
    set_uid_macaddr_hex(sta_if)
    return sta_if.isconnected()
Exemple #26
0
def bootup_hook():
    """
    Executes when system boots up.
    """
    # Execute LMs from boothook config parameter
    console_write("[BOOT HOOKS] EXECUTION...")
    if cfgget('boothook') is not None and cfgget('boothook').lower() != 'n/a':
        for shell_cmd in (cmd.strip() for cmd in tuple(cfgget('boothook').split(';')) if len(cmd.split()) > 1):
            console_write("|-[BOOT HOOKS] SHELL EXEC: {}".format(shell_cmd))
            try:
                state = execute_LM_function_Core(shell_cmd.split())
                console_write("|-[BOOT HOOKS] state: {}".format(state))
            except Exception as e:
                console_write("|--[BOOT HOOKS] error: {}".format(e))

    # Set boostmd (boost mode)
    if cfgget('boostmd') is True:
        console_write("[BOOT HOOKS] Set up CPU 16MHz/24MHz - boostmd: {}".format(cfgget('boostmd')))
        if platform == 'esp8266': freq(160000000)
        if platform == 'esp32': freq(240000000)
    else:
        console_write("[BOOT HOOKS] Set up CPU 8MHz - boostmd: {}".format(cfgget('boostmd')))
        freq(80000000)
 def server_console(self, msg):
     console_write("|" + "-" * self.server_console_indent + msg)
     if self.server_console_indent < 50:
         # if less then max indent
         self.server_console_indent += 1
 def __del__(self):
     console_write("[ socket server ] <<destructor>>")
     self.__deinit_socket()
Exemple #29
0
def set_wifi(essid, pwd, timeout=60):
    console_write('[NW: STA] SET WIFI: {}'.format(essid))
    essid_found = False

    # Disable AP mode
    ap_if = WLAN(AP_IF)
    if ap_if.active():
        ap_if.active(False)
    del ap_if

    # Set STA and Connect
    sta_if = WLAN(STA_IF)
    sta_if.active(True)
    if not sta_if.isconnected():
        console_write('\t| [NW: STA] CONNECT TO NETWORK {}'.format(essid))
        # Scan wifi network - retry workaround
        for _ in range(0, 2):
            if essid in (wifispot[0].decode('utf-8')
                         for wifispot in sta_if.scan()):
                essid_found = True
                console_write(
                    '\t| - [NW: STA] ESSID WAS FOUND {}'.format(essid_found))
                break
            sleep(1)
        # Connect to the located wifi network
        if essid_found:
            # connect to network
            sta_if.connect(essid, pwd)
            # wait for connection, with timeout set
            while not sta_if.isconnected() and timeout > 0:
                console_write("\t| [NW: STA] Waiting for connection... " +
                              str(timeout) + "/60")
                timeout -= 1
                sleep(0.5)
            # Set static IP - here because some data comes from connection.
            if sta_if.isconnected() and __set_wifi_dev_static_ip(sta_if):
                sta_if.disconnect()
                del sta_if
                return set_wifi(essid, pwd)
        else:
            console_write(
                "\t| [NW: STA] Wifi network was NOT found: {}".format(essid))
            return False
        console_write("\t|\t| [NW: STA] network config: " +
                      str(sta_if.ifconfig()))
        console_write("\t|\t| [NW: STA] CONNECTED: " +
                      str(sta_if.isconnected()))
    else:
        console_write("\t| [NW: STA] ALREADY CONNECTED TO {}".format(essid))
    cfgput("devip", str(sta_if.ifconfig()[0]))
    set_uid_macaddr_hex(sta_if)
    return sta_if.isconnected()
                try:
                    self.reply_message(
                        "[HA] Critical error - disconnect & hard reset")
                    self.__safe_reboot_system()
                except Exception as e:
                    console_write("==> [!!!][HA] Recovery error: {}".format(e))
        else:
            console_write("[HA] recovery only available on esp - nodemcu")

    def server_console(self, msg):
        console_write("|" + "-" * self.server_console_indent + msg)
        if self.server_console_indent < 50:
            # if less then max indent
            self.server_console_indent += 1

    def __del__(self):
        console_write("[ socket server ] <<destructor>>")
        self.__deinit_socket()


#########################################################
#                 MAIN (FOR TEST REASONS)               #
#########################################################

if __name__ == "__main__":
    try:
        server = SocketServer()
        server.run()
    except KeyboardInterrupt:
        console_write("Keyboard interrupt in SocketServer.")