def next(self, input):
        action = map(RSNAction.RSNAction, [input["action"]])[0]
        if action == RSNAction.turnOn:
            # TODO: do something about boot-strap
            # TODO: ping GSN
            # Qian: turnOn is called by host, thus, it is not necessary to make a DNS query.
            # just pass it within input
            # RSN can be set by:
            # 1. There is one bus asking for adding but there is no RSN yet (that bus is the first one in its route)
            # 2. The previous RSN is lost
            # for situation 1, the driver state machine will be hung up because he needs to wait for the initialization of RSN state machine
            # In situation 2, the GSN will send a backup group info to the new RSN. (Backup is not necessary for situation 1)

            # Terry: when a rsn turn on, it means gsn sent a message to bus to indicate it to be a rsn
            # Terry: the message should include the route and group info
            #GROUP_MEMBER = input["group_member"]
            #BUS_TABLE = input["bus_table"]
            global GSN_ADDR, LOCAL_ADDR, RSN_ID
            gsnIp = socket.gethostbyname('localhost')
            gsnPort = 40000  # pre-configured
            GSN_ADDR = Addr(gsnIp, gsnPort)

            LOCAL_ADDR = Addr(input["localIP"], input["localPort"])
            RSN_ID = input["rsnId"]

            LOC_REQ_NO = 0

            return RSNSM.Idle
        else:
            # remain off
            return RSNSM.Off
