def publish_updates():
    global NF_id, variable_id, sending_queue, update_num

    while True:
        update_num += 1
        new_data = makeData(variable_id, update_num)
        NF_log(
            "[OUT] <publish_updates>",
            "making update ({}) for variable_id ({})".format(
                update_num, variable_id))
        msg_len = 1400  # length of pure data each packet should carry
        frag_num = 1  # fragment number
        frag_tot = len(new_data) / msg_len  # Total fragments for the update
        if len(new_data) % msg_len != 0:
            frag_tot += 1
        while frag_tot >= frag_num:
            tmp_msg = new_data[msg_len * (frag_num - 1):msg_len *
                               frag_num]  # data chunk of length = msg_len

            # msg = length(2B)+kind(2B)+Global_ID(2B)+Variable_id(2B)+update_num(2B)+frag_tot(2B)+frag_num(2B)+pure data(nB)
            pub_msg = sp("HHHHHHH",
                         len(tmp_msg) + 14, 2, NF_id, variable_id, update_num,
                         frag_tot, frag_num) + "".join(
                             [sp("c", x) for x in tmp_msg])
            NF_log(
                "[OUT] <publish_updates>",
                "adding publish on variable ({}) sending_queue".format(
                    variable_id))
            sending_queue.append(pub_msg)
            frag_num += 1
        time.sleep(20)
def subscribe_on_variable(NF):  # SUBSCRIBE
    global NF_id, variable_name, var_names_IDs, answer, init_SUB_ID, SUB_ID_ans

    while not init_NF_ID:
        time.sleep(1)

    if NF == 3:
        variables = [
            x for x in sorted(var_names_IDs.keys()) if x != variable_name
        ]
        for i in range(3):
            sub_var_name = variables[i]
            if var_names_IDs[sub_var_name] == 0:
                while not init_SUB_ID:

                    # msg = Data_length(2B)+Kind(2B)+NF_Global_ID(2B)+sub_var(nB)
                    var_init_msg = sp("HHH", 6 + len(sub_var_name), 5,
                                      NF_id) + "".join(
                                          [sp("c", x) for x in sub_var_name])
                    NF_log(
                        "[NF] <subscribe_on_variable>",
                        "INIT SUB_VAR_ID msg made and added to sending_queue")
                    sending_queue.append(var_init_msg)

                    while not answer:  # wait for the answer from the REPLICA controller
                        time.sleep(1)

                    if SUB_ID_ans == "error":  # there is no "variable_id" assigned to that "variable"
                        time.sleep(10)
                        sending_queue.append(var_init_msg)

                    elif SUB_ID_ans == "ok":
                        init_SUB_ID = 1

                NF_log("[INFO] <subscribe_on_variable>", "SUB_VAR_ID : DONE")
                print "[INFO] <subscribe_on_variable> : SUB_VAR_ID : DONE\n"

            print "........... SUBSCRIBE ..........."
            print "Subscribing from < NF > : {} ".format(NF_id)
            print "Subscribing for the variable_NAME < {} >".format(
                sub_var_name)
            print "With the variable_ID < {} >".format(
                var_names_IDs[sub_var_name])
            print "................................."

            # msg = length(2B) + kind(2B) + Global_ID(2B) + variable_id(2B)
            sub_msg = sp("HHHH", 8, 3, NF_id, var_names_IDs[sub_var_name])
            NF_log("subscribe_on_variable", "sub_msg to the NF sending_queue")
            sending_queue.append(sub_msg)
            init_SUB_ID = 0
            answer = 0
            SUB_ID_ans = "-"
