def __init__(self, network):
     self.__network = network
     self._sn_handler = SequenceHandler()
class TransmitHandler(object):
    __network = None

    def __init__(self, network):
        self.__network = network
        self._sn_handler = SequenceHandler()

    def reset(self):
        self._sn_handler.reset()

    def __addEthernetDetails(self):
        eth = Ether()
        src_mac_padding = '%04x' % self.__port.vl_id
        eth.dst = "%s:%s:%s" % (get("MAC_PREFIX_RX"), 
                                                 src_mac_padding[:2], 
                                                 src_mac_padding[2:])
        eth.src = get("MAC_PREFIX_TX") + ":20"
        eth.type = 0x800
        self.__packet = eth

    def __addIpDetails(self):
        port = self.__port
        ip_layer = IP()
        ip_layer.src = port.ip_src if hasattr(port, 'ip_src') else \
            get("TE_IP")

        if hasattr(port, 'dest_ip'):
            port.ip_dst = port.dest_ip
        elif port.ip_dst in ('', None):
            port.ip_dst = get("TR_IP")

        ip_layer.dst = port.ip_dst
        ip_layer.id  = self._sn_handler.nextIpId()
        ip_layer.ttl = 1
        #ip_layer.prot = 0x17
        self.__packet = self.__packet/ip_layer

    def __addUDPDetails(self):
        port = self.__port
        udp_layer = UDP()
        udp_layer.sport = port.udp_src if hasattr(port, 'udp_src') else \
        int(get("TE_UDP"))
        udp_layer.dport = port.udp_dst
        udp_layer.chksum = 0x00
        #udp_layer.len    = len(port.payload)
        self.__packet = self.__packet/udp_layer

    def __addICMP(self):
        port = self.__port
        icmp = ICMP()
        icmp.seq = self._sn_handler.next(port.rx_vl_id)
        self.__packet /= icmp

    def __addSNMP(self):

        oids = self.__port.oids
        varbindlist = [SNMPvarbind(oid = \
                                   ASN1_OID(str(oid).replace("enterprises", \
                                                             "1.3.6.1.4.1"))) \
                                                             for oid in oids]
        if 'next' in self.__port.proto:
            pdu = SNMPnext(varbindlist = varbindlist)
        else:
            pdu = SNMPget(varbindlist = varbindlist)

        snmp_packet = scapy.SNMP(community = "afdxRead", PDU = pdu, version = 0)
        #print "Packet length is ", len(reduce(lambda x,y : 
        #                                      str(x).replace('.', '') + 
        #                                      str(y).replace('.', ''), oids))
        self.__packet /= snmp_packet

    def __addPayload(self):
        if 'SNMP' in self.__port.proto:
            self.__addSNMP()
        else:
            self.__packet /= self.__port.payload

    def __normalize(self):
        port = self.__port
        # any payload size greater than 1472 needs to be fragmented
        # as the its the ethernet limitation
        if (len(port.payload) > 1472 or \
            len(port.payload) > int(port.max_frame_size)):
            self.__packet = self.fragment(self.__packet)
        else:
            self.__packet = [self.__packet]

    def __addPadding(self, packet):
        if packet.haslayer(SNMP):
            payload_length = len(packet[SNMP])
        else:
            payload_length = len(packet[Raw])

        padding = ''
        # the size index 17 is caculated as 60 - (ethHdr + ipHdr + udpHdr) = 18
        # but here we are using the size index as 17 because the last bit will
        # be the sequence number which will be added at 'transmit' function

        if payload_length < 17:
            padding = '\0' * (17 - payload_length)

        if (len(packet) + len(padding)) < 59:
            padding += '\0' * (59 - (len(packet) + len(padding)))

        if hasattr(self.__port, 'sn_func'):
            sn = self.__port.sn_func(self.__port.vl_id)
        else:
            sn = self._sn_handler.next(self.__port.vl_id)
        if sn == 0:
            padding += '\0'
        else:
            padding += ('\\x%02X' % sn).decode('string_escape')

        packet /= Padding(padding)
        return packet

    def __createPacket(self):
        if self.__port == None:
            return
        if (not hasattr(self.__port, 'payload')) or self.__port.payload == None:
            return

        self.__addEthernetDetails()
        self.__addIpDetails()
        if self.__port.proto in ('UDP', 'SNMP', 'SNMPnext'):
            self.__addUDPDetails()
        elif self.__port.proto == 'ICMP':
            self.__addICMP()

        self.__addPayload()
        self.__normalize()

    def change_sequence_number(self, to_seqno, vlId):
        self._sn_handler.change_sn(to_seqno, vlId)

    def transmit(self, port, network = None, send = True):
        def transmit_low(packet, network):
            packet = self.__addPadding(packet)
            packets = []

            try:
                if NETWORK_A in network:
                    packet[Ether].src = get("MAC_PREFIX_TX") + ":20"
                    if send:
                        sendp(packet, iface = get("NETWORK_INTERFACE_A"),
                              verbose = False)
                    else:
                        packets.append(packet)
    
                if NETWORK_B in network:
                    packet[Ether].src = get("MAC_PREFIX_TX") + ":40"
                    if send:
                        sendp(packet, iface = get("NETWORK_INTERFACE_B"),
                              verbose = False)
                    else:
                        packets.append(packet)
            except Exception, ex:
                general_logger.exception(str(ex))
            return packets

        self.__port = port

        self.__createPacket()

        if network == None:
            network = self.__network

        packets = []

        if type(network) == list:
            if len(network) == len(self.__packet):
                for index in range(0, len(network)):
                    network_id = network[index]
                    packet = self.__packet[index]
                    packets += transmit_low(packet, network_id)
        else:
            for packet in self.__packet:
                packets += transmit_low(packet, network)
        if not send:
            return packets