Exemple #2
0
 def next(self, input):
     action = map(UserAction.UserAction, [input["action"]])[0]
     if action == UserAction.turnOn:
         global LOCAL_ADDR, GSN_ADDR, USER_ID
         # TODO: do something about boot-strap
         # TODO: ping DNS
         LOCAL_ADDR = Addr(input["localIP"], input["localPort"])
         gsnIp = socket.gethostbyname('localhost')
         gsnPort = 40000  # pre-configured
         GSN_ADDR = Addr(gsnIp, gsnPort)
         USER_ID = input["userId"]
         return UserSM.Ready
     else:
         # remain off
         return UserSM.Off
    def next(self, input):
        action = map(DriverAction.DriverAction, [input["action"]])[0]
        if action == DriverAction.turnOn:
            global ROUTE_NO, DIRECTION, BUS_ID, LOCAL_ADDR, GSN_ADDR

            # TODO: do something about boot-strap
            # TODO: DNS query, need to read this name from config.
            # gsn_ip = socket.gethostbyname('ece.cmu.edu')
            gsnIp = socket.gethostbyname('localhost')
            gsnPort = 40000  # pre-configured
            GSN_ADDR = Addr(gsnIp, gsnPort)
            
            LOCAL_ADDR = Addr(input["localIP"], input["localPort"])
            BUS_ID = input["busId"]            
            
            return DriverSM.Idle
        else:
            # remain off
            return DriverSM.Off
    def next(self, input):
        action = map(GSNAction.GSNAction, [input["action"]])[0]
        if action == GSNAction.turnOn:
            global LOCAL_ADDR, GSN_ID, TIMER_OFF, TIMER_ON
            # do something about boot-strap
            # Qian: seems we don't need to do anything
            LOCAL_ADDR = Addr(input["localIP"], input["localPort"])
            GSN_ID = input["gsnId"]

            # unblock the timer thread
            TIMER_OFF.clear()
            TIMER_ON.set()

            return GSNSM.Ready
        else:
            # remain off
            return GSNSM.Off
    def next(self, input):
        action = map(DriverAction.DriverAction, [input["action"]])[0]
        if action == DriverAction.recvLocReq:
            # TODO: response the current location
            # check if the rsn is my RSN, route matched?
            global ROUTE_NO, DIRECTION, RSN_ADDR, LOCAL_ADDR, BUS_ID, WATCHDOG
            LOGGER.info("received RSN location request: %s" % input)
            
            # pet the watch dog
            WATCHDOG.petWatchdog()
            
            # check if the RSN has changed
            if RSN_ADDR.ip != input["rsnIP"] or RSN_ADDR.port != input["rsnPort"]:
                LOGGER.info("RSN has changed")
                RSN_ADDR = Addr(input["rsnIP"], input["rsnPort"])
            
            loc_message = {
                           "SM" : "RSN_SM",
                           "action" : "recvDriverLoc",
                           "requestNo" : input["requestNo"],
                           "route" : ROUTE_NO,
                           "direction" : DIRECTION,
                           "busId" : BUS_ID,
                           "location" : Location.getLocation(), 
                           "busIP" : LOCAL_ADDR.ip,
                           "busPort" : LOCAL_ADDR.port
                           }
            # TODO: TEST ONLY; rsn should be modified
            MessagePasser.directSend(RSN_ADDR.ip, RSN_ADDR.port, loc_message)
            
            return DriverSM.Ready
        
        elif action == DriverAction.restart:
            # restart
            global LOCAL_ADDR, RSN_ADDR, ROUTE_NO, DIRECTION, BUS_ID, RESEND_ELECT_NUM

            LOGGER.info("Receive restart message from GSN. Restart now.")
                
                
            # TODO: ping RSN to add into the group
            add_message = {
                           "SM" : "GSN_SM",
                           "action" : "recvBusReq",
                           "type" : "add",
                           "route" : ROUTE_NO,
                           "direction" : DIRECTION,
                           "busId" : BUS_ID,
                           "location" : Location.getLocation(), 
                           "busIP" : LOCAL_ADDR.ip,
                           "busPort" : LOCAL_ADDR.port
                           }
            # TODO: should use real gsn 
            MessagePasser.directSend(GSN_ADDR.ip, GSN_ADDR.port, add_message)

            RESEND_ELECT_NUM = 0
            
            # pet the watch dog
            WATCHDOG.petWatchdog()
            
            return DriverSM.Init_Waiting
        elif action == DriverAction.timeout:
            # if reaches the limit of re-elect, reboot
            global RESEND_ELECT_NUM
            if RESEND_ELECT_NUM >= 3:
                LOGGER.info("RESEND_ELECT_NUM reaches the limit, reboot now.")
                RESEND_ELECT_NUM = 0
                # restart
                global LOCAL_ADDR, RSN_ADDR, ROUTE_NO, DIRECTION, BUS_ID

                add_message = {
                               "SM" : "GSN_SM",
                               "action" : "recvBusReq",
                               "type" : "add",
                               "route" : ROUTE_NO,
                               "direction" : DIRECTION,
                               "busId" : BUS_ID,
                               "location" : Location.getLocation(), 
                               "busIP" : LOCAL_ADDR.ip,
                               "busPort" : LOCAL_ADDR.port
                               }
                # TODO: should use real gsn 
                MessagePasser.directSend(GSN_ADDR.ip, GSN_ADDR.port, add_message)
                
                # pet the watch dog
                WATCHDOG.petWatchdog()
                
                return DriverSM.Init_Waiting
            else:
                # re-send re-elect msg
                LOGGER.info("send re-elect request to GSN, RESEND_ELECT_NUM: %s" % str(RESEND_ELECT_NUM))
                RESEND_ELECT_NUM = RESEND_ELECT_NUM + 1
                RSN_elect_message = {
                                     "SM" : "GSN_SM",
                                     "action" : "recvElecReq",
                                     "busId" : BUS_ID,
                                     "route" : ROUTE_NO,
                                     "direction" : DIRECTION,
                                     "location" : Location.getLocation(),
                                     "busIP" : LOCAL_ADDR.ip,
                                     "busPort" : LOCAL_ADDR.port
                                     }
                MessagePasser.directSend(GSN_ADDR.ip, GSN_ADDR.port, RSN_elect_message)
                
                # pet the watch dog
                WATCHDOG.petWatchdog()
                
                return DriverSM.Hold
        elif action == DriverAction.turnOff:
            # TODO: do something to shut-down
            RESEND_ELECT_NUM = 0
            WATCHDOG.stopWatchdog()
            return DriverSM.Off
        else:
            # for other illegal action
            # assert 0, "Init_Waiting: invalid action: %s" % str(input)
            pass
    def next(self, input):
        action = map(DriverAction.DriverAction, [input["action"]])[0]
        if action == DriverAction.recvRSNAck:
            global MYSELF_ADDR, RSN_ADDR, ROUTE_NO, DIRECTION, BUS_ID

            # if the response route number doesn't match
            if input["route"] != ROUTE_NO:
                return DriverSM.Init_Waiting
            
            RSN_ADDR = Addr(input["rsnIP"], input["rsnPort"])
            
            # pet the watch dog
            WATCHDOG.petWatchdog()

            return DriverSM.Ready
        elif action == DriverAction.timeout:
            # not receive the reponse from RSN for 15 secs
            global RESEND_ELECT_NUM
            if RESEND_ELECT_NUM >= 3:
                LOGGER.info("RESEND_ELECT_NUM reaches the limit, reboot now.")
                RESEND_ELECT_NUM = 0
                # restart
                global LOCAL_ADDR, RSN_ADDR, ROUTE_NO, DIRECTION, BUS_ID

                add_message = {
                               "SM" : "GSN_SM",
                               "action" : "recvBusReq",
                               "type" : "add",
                               "route" : ROUTE_NO,
                               "direction" : DIRECTION,
                               "busId" : BUS_ID,
                               "location" : Location.getLocation(), 
                               "busIP" : LOCAL_ADDR.ip,
                               "busPort" : LOCAL_ADDR.port
                               }
                # TODO: should use real gsn 
                MessagePasser.directSend(GSN_ADDR.ip, GSN_ADDR.port, add_message)
                
                # pet the watch dog
                WATCHDOG.petWatchdog()
                
                return DriverSM.Init_Waiting
            else:
                # re-send re-elect msg
                LOGGER.info("send re-elect request to GSN, RESEND_ELECT_NUM: %s" % str(RESEND_ELECT_NUM))
                RESEND_ELECT_NUM = RESEND_ELECT_NUM + 1
                RSN_elect_message = {
                                     "SM" : "GSN_SM",
                                     "action" : "recvElecReq",
                                     "busId" : BUS_ID,
                                     "route" : ROUTE_NO,
                                     "direction" : DIRECTION,
                                     "location" : Location.getLocation(),
                                     "busIP" : LOCAL_ADDR.ip,
                                     "busPort" : LOCAL_ADDR.port
                                     }
                MessagePasser.directSend(GSN_ADDR.ip, GSN_ADDR.port, RSN_elect_message)
                
                # pet the watch dog
                WATCHDOG.petWatchdog()
                
                return DriverSM.Init_Waiting
            
            return DriverSM.Init_Waiting
        elif action == DriverAction.turnOff:
            # TODO: do something to shut-down
            RESEND_ELECT_NUM = 0
            WATCHDOG.stopWatchdog()
            return DriverSM.Off
        else:
            # for other illegal action
            # assert 0, "Init_Waiting: invalid action: %s" % str(input)
            pass
    def next(self, input):
        action = map(GSNAction.GSNAction, [input["action"]])[0]
        if action == GSNAction.recvUserReq:
            # TODO: forward user request to responding RSN
            LOGGER.info("receive user request")
            rsn = getRSNByName(input["route"])

            if rsn != None:
                LOGGER.info("forward user request to RSN")
                rsnAddr = rsn["rsnAddr"]
                request_message = {
                    "SM": "RSN_SM",
                    "action": "recvLocReq",
                    "original": input
                }
                MessagePasser.directSend(rsnAddr.ip, rsnAddr.port,
                                         request_message)
            else:
                LOGGER.info("no rsn running")
                response_message = {
                    "SM": "USER_SM",
                    "action": "recvRes",
                    "location": None,
                    "busId": None,
                    "original": input
                }
                MessagePasser.directSend(input["userIP"], input["userPort"],
                                         response_message)

            return GSNSM.Ready

        elif action == GSNAction.heartBeat:
            LOGGER.info("send heart beat to each RSN")
            global HB_NO
            HB_NO = HB_NO + 1

            hb_message = {"SM": "RSN_SM", "action": "recvGSNHB", "HBNo": HB_NO}

            for route in ROUTE_TABLE:
                MessagePasser.directSend(ROUTE_TABLE[route]["rsnAddr"].ip,
                                         ROUTE_TABLE[route]["rsnAddr"].port,
                                         hb_message)

            return GSNSM.Ready

        elif action == GSNAction.recvHBRes:
            LOGGER.info("receive HB response")

            global ROUTE_TABLE, HB_NO

            # update ROUTE_TABLE
            if input["route"] in ROUTE_TABLE:
                if input["rsnId"] == ROUTE_TABLE[input["route"]]["rsnId"]:
                    ROUTE_TABLE[input["route"]]["rsnAddr"] = Addr(
                        input["rsnIP"], input["rsnPort"])
                    ROUTE_TABLE[input["route"]]["busTable"] = input["busTable"]
                    ROUTE_TABLE[input["route"]]["last_update"] = input["HBNo"]
                    ROUTE_TABLE[input["route"]]["isElect"] = False
                else:
                    # TODO: the rsnId is not recorded
                    pass
            else:
                # TODO: the route is not recorded.
                pass

            return GSNSM.Ready
        elif action == GSNAction.recvBusReq:
            # TODO: update route table and forward user request to responding RSN
            LOGGER.info("receive bus request")
            rsn = getRSNByName(input["route"])
            # if there is no RSN, assign the request bus as the RSN
            if rsn == None:
                # Qian: some checks: (1) if there is no rsn but receive a remove req
                LOGGER.info("assign new RSN")
                """
                routeTableElm = RouteTableElm(input["route"], 
                                              Addr(input["driverIp"], input["driverPort"]), 
                                              [])
                routeTableElm.busTable.append(BusTableElm(Addr(input["driverIp"], input["driverPort"])))
                """
                route_table_entry = {
                    "rsnId": input["busId"],
                    "rsnAddr": Addr(input["busIP"], input["busPort"]),
                    "busTable": None,
                    "last_update": HB_NO
                }

                ROUTE_TABLE[input["route"]] = route_table_entry
                assign_message = {
                    "SM": "RSN_SM",
                    "action": "recvRSNAssign",
                    "type": "self",
                    "route": input["route"],
                    "original": input,
                    "groupMember": [input["busId"]]
                }

                MessagePasser.directSend(input["busIP"], input["busPort"],
                                         assign_message)
            else:
                # Qian: GSN will just forward it to rsn
                # may change this design
                request_message = {
                    "SM": "RSN_SM",
                    "action": "recvBusChange",
                    "type": input["type"],  # add or remove
                    "route": input["route"],
                    "direction": input["direction"],
                    "location": input["location"],
                    "busId": input["busId"],
                    "busIP": input["busIP"],
                    "busPort": input["busPort"]
                }
                MessagePasser.directSend(rsn["rsnAddr"].ip,
                                         rsn["rsnAddr"].port, request_message)
            return GSNSM.Ready
        elif action == GSNAction.recvElecReq:
            # receive election rsn request for a bus
            LOGGER.info("receive election request")
            global HB_NO

            rsn = getRSNByName(input["route"])

            # check if the rsn is live by checking the time stamp
            if rsn["last_update"] + 1 >= HB_NO:
                # means the RSN is alive, tell the driver to wait or reboot
                if rsn["isElect"] == True:
                    LOGGER.info(
                        "new RSN has been elected, ignore the elect request")
                else:
                    LOGGER.info("RSN is alive, ask the driver to reboot")
                    restart_message = {"SM": "DRIVER_SM", "action": "restart"}
                    MessagePasser.directSend(input["busIP"], input["busPort"],
                                             restart_message)
            else:
                # the RSN is dead, elect a new one, select the bus who sends the request, #with the longest potential running time

                bus_table = rsn["busTable"]
                '''
                rsn_candidate = None
                min_dist = -1
                min_bus_id = -1
                
                for bus in bus_table:
                    dist = int(bus_table[bus]["location"])
                    if min_dist < 0 or dist < min_dist:
                        min_dist = dist
                        rsn_candidate = bus_table[bus]
                        min_bus_id = bus
                '''
                LOGGER.info(
                    "RSN is dead, select a new RSN [%s] for route [%s]" %
                    (input["busId"], input["route"]))

                # explicitly send a message to shut down the previous RSN
                resign_message = {"SM": "RSN_SM", "action": "recvRSNResign"}
                MessagePasser.directSend(rsn["rsnAddr"].ip,
                                         rsn["rsnAddr"].port, resign_message)

                # assign a new RSN
                assign_message = {
                    "SM": "RSN_SM",
                    "action": "recvRSNAssign",
                    "type": "normal",
                    "route": input["route"],
                    "original": None,
                    "busTable": bus_table
                }

                ROUTE_TABLE[input["route"]] = {
                    "rsnId": input["busId"],
                    "rsnAddr": Addr(input["busIP"], input["busPort"]),
                    "busTable": bus_table,
                    "last_update": HB_NO,
                    "isElect": True,
                }

                MessagePasser.directSend(input["busIP"], input["busPort"],
                                         assign_message)

            # TODO: select a bus from the table to be the new rsn, below code just selects the first driver
            '''
            elm.rsnIP = elm.busTable[0]["rsnAddr"].ip
            elm.rsnPort = elm.busTable[0]["rsnAddr"].port
            
            LOGGER.info("send message to new rsn")
            assign_message = {
                              "SM" : "RSN_SM",
                              "action" : "recvRSNAssign",
                              "groupMember" : elm.busTable
                              }
            # TODO: TEST ONLY; gsn should be modified
            MessagePasser.directSend(elm.rsnIP, elm.rsnPort, request_message)
            '''
            return GSNSM.Ready
        elif action == GSNAction.turnOff:
            # TODO: do something to shut-down
            return GSNSM.Off
    def next(self, input):
        action = map(RSNAction.RSNAction, [input["action"]])[0]
        if action == RSNAction.recvLocReq:
            # TODO: lookup the queried bus location and
            # TODO: response to user directly
            global BUS_TABLE, LOC_REQ_NO
            LOGGER.info("received location request: %s" % input)

            # fetch the nearest bus available
            # TODO: this function should be polished
            nearest_bus = None
            nearest_loc = None
            nearest_dist = -1
            for key in BUS_TABLE:
                bus = BUS_TABLE[key]
                if (int(bus["last_update"]) >= int(LOC_REQ_NO) - 1) and (int(
                        bus["last_update"]) <= int(LOC_REQ_NO)):
                    distance = int(input["original"]["location"]) - int(
                        bus["location"])
                    if (nearest_dist < 0
                            or distance < nearest_dist) and distance >= 0:
                        nearest_dist = distance
                        nearest_bus = key
                        nearest_loc = bus["location"]

            response_message = {
                "SM": "USER_SM",
                "action": "recvRes",
                "location": nearest_loc,
                "busId": nearest_bus,
                "original": input["original"]
            }

            MessagePasser.directSend(input["original"]["userIP"],
                                     input["original"]["userPort"],
                                     response_message)

            return RSNSM.Ready
        elif action == RSNAction.askBusLoc:
            # periodically ask each buses' location
            # TODO: triggered by host timer
            global GROUP_MEMBER, RSN_ID, ROUTE_NO, LOCAL_ADDR, LOC_REQ_NO
            LOGGER.info("asking each bus' location %s" % BUS_TABLE.keys())
            LOC_REQ_NO = LOC_REQ_NO + 1  # maybe overflow!!!

            req_loc_message = {
                "SM": "DRIVER_SM",
                "action": "recvLocReq",
                "requestNo": LOC_REQ_NO,
                "rsnId": RSN_ID,
                "route": ROUTE_NO,
                "rsnIP": LOCAL_ADDR.ip,
                "rsnPort": LOCAL_ADDR.port
            }

            #MessagePasser.multicast(GROUP_MEMBER, req_loc_message)
            # TODO: replace the code below with a multicast version

            for member in BUS_TABLE:
                MessagePasser.directSend(BUS_TABLE[member]["addr"].ip,
                                         BUS_TABLE[member]["addr"].port,
                                         req_loc_message)

            return RSNSM.Ready
        elif action == RSNAction.recvDriverLoc:
            # TODO: update local cache
            global BUS_TABLE, ROUTE_NO

            if input["route"] == ROUTE_NO \
                and input["busId"] in BUS_TABLE \
                and input["requestNo"] > BUS_TABLE[input["busId"]]["last_update"]:

                BUS_TABLE[input["busId"]] = {
                    "direction": input["direction"],
                    "location": input["location"],
                    "addr": Addr(input["busIP"], input["busPort"]),
                    "last_update":
                    input["requestNo"]  # TODO: use local time stamp
                }

            return RSNSM.Ready
        elif action == RSNAction.recvBusChange:
            # TODO: add or remove a bus from current group
            LOGGER.info("Receive bus change request: %s" % input)
            global GROUP_MEMBER, BUS_TABLE, ROUTE_NO, RSN_ID, LOCAL_ADDR, LOC_REQ_NO

            if input["route"] == ROUTE_NO:
                if input["type"] == "add":
                    #if not input["busId"] in BUS_TABLE:
                    #GROUP_MEMBER.append(input["busId"])
                    BUS_TABLE[input["busId"]] = {
                        "direction": input["direction"],
                        "location": input["location"],
                        "addr": Addr(input["busIP"], input["busPort"]),
                        "last_update": LOC_REQ_NO  # TODO: use local time stamp
                    }
                    # send an ACK to driver
                    rsn_ack = {
                        "SM": "DRIVER_SM",
                        "action": "recvRSNAck",
                        "route": ROUTE_NO,
                        "rsnId": RSN_ID,
                        "rsnIP": LOCAL_ADDR.ip,
                        "rsnPort": LOCAL_ADDR.port
                    }
                    MessagePasser.directSend(input["busIP"], input["busPort"],
                                             rsn_ack)
                elif input["type"] == "remove":
                    if input["busId"] in BUS_TABLE:
                        #GROUP_MEMBER.remove(input["busId"])
                        BUS_TABLE.pop(input["busId"])
            return RSNSM.Ready

        elif action == RSNAction.recvGSNHB:
            LOGGER.info("Receive GSN heart beat: %s" % input["HBNo"])

            global BUS_TABLE, RSN_ID, ROUTE_NO, LOCAL_ADDR, GSN_ADDR, LOC_REQ_NO

            # filter out some dead buses
            remove_list = []
            for bus in BUS_TABLE:
                if int(BUS_TABLE[bus]["last_update"]) + 1 < LOC_REQ_NO:
                    remove_list.append(bus)
            for bus in remove_list:
                BUS_TABLE.pop(bus)

            # send current route table to GSN
            HB_res_message = {
                "SM": "GSN_SM",
                "action": "recvHBRes",
                "HBNo": input["HBNo"],
                "rsnId": RSN_ID,
                "route": ROUTE_NO,
                "rsnIP": LOCAL_ADDR.ip,
                "rsnPort": LOCAL_ADDR.port,
                "busTable": BUS_TABLE
            }
            MessagePasser.directSend(GSN_ADDR.ip, GSN_ADDR.port,
                                     HB_res_message)
            return RSNSM.Ready
        elif action == RSNAction.recvRSNResign:
            LOGGER.info("Receive GSN resign")
            TIMER_OFF.set()
            TIMER_ON.clear()
            return RSNSM.Idle
        elif action == RSNAction.turnOff:
            # TODO: do something to shut-down
            TIMER_OFF.set()
            TIMER_ON.clear()
            return RSNSM.Off
        else:
            # for other illegal action
            # assert 0, "Ready: invalid action: %s" % str(input)
            pass
    def next(self, input):
        action = map(RSNAction.RSNAction, [input["action"]])[0]
        if action == RSNAction.recvRSNAssign:
            # TODO: received the group info from GSN
            # TODO: store the group info

            global LOCAL_ADDR, ROUTE_NO, BUS_TABLE, TIMER_ON, TIMER_OFF
            ROUTE_NO = input["route"]

            # if the RSN is the Driver itself, send a recvRSNAck to driver role
            if input["type"] == "self":
                BUS_TABLE[input["original"]["busId"]] = {
                    "direction":
                    input["original"]["direction"],
                    "location":
                    input["original"]["location"],
                    "addr":
                    Addr(input["original"]["busIP"],
                         input["original"]["busPort"]),
                    "last_update":
                    0  # TODO: use local time stamp
                }

                rsn_ack = {
                    "SM": "DRIVER_SM",
                    "action": "recvRSNAck",
                    "route": ROUTE_NO,
                    "rsnId": RSN_ID,
                    "rsnIP": LOCAL_ADDR.ip,
                    "rsnPort": LOCAL_ADDR.port
                }
                MessagePasser.directSend(input["original"]["busIP"],
                                         input["original"]["busPort"], rsn_ack)
            elif input["type"] == "normal":
                BUS_TABLE = input["busTable"]

                if BUS_TABLE == None:
                    BUS_TABLE = {}
                # reset all time stampes
                for bus in BUS_TABLE:
                    BUS_TABLE[bus]["last_update"] = 0

                # notify each bus
                global GROUP_MEMBER, RSN_ID, ROUTE_NO, LOCAL_ADDR, LOC_REQ_NO
                LOGGER.info("asking each bus' location %s" % BUS_TABLE.keys())
                LOC_REQ_NO = 0
                LOC_REQ_NO = LOC_REQ_NO + 1  # maybe overflow!!!

                req_loc_message = {
                    "SM": "DRIVER_SM",
                    "action": "recvLocReq",
                    "requestNo": LOC_REQ_NO,
                    "rsnId": RSN_ID,
                    "route": ROUTE_NO,
                    "rsnIP": LOCAL_ADDR.ip,
                    "rsnPort": LOCAL_ADDR.port
                }
                for member in BUS_TABLE:
                    MessagePasser.directSend(BUS_TABLE[member]["addr"].ip,
                                             BUS_TABLE[member]["addr"].port,
                                             req_loc_message)

            # unblock the timer thread
            TIMER_OFF.clear()
            TIMER_ON.set()

            return RSNSM.Ready
        elif action == RSNAction.timeout:
            # TODO: re-ping
            # Terry: seems no need to re-ping gsn
            return RSNSM.Idle
        elif action == RSNAction.turnOff:
            global TIMER_ON, TIMER_OFF
            # TODO: do something to shut-down
            TIMER_OFF.set()
            TIMER_ON.clear()
            return RSNSM.Off
        else:
            # for other illegal action
            # assert 0, "Idle: invalid action: %s" % str(input)
            pass