def init_NF_MW_publish(NF):
    global NF_names, NF_name, NF_id, variable_names, variable_name, variable_id, init_NF_ID, init_PUB_ID

    NF_name = NF_names[NF]
    variable_name = variable_names[NF]

    # msg = Data length(2B)+Kind(2B)+NF_local_ID(2B)+NF_Global_ID(2B)+NF_NAME(nB)
    init_msg = sp("HHHH", 8 + len(NF_name), 0, 0, 0) + "".join(
        [sp("c", x) for x in NF_name])
    NF_log("[INIT][OUT] <init_NF_MW_publish>",
           "INIT NF_ID msg made and added to sending_queue")
    sending_queue.append(init_msg)
    while not init_NF_ID:
        time.sleep(1)

    print "********* INIT (NF_ID) ***********"
    print "Registered in Middle-Ware"
    print "My NF_ID : global={}".format(NF_id)
    print "**********************************"
    NF_log("[INIT] <init_NF_MW_publish>", "INIT_NF_ID :[DONE]")
    # print "[INIT] <init_NF_MW_publish> INIT_NF_ID :[DONE]\n"

    # msg = Data length(2B)+Kind(2B)+NF_Global_ID(2B)+NF_NAME(nB)
    init_msg = sp("HHH", 6 + len(variable_name), 1, NF_id) + "".join(
        [sp("c", x) for x in variable_name])
    NF_log("[INIT][OUT] <init_NF_MW_publish>",
           "INIT PUB_VAR_ID msg made and added to sending_queue")
    sending_queue.append(init_msg)
    while not init_PUB_ID:
        time.sleep(1)

    print "********* INIT (PUB_ID) **********"
    print "My Publish ID : {}".format(variable_id)
    print "**********************************"
    NF_log("[INIT] <init_NF_MW_publish>", "PUB_VAR_ID :[DONE]")
    # print "[INIT] <init_NF_MW_publish> PUB_VAR_ID :[DONE]\n"

    time.sleep(5)
    publish_updates()
def msg_cleaner_handler():
    global init_NF_ID, init_PUB_ID, received_queue, NF_id, variable_id, variable_name, var_names_IDs, answer, SUB_ID_ans

    current_data = ""  # empty for started
    NF_log("[INIT] <msg_cleaner_handler>", ":[STARTED]")
    print "[INIT] <msg_cleaner_handler> :[STARTED]\n"
    while True:
        try:
            current_data += received_queue.pop(
                0
            )  # pop the first received chunk and add to the remained bytes (if any)

            # more than 2 bytes to know the lenght of the msg AND enough bytes to rebuild a msg
            while (len(current_data) > 2
                   and len(current_data) >= int(su("H", current_data[:2])[0])):
                in_msg = current_data[:int(su("H", current_data[:2])
                                           [0])]  # we extract the msg

                #### INIT NF_ID REPLY => (kind = 0)
                ## Length(2B)+kind(2B)+NF_global_ID(2B)
                if int(
                        su("H", in_msg[2:4])[0]
                ) == 0:  # it is an NF_global_ID reply from the SDN controller
                    init_NF_ID = 1
                    NF_id = int(su("H", in_msg[6:8])[0])  # NF_global_ID
                    NF_log("[IN] <msg_cleaner_handler>",
                           "My NF_ID : global={}".format(NF_id))

                    #### CUT PROCESSED MSG FROM current_data
                    current_data = current_data[int(
                        su("H", current_data[:2])
                        [0]):]  # continue from begining of the next msg

                #### INIT PUB_variable_ID REPLY => (kind = 1)
                ## Length(2B)+kind(2B)+NF_global_ID(2B)
                elif int(
                        su("H", in_msg[2:4])[0]
                ) == 1:  # it is an PUB_variable_ID reply from the SDN controller
                    init_PUB_ID = 1
                    variable_id = int(su("H",
                                         in_msg[6:8])[0])  # PUB_variable_ID
                    var_names_IDs[variable_name] = int(
                        su("H",
                           in_msg[6:8])[0])  # convert and save the Variable_ID
                    NF_log("[IN] <msg_cleaner_handler>",
                           "My Publish variable_ID : {}".format(variable_id))
                    update_num = 0  # initializing

                    #### CUT PROCESSED MSG FROM current_data
                    current_data = current_data[int(
                        su("H", current_data[:2])
                        [0]):]  # continue from begining of the next msg

                #### PUBLISH MSG => (kind = 2)
                ## kind(2B)+variable_id(4B)+update_num(2B)+frag_tot(2B)+frag_num(2B)+DATA(mB)
                elif int(su("H", in_msg[2:4])[0]) == 2:  # it is a publish
                    NF_log(
                        "[IN] <msg_cleaner_handler>",
                        "Received PUBLISH => len({}), kind({})\
                           ".format(
                            su("H", in_msg[:2])[0],
                            msg_kind(int(su("H", in_msg[2:4])[0]))))

                    print "[IN] <msg_cleaner_handler>", "Received PUBLISH => len({}), kind({})\
                          ".format(
                        su("H", in_msg[:2])[0],
                        msg_kind(int(su("H", in_msg[2:4])[0])))

                    # checking if drop mark for "Variable_ID,update_num"
                    if (str(su("H", in_msg[6:8])[0]) + "," +
                            str(su("H", in_msg[8:10])[0])
                        ) not in drop_update.keys():
                        drop_update[str(su("H", in_msg[6:8])[0]) + "," +
                                    str(su("H", in_msg[8:10])
                                        [0])] = 0  # do not drop this update
                        ## making a fake last received packet for the first time
                        global_table_last_frame[int(su(
                            "H", in_msg[6:8])[0])] = [
                                int(su("H", in_msg[8:10])[0]),
                                int(su("H", in_msg[10:12])[0]),
                                int(su("H", in_msg[12:14])[0]) - 1
                            ]
                        tmp_recvd_publishes[int(su("H", in_msg[6:8])[0])] = [
                        ]  # building place for the first msg

                    # there is no drop desicion on this "Variable_ID,update_num"
                    if (drop_update[str(su("H", in_msg[6:8])[0]) + "," +
                                    str(su("H", in_msg[8:10])[0])]) == 0:
                        if global_table_last_frame[int(
                                su("H", in_msg[6:8])[0])][0] == int(
                                    su("H", in_msg[8:10])
                                    [0]):  # from the same update_num
                            if global_table_last_frame[int(
                                    su("H", in_msg[6:8])[0])][2] + 1 == int(
                                        su("H", in_msg[12:14])
                                        [0]):  # we have normal next fragment

                                # appending the pure msg to the temporary list for this update_num of this variable_id
                                tmp_recvd_publishes[int(
                                    su("H",
                                       in_msg[6:8])[0])].append(in_msg[14:])
                                if int(su("H", in_msg[10:12])[0]) == int(
                                        su("H", in_msg[12:14])
                                    [0]):  # last fragment of the update
                                    fileName = "logs/P_recv_" + str(
                                        su("H", in_msg[6:8])
                                        [0])  # making filname for saving data
                                    with open(
                                            fileName, "a"
                                    ) as f:  # open file for external save(DEBUGING)
                                        f.write("".join(
                                            tmp_recvd_publishes[int(
                                                su("H", in_msg[6:8])
                                                [0])]))  # external save
                                    tmp_recvd_publishes[int(
                                        su("H", in_msg[6:8])[0]
                                    )] = [
                                    ]  # cleaning the in_msg for next update

                                    # ready for first fragment of next update
                                    global_table_last_frame[int(
                                        su("H", in_msg[6:8])[0])] = [
                                            int(su("H", in_msg[8:10])[0]) + 1,
                                            0, 0
                                        ]
                            else:  # we have lost fragment/s

                                # puting drop desicion on this "Variable_ID,update_num"
                                # drop_update[str(su("H",in_msg[6:8])[0])+","+str(su("H",in_msg[8:10])[0])] = 1

                                # Data_length(2B)+kind(2B)+Global_ID(2B)+variable_id(2B)+update_num(2B)
                                recover_msg = sp("H", 10) + sp("H", 6) + sp(
                                    "H", NF_id) + in_msg[6:10]
                                sending_queue.append(recover_msg)
                                tmp_recvd_publishes[int(
                                    su("H", in_msg[6:8])[0]
                                )] = [
                                ]  # cleaning the in_msg due to lost fragment
                        elif int(
                                su("H", in_msg[12:14])[0]
                        ) > 1:  # we have lost msg from 2 consequent updates
                            # drop_update[str(su("H",in_msg[6:8])[0])+","+str(su("H",in_msg[8:10])[0])] = 1 # puting drop desicion on this "variable_id,update_num"

                            ## Data_length(2B)+kind(2B)+Global_ID(2B)+variable_id(2B)+previous_update_num(2B)
                            recover_msg = sp("H", 10) + sp("H", 6) + sp(
                                "H", NF_id) + in_msg[6:8] + sp(
                                    "H",
                                    int(su("H", in_msg[8:10])[0]) -
                                    1)  #recover for previous update
                            sending_queue.append(recover_msg)
                            tmp_recvd_publishes[int(
                                su("H", in_msg[6:8])[0]
                            ) - 1] = [
                            ]  # cleaning the in_msg due to lost fragment of previous update

                            ## Data_length(2B)+kind(2B)+Global_ID(2B)+variable_id(2B)+update_num(2B)
                            recover_msg = sp("H", 10) + sp("H", 6) + sp(
                                "H", NF_id) + in_msg[6:10]
                            sending_queue.append(recover_msg)
                            tmp_recvd_publishes[int(su(
                                "H", in_msg[6:8])[0])] = [
                                ]  # cleaning the in_msg due to lost fragment
                    else:
                        tmp_recvd_publishes[int(su("H", in_msg[6:8])[0])] = [
                        ]  # empty the tempory received update because of fragment/s lost

                    #### CUT PROCESSED MSG FROM current_data
                    current_data = current_data[int(
                        su("H", current_data[:2])
                        [0]):]  # continue from begining of the next msg

                #### SUBSCRIBE VARIABLE_ID RESPONSE
                elif int(
                        su("H", in_msg[2:4])[0]
                ) == 5:  # it is a SDN reply to variable_ID request for subscription
                    if int(su("H", in_msg[6:8])[0]) == 0:
                        SUB_ID_ans = "error"
                        NF_log(
                            "msg_cleaner_handler",
                            "UN-SUCCESSFUL VAR_ID_REQ response from the SDN")
                        print "msg_cleaner_handler: UN-SUCCESSFUL VAR_ID_REQ response from the SDN"
                    else:
                        SUB_ID_ans = "ok"
                        var_name = "".join([su("c", x)[0] for x in in_msg[8:]
                                            ])  # the variable_name
                        # print "var_name: ",var_name
                        var_names_IDs[var_name] = int(
                            su("H", in_msg[6:8])
                            [0])  # convert and save the Variable_ID
                        NF_log("msg_cleaner_handler",
                               "SUCCESSFUL VAR_ID_REQ response from the SDN")
                        print "msg_cleaner_handler: SUCCESSFUL VAR_ID_REQ response from the SDN"

                    #### CUT PROCESSED MSG FROM current_data
                    current_data = current_data[int(
                        su("H", current_data[:2])
                        [0]):]  # continue from begining of the next msg
                    answer = 1

        except IndexError:
            time.sleep(1)
            pass
def VNF_sock_data_cleaner_handlr(
    VNF_ID
):  # rebuild the msgs coming from the VNF and send to needed queues in the Middle_Ware
    global VNF_sock_input_queues, VNF_sock_output_queues, VNF_subscriptions
    global VNF_publishes, OUT_2_queue, VNF_local_global_id

    current_data = ""  # empty for started
    print "[INFO] <VNF_sock_data_cleaner_handlr> for VNF({}) :[STARTED]".format(
        VNF_ID)
    mid_log("[INFO] <VNF_sock_data_cleaner_handlr>",
            "for VNF({}) :[STARTED]".format(VNF_ID))
    while True:
        try:
            # pop the first received chunk and add to the remained bytes (if any)
            current_data = current_data + VNF_sock_output_queues[VNF_ID].pop(0)

            # more than 2 bytes to know the lenght of the msg and enough bytes to rebuild a msg
            while (len(current_data) > 2
                   and len(current_data) >= int(su("H", current_data[:2])[0])):
                in_msg = current_data[:int(
                    su("H", current_data[:2])
                    [0])]  # we extract the msg from Data_length(2B)
                mid_log(
                    "[MW][IN]  <VNF_sock_data_cleaner_handlr>",
                    "MSG len({}), kind({})".format(
                        su("H", in_msg[:2])[0],
                        su("H", in_msg[2:4])[0]))
                print "[MW][IN] <VNF_sock_data_cleaner_handlr>  => len({}), kind({})".format(
                    su("H", in_msg[:2])[0],
                    su("H", in_msg[2:4])[0])

                #### INITIALIZING VNF_ID REQUEST
                #### => (kind = 0)
                if int(
                        su("H", in_msg[2:4])[0]
                ) == 0:  # it is an initializing request from the VNF => send to the SDN controller
                    try:
                        ## msg = Data_length(2B)+Kind(2B)+local_ID(2B)+Global_ID(2B)+VNF_NAME(nB)
                        in_msg_tmp = in_msg[2:4] + sp("H", VNF_ID) + in_msg[6:]
                        in_msg_tmp = sp("H", len(in_msg_tmp) + 2) + in_msg_tmp
                        OUT_1_queue.append(in_msg_tmp)

                        #### CUT PROCESSED MSG FROM current_data
                        current_data = current_data[int(
                            su("H", current_data[:2])
                            [0]):]  # continue from begining of the next msg
                    except:
                        raise

                #### PUB_ID, SUB_ID or RECOVER REQUEST
                #### => (kind = 1, 5 and 6)
                elif int(su("H", in_msg[2:4])[0]) in [
                        1, 5, 6
                ]:  # it is an initializing request from the VNF => send to the SDN controller
                    try:
                        ## msg = Data_length(2B)+Kind(2B)+Global_ID(2B)+VNF_NAME(nB)
                        OUT_1_queue.append(in_msg)

                        #### CUT THE PROCESSED MSG FROM current_data
                        current_data = current_data[int(
                            su("H", current_data[:2])
                            [0]):]  # continue from begining of the next msg
                    except:
                        raise

                #### PUBLISH
                #### => (kind = 2)
                elif int(su(
                        "H",
                        in_msg[2:4])[0]) == 2:  # it is a publish msg from VNF
                    try:
                        tmp_var_ID = int(su(
                            "H", in_msg[6:8])[0])  # extracting the Variable_ID

                        ## append var_ID to the published list of the related VNF socket
                        if tmp_var_ID in VNF_subscriptions.keys(
                        ):  # if there is internal subscriptions on this Variable_ID
                            for dest in VNF_subscriptions[tmp_var_ID]:
                                ## msg = Data_length(2B)+Kind(2B)+Local_ID(2B)+Global_ID(4B)+tot_var(2B)
                                msg_copy = copy.deepcopy(in_msg)
                                VNF_sock_input_queues[
                                    VNF_local_global_id.index(dest)].append(
                                        msg_copy)
                        OUT_2_queue.append(in_msg)

                        #### CUT THE PROCESSED MSG FROM current_data
                        current_data = current_data[int(
                            su("H", current_data[:2])
                            [0]):]  # continue from begining of the next msg
                    except:
                        raise

                #### SUBSCRIBE REGISTER
                #### => (kind = 3)
                elif int(su("H", in_msg[2:4])
                         [0]) == 3:  # it is a subscribe-register request
                    if int(
                            su("H", in_msg[6:8])[0]
                    ) not in VNF_subscriptions.keys(
                    ):  # If variable_ID is NOT in VNF_subscription as a key e.g. var_id:[.....] NOT exists
                        VNF_subscriptions[int(su("H", in_msg[6:8])[0])] = [
                            int(su("H", in_msg[4:6])[0])
                        ]  # add VNF_GLOBAL_ID to subscriptions of var_id:[]
                        internal_publish = 0
                        print "[INFO] <VNF_sock_data_cleaner_handlr> check before subscribe in SW"
                        print "VNF_publishes: ", VNF_publishes
                        print "VNF_subscriptions: ", VNF_subscriptions
                        for VNF in VNF_publishes.keys():
                            # check internal registered publishes for the var_id
                            if int(su("H",
                                      in_msg[6:8])[0]) in VNF_publishes[VNF]:
                                internal_publish = 1
                                break
                        if not internal_publish:  # if no internal publish on that var_id exist
                            OUT_2_queue.append(
                                in_msg)  # try to send request to the switch
                    else:  # If variable_ID is in VNF_subscription as a key
                        if int(su(
                                "H",
                                in_msg[4:6])[0]) not in VNF_subscriptions[int(
                                    su("H", in_msg[6:8])
                                    [0])]:  # if VNF_ID is not in the var_id:[]
                            VNF_subscriptions[int(su(
                                "H", in_msg[6:8])[0])].append(
                                    int(su("H", in_msg[4:6])[0])
                                )  # add VNF_ID to subscriptions of var_id

                    #### CUT THE PROCESSED MSG FROM current_data
                    current_data = current_data[int(
                        su("H", current_data[:2])
                        [0]):]  # continue from begining of the next msg

                #### SUBSCRIBE REMOVE
                #### => (KIND = 4)
                elif int(su("H", in_msg[2:4])
                         [0]) == 4:  # it is a subscribe-remove request
                    if (int(su("H",
                               in_msg[6:8])[0]) in VNF_subscriptions.keys()
                            and int(su(
                                "H", in_msg[4:6])[0]) in VNF_subscriptions[int(
                                    su("H", in_msg[6:8])[0])]):
                        VNF_subscriptions[int(su("H", in_msg[6:8])[0])].remove(
                            int(su("H", in_msg[4:6])[0]))
                    if not VNF_subscriptions[int(su("H", in_msg[6:8])[0])]:
                        internal_publish = 0
                        for VNF in VNF_publishes.keys():
                            if VNF_subscriptions[int(
                                    su("H",
                                       in_msg[6:8])[0])] in VNF_publishes[VNF]:
                                internal_publish = 1
                                break
                        if not internal_publish:
                            OUT_2_queue.append(in_msg)
                    #### CUT THE PROCESSED MSG FROM current_data
                    current_data = current_data[int(
                        su("H", current_data[:2])
                        [0]):]  # continue from begining of the next msg

                else:
                    print "WHY? ;)"
        except IndexError:
            time.sleep(1)
            pass
        except:
            raise
def MW_sock_data_cleaner_handlr(MW_ID):
    global MW_sock_input_queues, MW_sock_output_queues
    global nxt_NF_global_id, nxt_variable_global_id
    global NF_pub_global_ids, global_name_NF_id

    current_data = ""  # empty for started
    print "[INFO] <MW_sock_data_cleaner_handlr> for MW({}) :[STARTED]".format(
        MW_ID)
    REPLICA_log("[INFO] <MW_sock_data_cleaner_handlr>",
                "for MW({}) :[STARTED]".format(MW_ID))
    while True:
        try:
            # pop the first received chunk and add to the remained bytes (if any)
            current_data += MW_sock_output_queues[MW_ID].pop(0)

            # more than 2 bytes to know the lenght of the msg and enough bytes to rebuild a msg
            while (len(current_data) > 2
                   and len(current_data) >= int(su("H", current_data[:2])[0])):
                in_msg = current_data[:int(
                    su("H", current_data[:2])
                    [0])]  # we extract the msg from Data_length(2B)
                REPLICA_log(
                    "[MW][IN]  <MW_sock_data_cleaner_handlr>",
                    "MSG len({}), kind({})".format(
                        su("H", in_msg[:2])[0],
                        su("H", in_msg[2:4])[0]))
                print "[MW][IN] <MW_sock_data_cleaner_handlr>  => len({}), kind({})".format(
                    su("H", in_msg[:2])[0],
                    su("H", in_msg[2:4])[0])

                #### INITIALIZING NF_ID REQUEST
                #### => (kind = 0)
                if int(su("H", in_msg[2:4])[0]) == 0:
                    REPLICA_log("[SW][IN] <handle_pkt_REPLICA> ",
                                "INIT_NF_ID request msg received.")
                    print "INIT_NF_ID REQUEST msg received."
                    global_name_NF_id["".join([
                        su("c", x)[0] for x in in_msg[8:]
                    ])] = nxt_NF_global_id  # mapping NF_NAME : NF_ID
                    NF_pub_global_ids[nxt_NF_global_id] = []
                    tmp_msg = in_msg[2:6] + sp("H",
                                               nxt_NF_global_id) + in_msg[8:]
                    tmp_msg = sp("H", len(tmp_msg) + 2) + tmp_msg
                    MW_sock_input_queues[MW_ID].append(tmp_msg)

                    REPLICA_log("[MW][IN] <handle_pkt_REPLICA> ",
                                "INIT_NF_ID reply msg sent.")
                    print "INIT_NF_ID REPLY msg sent."
                    nxt_NF_global_id += 1
                    #### CUT THE PROCESSED MSG FROM current_data
                    current_data = current_data[int(
                        su("H", current_data[:2])
                        [0]):]  # continue from begining of the next msg

                ### INIT PUB_ID MSG
                ### (kind = 1)
                elif int(su("H", in_msg[2:4])[0]) == 1:
                    REPLICA_log("[SW][IN] <handle_pkt_REPLICA> ",
                                "INIT_PUB_ID request msg received.")
                    print "INIT_PUB_ID request msg received."
                    global_name_variable_id["".join([
                        su("c", x)[0] for x in in_msg[6:]
                    ])] = nxt_variable_global_id
                    NF_pub_global_ids[int(su(
                        "H", in_msg[4:6])[0])].append(nxt_variable_global_id)
                    tmp_msg = in_msg[2:6] + sp(
                        "H", nxt_variable_global_id) + in_msg[6:]
                    tmp_msg = sp("H", len(tmp_msg) + 2) + tmp_msg
                    MW_sock_input_queues[MW_ID].append(tmp_msg)

                    REPLICA_log("[SW][IN] <handle_pkt_REPLICA> ",
                                "INIT_PUB_ID reply msg sent.")
                    print "INIT_PUB_ID REPLY msg sent."
                    nxt_variable_global_id += 1
                    #### CUT THE PROCESSED MSG FROM current_data
                    current_data = current_data[int(
                        su("H", current_data[:2])
                        [0]):]  # continue from begining of the next msg

                ### VARIABLE_ID request
                ### (kind = 5)
                elif int(su("H", in_msg[2:4])[0]) == 5:
                    REPLICA_log("[SW][IN] <handle_pkt_REPLICA> ",
                                "Variable_ID request msg received.")
                    print "Variable_ID request msg received."
                    var_name = "".join([su("c", x)[0] for x in in_msg[6:]])
                    if var_name in global_name_variable_id.keys():
                        tmp_msg = in_msg[2:6] + sp(
                            "H",
                            global_name_variable_id[var_name]) + in_msg[6:]
                        tmp_msg = sp("H", len(tmp_msg) + 2) + tmp_msg
                        REPLICA_log("[SW][IN] <handle_pkt_REPLICA> ",
                                    "Variable_ID reply msg sent.")
                        print "Variable_ID reply msg sent."
                    else:
                        tmp_msg = in_msg[2:6] + sp("H", 0) + in_msg[6:]
                        tmp_msg = sp("H", len(tmp_msg) + 2) + tmp_msg
                        REPLICA_log("[SW][IN] <handle_pkt_REPLICA> ",
                                    "Variable_ID reply (ERROR) msg sent.")
                        print "Variable_ID reply (ERROR) msg sent."
                    MW_sock_input_queues[MW_ID].append(tmp_msg)
                    #### CUT THE PROCESSED MSG FROM current_data
                    current_data = current_data[int(
                        su("H", current_data[:2])
                        [0]):]  # continue from begining of the next msg

                ### RECOVER msg
                ### (kind = 6)
                elif int(su("H", in_msg[2:4])[0]) == 6:
                    REPLICA_log("[SW][IN] <handle_pkt_REPLICA> ",
                                "RECOVER msg received.")
                    print "RECOVER msg : "
                    print in_msg
                    #### CUT THE PROCESSED MSG FROM current_data
                    current_data = current_data[int(
                        su("H", current_data[:2])
                        [0]):]  # continue from begining of the next msg
        except:
            time.sleep(1)
            pass
def handle_pkt_REPLICA():
    global recv_REPLICA_sock, send_REPLICA_sock
    global nxt_NF_global_id, nxt_variable_global_id
    global NF_pub_global_ids, global_name_NF_id

    while True:
        msg, msg_address = recv_REPLICA_sock.recvfrom(2048)
        REPLICA_log("\n[SW][IN] <handle_pkt_REPLICA> ", " => len({}), kind({})".format(su("H",msg[:2])[0],msg_kind(int(su("H",msg[2:4])[0]))))
        print "\nGot msg => kind({})".format(msg_kind(int(su("H",msg[2:4])[0])))

        ### INIT NF_ID MSG
        ### (kind = 0)
        if int(su("H",msg[2:4])[0])==0:
            REPLICA_log("[SW][IN] <handle_pkt_REPLICA> ", "INIT_NF_ID request msg received.")
            print  "INIT_NF_ID REQUEST msg received."
            global_name_NF_id["".join([su("c", x)[0] for x in msg[8:]])] = nxt_NF_global_id # mapping NF_NAME : NF_ID
            NF_pub_global_ids[nxt_NF_global_id] = []
            tmp_msg = msg[2:6]+sp("H",nxt_NF_global_id)+msg[8:]
            tmp_msg = sp("H",len(tmp_msg)+2) + tmp_msg
            try:
                dest_addr = (msg_address[0],65432)
                sent = send_REPLICA_sock.sendto(tmp_msg, dest_addr)
            except:
                raise

            REPLICA_log("[SW][IN] <handle_pkt_REPLICA> ", "INIT_NF_ID reply msg sent.")
            print "INIT_NF_ID REPLY msg sent."
            nxt_NF_global_id += 1

        ### INIT PUB_ID MSG
        ### (kind = 1)
        elif int(su("H",msg[2:4])[0])==1:
            REPLICA_log("[SW][IN] <handle_pkt_REPLICA> ", "INIT_PUB_ID request msg received.")
            print "INIT_PUB_ID request msg received."
            global_name_variable_id["".join([su("c", x)[0] for x in msg[6:]])] = nxt_variable_global_id
            NF_pub_global_ids[int(su("H",msg[4:6])[0])].append(nxt_variable_global_id)
            tmp_msg = msg[2:6]+sp("H",nxt_variable_global_id)+msg[6:]
            tmp_msg = sp("H",len(tmp_msg)+2) + tmp_msg
            try:
                dest_addr = (msg_address[0],65432)
                sent = send_REPLICA_sock.sendto(tmp_msg, dest_addr)
            except:
                raise

            REPLICA_log("[SW][IN] <handle_pkt_REPLICA> ", "INIT_PUB_ID reply msg sent.")
            print "INIT_PUB_ID REPLY msg sent."
            nxt_variable_global_id += 1

        ### VARIABLE_ID request
        ### (kind = 5)
        elif int(su("H",msg[2:4])[0])==5:
            REPLICA_log("[SW][IN] <handle_pkt_REPLICA> ","Variable_ID request msg received.")
            print "Variable_ID request msg received."
            var_name = "".join([su("c", x)[0] for x in msg[6:]])
            if var_name in global_name_variable_id.keys():
                tmp_msg = msg[2:6]+sp("H",global_name_variable_id[var_name])+msg[6:]
                tmp_msg = sp("H",len(tmp_msg)+2) + tmp_msg
                REPLICA_log("[SW][IN] <handle_pkt_REPLICA> ","Variable_ID reply msg sent.")
                print "Variable_ID reply msg sent."
            else:
                tmp_msg = msg[2:6]+sp("H", 0)+msg[6:]
                tmp_msg = sp("H",len(tmp_msg)+2) + tmp_msg
                REPLICA_log("[SW][IN] <handle_pkt_REPLICA> ","Variable_ID reply (ERROR) msg sent.")
                print "Variable_ID reply (ERROR) msg sent."
            try:
                dest_addr = (msg_address[0],65432)
                sent = send_REPLICA_sock.sendto(tmp_msg, dest_addr)
            except:
                raise

        ### RECOVER msg
        ### (kind = 6)
        elif int(su("H",msg[2:4])[0])==6:
            REPLICA_log("[SW][IN] <handle_pkt_REPLICA> ", "RECOVER msg received.")
            print "RECOVER msg : \n"
            print msg