<commit_before>__author__ = 'bernardyuan'
from scapy import all as scapy_all
from scapy import layers as layer

class DlrBase(scapy_all.Packet):
    name = 'DlrBaseClass'
    fields_desc = [
        scapy_all.XByteField('Ring_SubType', None),
        scapy_all.XByteField('Ring_Protocol_Version',None),
        scapy_all.ByteEnumField('Frame_Type', None, {
            1: 'Beacon',
            2: 'Neighbor_Request',
            3: 'Neighbor_Response',
            4: 'Link_State',
            5: 'Locate_Fault',
            6: 'Announce',
            7: 'Sign_On',
            8: 'Advertise',
            9: 'Flush_Tables',
            10: 'Learning_Update'
        }),
        scapy_all.ByteField('Source_Port', None),
        scapy_all.IPField('Source_IP', None),
        scapy_all.XIntField('Sequence_ID', None)
    ]

    # def guess_payload_class(self, payload):
    #     if self.Frame_Type == 1:
    #         return DlrBeacon
    #     else :
    #         return scapy_all.Packet.guess_payload_class(self,payload)
    #
    # def do_dissect_payload(self, s):
    #     cls = self.guess_payload_class(s)
    #     p = cls(s)
    #     self.add_payload(p)

class DlrBeacon(scapy_all.Packet):
    name = 'Beacon'
    fields_desc = [
        scapy_all.ByteEnumField('Ring_State', None, {
            1: 'Ring_Normal_State',
            2: 'Ring_Fault_State'
        }),
        scapy_all.ByteField('Supervisor_Precedence', None),
        scapy_all.ShortField('Beacon_Interval', None),
        scapy_all.ShortField('Beacon_Timeout', None),
        # There are some doubts on the length of this field
        scapy_all.StrLenField('Reserved', '', length_from=None),
    ]
class DlrNeighborRequest(scapy_all.Packet):
    name = 'NeighborRequest'
    fields_desc = [
        scapy_all.XShortField('Ring_SubType', -1),
        scapy_all.XShortField('Ring_Protocol_Version', -1),
        scapy_all.XShortEnumField('Frame_Type', -1, {
            0x01: 'Beacon',
            0x02: 'Neighbor_Reqest',
            0x03: 'Neighbor_Response',
            0x04: 'Link_State',
            0x05: 'Locate_Fault',
            0x06: 'Announce',
            0x07: 'Sign_On',
            0x08: 'Advertise',
            0x09: 'Flush_Tables',
            0x0a: 'Learning_Update'
        }),
        scapy_all.XShortEnumField('Source_Port', -1,{
            0x00: 'Port1_or_Port2',
            0x01: 'Port1',
            0x02: 'Port2'
        }),
        scapy_all.LongField('Source_IP', -1),
        scapy_all.XLongField('Sequence_ID', -1),
        scapy_all.StrLenField('Reserved','',length_from=None)
    ]

class DlrNeighborResponse(scapy_all.Packet):
    name = 'NeighborResponse'
    fields_desc = [
        scapy_all.XShortField('Ring_SubType', -1),
        scapy_all.XShortField('Ring_Protocol_Version', -1),
        scapy_all.XShortEnumField('Frame_Type', -1, {
            0x01: 'Beacon',
            0x02: 'Neighbor_Reqest',
            0x03: 'Neighbor_Response',
            0x04: 'Link_State',
            0x05: 'Locate_Fault',
            0x06: 'Announce',
            0x07: 'Sign_On',
            0x08: 'Advertise',
            0x09: 'Flush_Tables',
            0x0a: 'Learning_Update'
        }),
        scapy_all.XShortEnumField('Source_Port', -1,{
            0x00: 'Port1_or_Port2',
            0x01: 'Port1',
            0x02: 'Port2'
        }),
        scapy_all.LongField('Source_IP', -1),
        scapy_all.XLongField('Sequence_ID', -1),

    ]
class DlrLinkState(scapy_all.Packet):
    name = 'LinkState'
    fields_desc = [
        scapy_all.XShortField('Ring_SubType', -1),
        scapy_all.XShortField('Ring_Protocol_Version', -1),
        scapy_all.XShortEnumField('Frame_Type', -1, {
            0x01: 'Beacon',
            0x02: 'Neighbor_Reqest',
            0x03: 'Neighbor_Response',
            0x04: 'Link_State',
            0x05: 'Locate_Fault',
            0x06: 'Announce',
            0x07: 'Sign_On',
            0x08: 'Advertise',
            0x09: 'Flush_Tables',
            0x0a: 'Learning_Update'
        }),
        scapy_all.XShortEnumField('Source_Port', -1,{
            0x00: 'Port1_or_Port2',
            0x01: 'Port1',
            0x02: 'Port2'
        }),
        scapy_all.LongField('Source_IP', -1),
        scapy_all.XLongField('Sequence_ID', -1),
        scapy_all.XShortField('Link/Neighbor_Status',-1),
        scapy_all.StrLenField('Reserved',''),

    ]

class DlrLocateFault(scapy_all.Packet):
    name = 'LocateFault'
    fields_desc = [
        scapy_all.XShortField('Ring_SubType', -1),
        scapy_all.XShortField('Ring_Protocol_Version', -1),
        scapy_all.XShortEnumField('Frame_Type', -1, {
            0x01: 'Beacon',
            0x02: 'Neighbor_Reqest',
            0x03: 'Neighbor_Response',
            0x04: 'Link_State',
            0x05: 'Locate_Fault',
            0x06: 'Announce',
            0x07: 'Sign_On',
            0x08: 'Advertise',
            0x09: 'Flush_Tables',
            0x0a: 'Learning_Update'
        }),
        scapy_all.XShortEnumField('Source_Port', -1,{
            0x00: 'Port1_or_Port2',
            0x01: 'Port1',
            0x02: 'Port2'
        }),
        scapy_all.LongField('Source_IP', -1),
        scapy_all.XLongField('Sequence_ID', -1),
        scapy_all.StrLenField('Reserved',''),
    ]

class DlrAnnounce(scapy_all.Packet):
    name = 'Announce'
    fields_desc = [
        scapy_all.XShortField('Ring_SubType', -1),
        scapy_all.XShortField('Ring_Protocol_Version', -1),
        scapy_all.XShortEnumField('Frame_Type', -1, {
            0x01: 'Beacon',
            0x02: 'Neighbor_Reqest',
            0x03: 'Neighbor_Response',
            0x04: 'Link_State',
            0x05: 'Locate_Fault',
            0x06: 'Announce',
            0x07: 'Sign_On',
            0x08: 'Advertise',
            0x09: 'Flush_Tables',
            0x0a: 'Learning_Update'
        }),
        scapy_all.XShortEnumField('Source_Port', -1,{
            0x00: 'Port1_or_Port2',
            0x01: 'Port1',
            0x02: 'Port2'
        }),
        scapy_all.LongField('Source_IP', -1),
        scapy_all.XLongField('Sequence_ID', -1),
        scapy_all.XShortEnumField('Ring_State',-1,{
            0X01: 'RING_NORMAL_STATE',
            0x02: 'RING_FAULT_STATE'
        }),
        scapy_all.StrLenField('Reserved','')

    ]

class DlrSignOn(scapy_all.Packet):
    name = 'SignOn'
    fields_desc = [
        scapy_all.XShortField('Ring_SubType', -1),
        scapy_all.XShortField('Ring_Protocol_Version', -1),
        scapy_all.XShortEnumField('Frame_Type', -1, {
            0x01: 'Beacon',
            0x02: 'Neighbor_Reqest',
            0x03: 'Neighbor_Response',
            0x04: 'Link_State',
            0x05: 'Locate_Fault',
            0x06: 'Announce',
            0x07: 'Sign_On',
            0x08: 'Advertise',
            0x09: 'Flush_Tables',
            0x0a: 'Learning_Update'
        }),
        scapy_all.XShortEnumField('Source_Port', -1,{
            0x00: 'Port1_or_Port2',
            0x01: 'Port1',
            0x02: 'Port2'
        }),
        scapy_all.LongField('Source_IP', -1),
        scapy_all.XLongField('Sequence_ID', -1),
        scapy_all.XIntField('Num_nodes',-1),
        # implement with the PacketListField
        # scapy_all.FieldListField('Nodes_Info',None,),

        scapy_all.StrLenField('Reserved','')
    ]

class DlrAdvertise(scapy_all.Packet):
    name = 'Advertise'
    fields_desc = [
        scapy_all.XShortField('Ring_SubType', -1),
        scapy_all.XShortField('Ring_Protocol_Version', -1),
        scapy_all.XShortEnumField('Frame_Type', -1, {
            0x01: 'Beacon',
            0x02: 'Neighbor_Reqest',
            0x03: 'Neighbor_Response',
            0x04: 'Link_State',
            0x05: 'Locate_Fault',
            0x06: 'Announce',
            0x07: 'Sign_On',
            0x08: 'Advertise',
            0x09: 'Flush_Tables',
            0x0a: 'Learning_Update'
        }),
        scapy_all.XShortEnumField('Source_Port', -1,{
            0x00: 'Port1_or_Port2',
            0x01: 'Port1',
            0x02: 'Port2'
        }),
        scapy_all.LongField('Source_IP', -1),
        scapy_all.XLongField('Sequence_ID', -1),

    ]

class DlrFlushTable(scapy_all.Packet):
    name = 'FlushTable'
    fields_desc = [
        scapy_all.XShortField('Ring_SubType', -1),
        scapy_all.XShortField('Ring_Protocol_Version', -1),
        scapy_all.XShortEnumField('Frame_Type', -1, {
            0x01: 'Beacon',
            0x02: 'Neighbor_Reqest',
            0x03: 'Neighbor_Response',
            0x04: 'Link_State',
            0x05: 'Locate_Fault',
            0x06: 'Announce',
            0x07: 'Sign_On',
            0x08: 'Advertise',
            0x09: 'Flush_Tables',
            0x0a: 'Learning_Update'
        }),
        scapy_all.XShortEnumField('Source_Port', -1,{
            0x00: 'Port1_or_Port2',
            0x01: 'Port1',
            0x02: 'Port2'
        }),
        scapy_all.LongField('Source_IP', -1),
        scapy_all.XLongField('Sequence_ID', -1),

    ]

class DlrLearningUpdate(scapy_all.Packet):
    name = 'LearningUpdate'
    fields_desc = [
        scapy_all.XShortField('Ring_SubType', -1),
        scapy_all.XShortField('Ring_Protocol_Version', -1),
        scapy_all.XShortEnumField('Frame_Type', -1, {
            0x01: 'Beacon',
            0x02: 'Neighbor_Reqest',
            0x03: 'Neighbor_Response',
            0x04: 'Link_State',
            0x05: 'Locate_Fault',
            0x06: 'Announce',
            0x07: 'Sign_On',
            0x08: 'Advertise',
            0x09: 'Flush_Tables',
            0x0a: 'Learning_Update'
        }),
        scapy_all.XShortEnumField('Source_Port', -1,{
            0x00: 'Port1_or_Port2',
            0x01: 'Port1',
            0x02: 'Port2'
        }),
        scapy_all.LongField('Source_IP', -1),
        scapy_all.XLongField('Sequence_ID', -1),

    ]

scapy_all.bind_layers(layer.l2.Dot1Q,DlrBase,type=0x80e1)
scapy_all.bind_layers(DlrBase,DlrBeacon,Frame_Type=1)
<commit_msg>black magic half completed<commit_after>__author__ = 'bernardyuan'
from scapy import all as scapy_all
from scapy import layers as layer

class DlrBase(scapy_all.Packet):
    name = 'DlrBaseClass'
    fields_desc = [
        scapy_all.XByteField('Ring_SubType', None),
        scapy_all.XByteField('Ring_Protocol_Version', None),
        scapy_all.ByteEnumField('Frame_Type', None, {
            1: 'Beacon',
            2: 'Neighbor_Request',
            3: 'Neighbor_Response',
            4: 'Link_State',
            5: 'Locate_Fault',
            6: 'Announce',
            7: 'Sign_On',
            8: 'Advertise',
            9: 'Flush_Tables',
            10: 'Learning_Update'
        }),
        scapy_all.ByteField('Source_Port', None),
        scapy_all.IPField('Source_IP', None),
        scapy_all.XIntField('Sequence_ID', None)
    ]

    frames = {
        0: [],
        1: [
            scapy_all.ByteEnumField('Ring_State', None, {
                1: 'Ring_Normal_State',
                2: 'Ring_Fault_State'
            }),
            scapy_all.ByteField('Supervisor_Precedence', None),
            scapy_all.IntField('Beacon_Interval', None),
            scapy_all.IntField('Beacon_Timeout', None),
            # There are some doubts on the length of this field
            # scapy_all.StrLenField('Reserved', '', length_from=None),
        ],
        2: [
            scapy_all.StrLenField('Reserved', '', length_from=None),
        ],
        3: [],
        4: [
            scapy_all.XShortField('Link/Neighbor_Status', -1),
            scapy_all.StrLenField('Reserved', ''),
        ],
        5: [
            scapy_all.StrLenField('Reserved', ''),
        ],
        6: [
            scapy_all.XShortEnumField('Ring_State', -1, {
                0X01: 'RING_NORMAL_STATE',
                0x02: 'RING_FAULT_STATE'
            }),
            scapy_all.StrLenField('Reserved', ''),
        ],
        7: [],
        8: [],
        9: [],
        10: [],
    }

    # def post_dissect(self, s):
    #     flist = self.frames[self.fields['Frame_Type']]
    #     flist.reverse()
    #     while s and flist:
    #         f = flist.pop()
    #         s, fval = f.getfield(self, s)
    #         print f.name + ':' + fval
    #         self.fields[f.name] = fval
    #     return s

    def do_dissect(self, s):
        flist = self.fields_desc[:]
        print flist
        flist.reverse()
        print flist
        raw = s
        while s and flist:
            f = flist.pop()
            s, fval = f.getfield(self, s)
            self.fields[f.name] = fval
            if f.name == 'Frame_Type':
                print fval
                print flist
                flist.reverse()
                print flist
                flist += self.frames[self.fields['Frame_Type']]
                print flist
                flist.reverse()
                print flist

        assert (raw.endswith(s))
        if s:
            self.raw_packet_cache = raw[:-len(s)]
        else:
            self.raw_packet_cache = raw
        self.explicit = 1
        return s

    # def guess_payload_class(self, payload):
    #     if self.Frame_Type == 1:
    #         return DlrBeacon
    #     else:
    #         return scapy_all.Packet.guess_payload_class(self, payload)
    #
    # def do_dissect_payload(self, s):
    #     cls = self.guess_payload_class(s)
    #     p = cls(s, _internal=1, _underlayer=self)
    #     p.add_underlayer(self)
    #     self.add_payload(p)

# class DlrBeacon(scapy_all.Packet):
#     name = 'Beacon'
#     fields_desc = [
#         scapy_all.ByteEnumField('Ring_State', None, {
#             1: 'Ring_Normal_State',
#             2: 'Ring_Fault_State'
#         }),
#         scapy_all.ByteField('Supervisor_Precedence', None),
#         scapy_all.ShortField('Beacon_Interval', None),
#         scapy_all.ShortField('Beacon_Timeout', None),
#         # There are some doubts on the length of this field
#         scapy_all.StrLenField('Reserved', '', length_from=None),
#     ]

# class DlrNeighborRequest(scapy_all.Packet):
#     name = 'NeighborRequest'
#     fields_desc = [
#         scapy_all.XShortField('Ring_SubType', -1),
#         scapy_all.XShortField('Ring_Protocol_Version', -1),
#         scapy_all.XShortEnumField('Frame_Type', -1, {
#             0x01: 'Beacon',
#             0x02: 'Neighbor_Reqest',
#             0x03: 'Neighbor_Response',
#             0x04: 'Link_State',
#             0x05: 'Locate_Fault',
#             0x06: 'Announce',
#             0x07: 'Sign_On',
#             0x08: 'Advertise',
#             0x09: 'Flush_Tables',
#             0x0a: 'Learning_Update'
#         }),
#         scapy_all.XShortEnumField('Source_Port', -1, {
#             0x00: 'Port1_or_Port2',
#             0x01: 'Port1',
#             0x02: 'Port2'
#         }),
#         scapy_all.LongField('Source_IP', -1),
#         scapy_all.XLongField('Sequence_ID', -1),
#         scapy_all.StrLenField('Reserved', '', length_from=None)
#     ]

# class DlrNeighborResponse(scapy_all.Packet):
#     name = 'NeighborResponse'
#     fields_desc = [
#         scapy_all.XShortField('Ring_SubType', -1),
#         scapy_all.XShortField('Ring_Protocol_Version', -1),
#         scapy_all.XShortEnumField('Frame_Type', -1, {
#             0x01: 'Beacon',
#             0x02: 'Neighbor_Reqest',
#             0x03: 'Neighbor_Response',
#             0x04: 'Link_State',
#             0x05: 'Locate_Fault',
#             0x06: 'Announce',
#             0x07: 'Sign_On',
#             0x08: 'Advertise',
#             0x09: 'Flush_Tables',
#             0x0a: 'Learning_Update'
#         }),
#         scapy_all.XShortEnumField('Source_Port', -1, {
#             0x00: 'Port1_or_Port2',
#             0x01: 'Port1',
#             0x02: 'Port2'
#         }),
#         scapy_all.LongField('Source_IP', -1),
#         scapy_all.XLongField('Sequence_ID', -1),
#
#     ]

# class DlrLinkState(scapy_all.Packet):
#     name = 'LinkState'
#     fields_desc = [
#         scapy_all.XShortField('Ring_SubType', -1),
#         scapy_all.XShortField('Ring_Protocol_Version', -1),
#         scapy_all.XShortEnumField('Frame_Type', -1, {
#             0x01: 'Beacon',
#             0x02: 'Neighbor_Reqest',
#             0x03: 'Neighbor_Response',
#             0x04: 'Link_State',
#             0x05: 'Locate_Fault',
#             0x06: 'Announce',
#             0x07: 'Sign_On',
#             0x08: 'Advertise',
#             0x09: 'Flush_Tables',
#             0x0a: 'Learning_Update'
#         }),
#         scapy_all.XShortEnumField('Source_Port', -1, {
#             0x00: 'Port1_or_Port2',
#             0x01: 'Port1',
#             0x02: 'Port2'
#         }),
#         scapy_all.LongField('Source_IP', -1),
#         scapy_all.XLongField('Sequence_ID', -1),
#         scapy_all.XShortField('Link/Neighbor_Status', -1),
#         scapy_all.StrLenField('Reserved', ''),
#
#     ]

# class DlrLocateFault(scapy_all.Packet):
#     name = 'LocateFault'
#     fields_desc = [
#         scapy_all.XShortField('Ring_SubType', -1),
#         scapy_all.XShortField('Ring_Protocol_Version', -1),
#         scapy_all.XShortEnumField('Frame_Type', -1, {
#             0x01: 'Beacon',
#             0x02: 'Neighbor_Reqest',
#             0x03: 'Neighbor_Response',
#             0x04: 'Link_State',
#             0x05: 'Locate_Fault',
#             0x06: 'Announce',
#             0x07: 'Sign_On',
#             0x08: 'Advertise',
#             0x09: 'Flush_Tables',
#             0x0a: 'Learning_Update'
#         }),
#         scapy_all.XShortEnumField('Source_Port', -1, {
#             0x00: 'Port1_or_Port2',
#             0x01: 'Port1',
#             0x02: 'Port2'
#         }),
#         scapy_all.LongField('Source_IP', -1),
#         scapy_all.XLongField('Sequence_ID', -1),
#         scapy_all.StrLenField('Reserved', ''),
#     ]

# class DlrAnnounce(scapy_all.Packet):
#     name = 'Announce'
#     fields_desc = [
#         scapy_all.XShortField('Ring_SubType', -1),
#         scapy_all.XShortField('Ring_Protocol_Version', -1),
#         scapy_all.XShortEnumField('Frame_Type', -1, {
#             0x01: 'Beacon',
#             0x02: 'Neighbor_Reqest',
#             0x03: 'Neighbor_Response',
#             0x04: 'Link_State',
#             0x05: 'Locate_Fault',
#             0x06: 'Announce',
#             0x07: 'Sign_On',
#             0x08: 'Advertise',
#             0x09: 'Flush_Tables',
#             0x0a: 'Learning_Update'
#         }),
#         scapy_all.XShortEnumField('Source_Port', -1, {
#             0x00: 'Port1_or_Port2',
#             0x01: 'Port1',
#             0x02: 'Port2'
#         }),
#         scapy_all.LongField('Source_IP', -1),
#         scapy_all.XLongField('Sequence_ID', -1),
#         scapy_all.XShortEnumField('Ring_State', -1, {
#             0X01: 'RING_NORMAL_STATE',
#             0x02: 'RING_FAULT_STATE'
#         }),
#         scapy_all.StrLenField('Reserved', '')
#
#     ]

class DlrSignOn(scapy_all.Packet):
    name = 'SignOn'
    fields_desc = [
        scapy_all.XShortField('Ring_SubType', -1),
        scapy_all.XShortField('Ring_Protocol_Version', -1),
        scapy_all.XShortEnumField('Frame_Type', -1, {
            0x01: 'Beacon',
            0x02: 'Neighbor_Reqest',
            0x03: 'Neighbor_Response',
            0x04: 'Link_State',
            0x05: 'Locate_Fault',
            0x06: 'Announce',
            0x07: 'Sign_On',
            0x08: 'Advertise',
            0x09: 'Flush_Tables',
            0x0a: 'Learning_Update'
        }),
        scapy_all.XShortEnumField('Source_Port', -1, {
            0x00: 'Port1_or_Port2',
            0x01: 'Port1',
            0x02: 'Port2'
        }),
        scapy_all.LongField('Source_IP', -1),
        scapy_all.XLongField('Sequence_ID', -1),
        scapy_all.XIntField('Num_nodes', -1),
        # implement with the PacketListField
        # scapy_all.FieldListField('Nodes_Info',None,),

        scapy_all.StrLenField('Reserved', '')
    ]

class DlrAdvertise(scapy_all.Packet):
    name = 'Advertise'
    fields_desc = [
        scapy_all.XShortField('Ring_SubType', -1),
        scapy_all.XShortField('Ring_Protocol_Version', -1),
        scapy_all.XShortEnumField('Frame_Type', -1, {
            0x01: 'Beacon',
            0x02: 'Neighbor_Reqest',
            0x03: 'Neighbor_Response',
            0x04: 'Link_State',
            0x05: 'Locate_Fault',
            0x06: 'Announce',
            0x07: 'Sign_On',
            0x08: 'Advertise',
            0x09: 'Flush_Tables',
            0x0a: 'Learning_Update'
        }),
        scapy_all.XShortEnumField('Source_Port', -1, {
            0x00: 'Port1_or_Port2',
            0x01: 'Port1',
            0x02: 'Port2'
        }),
        scapy_all.LongField('Source_IP', -1),
        scapy_all.XLongField('Sequence_ID', -1),

    ]

class DlrFlushTable(scapy_all.Packet):
    name = 'FlushTable'
    fields_desc = [
        scapy_all.XShortField('Ring_SubType', -1),
        scapy_all.XShortField('Ring_Protocol_Version', -1),
        scapy_all.XShortEnumField('Frame_Type', -1, {
            0x01: 'Beacon',
            0x02: 'Neighbor_Reqest',
            0x03: 'Neighbor_Response',
            0x04: 'Link_State',
            0x05: 'Locate_Fault',
            0x06: 'Announce',
            0x07: 'Sign_On',
            0x08: 'Advertise',
            0x09: 'Flush_Tables',
            0x0a: 'Learning_Update'
        }),
        scapy_all.XShortEnumField('Source_Port', -1, {
            0x00: 'Port1_or_Port2',
            0x01: 'Port1',
            0x02: 'Port2'
        }),
        scapy_all.LongField('Source_IP', -1),
        scapy_all.XLongField('Sequence_ID', -1),

    ]

class DlrLearningUpdate(scapy_all.Packet):
    name = 'LearningUpdate'
    fields_desc = [
        scapy_all.XShortField('Ring_SubType', -1),
        scapy_all.XShortField('Ring_Protocol_Version', -1),
        scapy_all.XShortEnumField('Frame_Type', -1, {
            0x01: 'Beacon',
            0x02: 'Neighbor_Reqest',
            0x03: 'Neighbor_Response',
            0x04: 'Link_State',
            0x05: 'Locate_Fault',
            0x06: 'Announce',
            0x07: 'Sign_On',
            0x08: 'Advertise',
            0x09: 'Flush_Tables',
            0x0a: 'Learning_Update'
        }),
        scapy_all.XShortEnumField('Source_Port', -1, {
            0x00: 'Port1_or_Port2',
            0x01: 'Port1',
            0x02: 'Port2'
        }),
        scapy_all.LongField('Source_IP', -1),
        scapy_all.XLongField('Sequence_ID', -1),

    ]

scapy_all.bind_layers(layer.l2.Dot1Q, DlrBase, type=0x80e1)
# scapy_all.bind_layers(DlrBase,DlrBeacon,Frame_Type=1)
<|endoftext|>


<commit_before>'''
    protocol lib for python
    usage:
    >>>
    >>> @protocol
    ... class protocol_1():
    ...     def get_class_name(self):
    ...         return self.__class__.__name__
    ...
    >>> @joint(protocol_1)
    ... class MyClass():
    ...     pass
    ...
    >>> a = MyClass()
    >>> a.get_class_name()
    'MyClass'

    >>>
    >>> from hashlib import MD5
    >>> from time import ctime
    >>>
    >>> @protocol
    ... class protocol_2(ParentClass):
    ...     def func(self, *args, **kwargs):
    ...         pass
    ...

    You can create protocol by inherit, but protocol could not be inherited.
    One protocol can also contain other protocols, which means one protocol
    can be created under other protocols, but protocol itself can not be inherited.

'''
import inspect
from warnings import warn
from IPython.core.debugger import Tracer
set_trace = Tracer()

def get_callables(cls):
    methods = dir(cls)
    return (getattr(cls, m) for m in methods if not m.startswith(
        '_') and callable(getattr(cls, m, None)))

def tuplize(obj):
    ''' Make obj a tuple if it's not a tuple, otherwise just return obj.'''
    return obj if isinstance(obj, tuple) else (obj,)

def listize(obj):
    ''' Make obj a list if it's not a tuple, otherwise just return obj.'''
    return obj if isinstance(obj, list) else [obj, ]

def add_metaclass(metaclass):
    """Class decorator for creating a class with a metaclass."""
    def wrapper(cls):
        orig_vars = cls.__dict__.copy()
        slots = orig_vars.get('__slots__')
        if slots is not None:
            if isinstance(slots, str):
                slots = [slots]
            for slots_var in slots:
                orig_vars.pop(slots_var)
        orig_vars.pop('__dict__', None)
        orig_vars.pop('__weakref__', None)
        return metaclass(cls.__name__, cls.__bases__, orig_vars)
    return wrapper

def protocol(cls):
    p = add_metaclass(ProtocolMeta)(cls)
    p._isprotocol = True
    return p

xxx = None

def joint(*protocols):
    joint.warning = False

    def wrapper(cls):
        cls.__protocols__ = set()

        for protocol in protocols:
            # Only protocols could be jointed
            if not isinstance(protocol, ProtocolMeta):
                raise TypeError('%s is %s, not a protocol' %
                                (protocol, type(protocol)))

            # attach protocol's __protocols__
            cls.__protocols__.update(getattr(protocol, '__protocols__', set()))

            # Here protocol interface could be overrided by other
            # protocols behind, but cls method with same __name__
            # as one of protocol's interface would not be overrided.
            # See detials in test.py
            exist_methods_name = dir(cls)
            for method in protocol.__interface__:
                if method.__name__ not in exist_methods_name:
                    setattr(cls, method.__name__, method)
                    cls.__protocols__.update({protocol})
                else:
                    if not joint.warning:
                        continue

                    exist_method = getattr(cls, method.__name__)
                    warning_string = '''
                    In jointing %s, conflict function name:
                    "%s" with "%s"
                    using the second one above.
                    ''' % (cls, method, exist_method)
                    warn(warning_string)

        cls.get_protocol_hierarchy = classmethod(
            ProtocolMeta.get_protocol_hierarchy)
        return cls
    return wrapper

class InheritException(Exception):

    ''' Could not be inherited.'''

class InstantiationException(Exception):

    ''' Protocols Could not be instantiated.'''

class DuplicateProtocolException(Exception):

    ''' No reason to joint duplicated protocols'''

class ProtocolMeta(type):

    def __new__(cls, name, bases, dct):
        for base in bases:
            if isinstance(base, cls):
                raise InheritException('Could not be inherited from %s' % base)

        name = name if name.startswith('ptl') else ''.join(('ptc', name))
        newclass = super().__new__(cls, name, bases, dct)
        # Maybe the class to create is jointing a protocol
        newclass._isprotocol = False
        # TODO 1:
        newclass.get_protocol_hierarchy = cls.get_protocol_hierarchy
        newclass.__interface__ = get_callables(newclass)

        return newclass

    def __call__(self, *args, **kwargs):
        if self._isprotocol is True:
            raise InstantiationException(
                'Protocols Could not be instantiated.')
        else:
            return super().__call__(*args, **kwargs)

    @staticmethod
    def update_hierarchy(upper, qname_list):

        this_level = qname_list.pop(0)
        level_content = getattr(upper, this_level, [])
        upper.update({this_level, level_content})

        if len(qname_list) == 0:
            return
        return level_content.append(update_hierarchy({}, qname_list))

    # this is classmethod, bounded when newclass bounded
    # @classmethod should not be here
    def get_protocol_hierarchy(cls):
        rslt = {}
        for method in get_callables(cls):
            qname_list = method.__qualname__.split(',')
            owner = qname_list[0]
            if owner != cls.__name__:
                ProtocolMeta.update_hierarchy(rslt, qname_list)

        return rslt

class ProtocolHierarchy():
    @property
    def hierarchy(self):
        return self._hierarchy

    def __setattr__(self, name, value):
        if not isinstance(value, ProtocolHierarchy):
            return

        object.__setattr__(self, name, value)
<commit_msg>Almost no progress, maybe ProtocolHierarchy is not necessary.<commit_after>'''
    protocol lib for python
    usage:
    >>>
    >>> @protocol
    ... class protocol_1():
    ...     def get_class_name(self):
    ...         return self.__class__.__name__
    ...
    >>> @joint(protocol_1)
    ... class MyClass():
    ...     pass
    ...
    >>> a = MyClass()
    >>> a.get_class_name()
    'MyClass'

    >>>
    >>> from hashlib import MD5
    >>> from time import ctime
    >>>
    >>> @protocol
    ... class protocol_2(ParentClass):
    ...     def func(self, *args, **kwargs):
    ...         pass
    ...

    You can create protocol by inherit, but protocol could not be inherited.
    One protocol can also contain other protocols, which means one protocol
    can be created under other protocols, but protocol itself can not be inherited.

'''
import inspect
from warnings import warn
from IPython.core.debugger import Tracer
set_trace = Tracer()

def get_callables(cls):
    methods = dir(cls)
    return (getattr(cls, m) for m in methods if not m.startswith(
        '_') and callable(getattr(cls, m, None)))

def tuplize(obj):
    ''' Make obj a tuple if it's not a tuple, otherwise just return obj.'''
    return obj if isinstance(obj, tuple) else (obj,)

def listize(obj):
    ''' Make obj a list if it's not a tuple, otherwise just return obj.'''
    return obj if isinstance(obj, list) else [obj, ]

def add_metaclass(metaclass):
    """Class decorator for creating a class with a metaclass."""
    def wrapper(cls):
        orig_vars = cls.__dict__.copy()
        slots = orig_vars.get('__slots__')
        if slots is not None:
            if isinstance(slots, str):
                slots = [slots]
            for slots_var in slots:
                orig_vars.pop(slots_var)
        orig_vars.pop('__dict__', None)
        orig_vars.pop('__weakref__', None)
        return metaclass(cls.__name__, cls.__bases__, orig_vars)
    return wrapper

def protocol(cls):
    p = add_metaclass(ProtocolMeta)(cls)
    p._isprotocol = True
    return p

xxx = None

def joint(*protocols):
    joint.warning = False

    def wrapper(cls):
        cls.__protocols__ = set()

        for protocol in protocols:
            # Only protocols could be jointed
            if not isinstance(protocol, ProtocolMeta):
                raise TypeError('%s is %s, not a protocol' %
                                (protocol, type(protocol)))

            # attach protocol's __protocols__
            cls.__protocols__.update(getattr(protocol, '__protocols__', set()))

            # Here protocol interface could be overrided by other
            # protocols behind, but cls method with same __name__
            # as one of protocol's interface would not be overrided.
            # See detials in test.py
            exist_methods_name = dir(cls)
            for method in protocol.__interface__:
                if method.__name__ not in exist_methods_name:
                    setattr(cls, method.__name__, method)
                    cls.__protocols__.update({protocol})
                else:
                    if not joint.warning:
                        continue

                    exist_method = getattr(cls, method.__name__)
                    warning_string = '''
                    In jointing %s, conflict function name:
                    "%s" with "%s"
                    using the second one above.
                    ''' % (cls, method, exist_method)
                    warn(warning_string)

        cls.get_protocol_hierarchy = classmethod(
            ProtocolMeta.get_protocol_hierarchy)
        return cls
    return wrapper

class InheritException(Exception):

    ''' Could not be inherited.'''

class InstantiationException(Exception):

    ''' Protocols Could not be instantiated.'''

class DuplicateProtocolException(Exception):

    ''' No reason to joint duplicated protocols'''

class ProtocolMeta(type):

    def __new__(cls, name, bases, dct):
        for base in bases:
            if isinstance(base, cls):
                raise InheritException('Could not be inherited from %s' % base)

        name = name if name.startswith('ptl') else ''.join(('ptc', name))
        newclass = super().__new__(cls, name, bases, dct)
        # Maybe the class to create is jointing a protocol
        newclass._isprotocol = False
        # TODO 1:
        newclass.get_protocol_hierarchy = cls.get_protocol_hierarchy
        newclass.__interface__ = get_callables(newclass)

        return newclass

    def __call__(self, *args, **kwargs):
        if self._isprotocol is True:
            raise InstantiationException(
                'Protocols Could not be instantiated.')
        else:
            return super().__call__(*args, **kwargs)

    # this is classmethod, bounded when newclass bounded
    # @classmethod should not be here
    def get_protocol_hierarchy(cls):
        hierarchy = ProtocolHierarchy()
        for method in get_callables(cls):
            qname_list = method.__qualname__.split('.')
            owner = qname_list[0]
            # Only jointed function should be stayed here
            if owner == cls.__name__:
                continue
            curr = hierarchy
            for name in qname_list:
                if hasattr(curr, name):
                    curr = getattr(curr, name)
                else:
                    _ = ProtocolHierarchy()
                    setattr(curr, name, _)
                    curr = _

        return hierarchy

class ProtocolHierarchy():

    def __setattr__(self, name, value):
        if not isinstance(value, ProtocolHierarchy):
            return

        object.__setattr__(self, name, value)

    def get_dict(self):
        pass
<|endoftext|>


<commit_before>#!/usr/bin/python
# -*- coding: utf-8 -*-

################################################################################
#
#   RMG - Reaction Mechanism Generator
#
#   Copyright (c) 2002-2010 Prof. William H. Green (whgreen@mit.edu) and the
#   RMG Team (rmg_dev@mit.edu)
#
#   Permission is hereby granted, free of charge, to any person obtaining a
#   copy of this software and associated documentation files (the 'Software'),
#   to deal in the Software without restriction, including without limitation
#   the rights to use, copy, modify, merge, publish, distribute, sublicense,
#   and/or sell copies of the Software, and to permit persons to whom the
#   Software is furnished to do so, subject to the following conditions:
#
#   The above copyright notice and this permission notice shall be included in
#   all copies or substantial portions of the Software.
#
#   THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
#   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
#   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
#   AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
#   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
#   FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
#   DEALINGS IN THE SOFTWARE.
#
################################################################################

import sys
import os.path

from input import load
from output import write_model
from optimization import optimize
from reduction import compute_observables, initialize

from rmgpy.scoop_framework.util import logger as logging

def main():

    inputFile, reductionFile, chemkinFile, spc_dict = sys.argv[-4:]

    for f in [inputFile, reductionFile, chemkinFile, spc_dict]:
        assert os.path.isfile(f), 'Could not find {}'.format(f)

    inputDirectory = os.path.abspath(os.path.dirname(inputFile))
    output_directory = inputDirectory

    rmg, targets, error = load(inputFile, reductionFile, chemkinFile, spc_dict)
    logging.info('Allowed error in target observables: {0:.0f}%'.format(error * 100))

    reactionModel = rmg.reactionModel
    initialize(rmg.outputDirectory, reactionModel.core.reactions)

    atol, rtol = rmg.absoluteTolerance, rmg.relativeTolerance
    index = 0
    reactionSystem = rmg.reactionSystems[index]

    #compute original target observables
    observables = compute_observables(targets, reactionModel, reactionSystem, \
     rmg.absoluteTolerance, rmg.relativeTolerance)

    logger.info('Observables of original model:')
    for target, observable in zip(targets, observables):
        logger.info('{}: {:.2f}%'.format(target, observable * 100))

    # optimize reduction tolerance
    tol, important_reactions = optimize(targets, reactionModel, rmg, index, error, observables)
    logging.info('Optimized tolerance: {:.0E}'.format(10**tol))
    logging.info('Number of reactions in optimized reduced model : {}'.format(len(important_reactions)))

    # plug the important reactions into the RMG object and write:
    rmg.reactionModel.core.reactions = important_reactions
    write_model(rmg)

if __name__ == '__main__':
    main()<commit_msg>create rudimental initializer for logging in reduction main module<commit_after>#!/usr/bin/python
# -*- coding: utf-8 -*-

################################################################################
#
#   RMG - Reaction Mechanism Generator
#
#   Copyright (c) 2002-2010 Prof. William H. Green (whgreen@mit.edu) and the
#   RMG Team (rmg_dev@mit.edu)
#
#   Permission is hereby granted, free of charge, to any person obtaining a
#   copy of this software and associated documentation files (the 'Software'),
#   to deal in the Software without restriction, including without limitation
#   the rights to use, copy, modify, merge, publish, distribute, sublicense,
#   and/or sell copies of the Software, and to permit persons to whom the
#   Software is furnished to do so, subject to the following conditions:
#
#   The above copyright notice and this permission notice shall be included in
#   all copies or substantial portions of the Software.
#
#   THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
#   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
#   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
#   AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
#   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
#   FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
#   DEALINGS IN THE SOFTWARE.
#
################################################################################

import sys
import os.path

from input import load
from output import write_model
from optimization import optimize
from reduction import compute_observables, initialize

from rmgpy.scoop_framework.util import logger

def main():
    level = 20#10 : debug, 20: info
    initializeLog(level)
    inputFile, reductionFile, chemkinFile, spc_dict = sys.argv[-4:]

    for f in [inputFile, reductionFile, chemkinFile, spc_dict]:
        assert os.path.isfile(f), 'Could not find {}'.format(f)

    inputDirectory = os.path.abspath(os.path.dirname(inputFile))
    output_directory = inputDirectory

    rmg, targets, error = load(inputFile, reductionFile, chemkinFile, spc_dict)
    logger.info('Allowed error in target observables: {0:.0f}%'.format(error * 100))

    reactionModel = rmg.reactionModel
    initialize(rmg.outputDirectory, reactionModel.core.reactions)

    atol, rtol = rmg.absoluteTolerance, rmg.relativeTolerance
    index = 0
    reactionSystem = rmg.reactionSystems[index]

    #compute original target observables
    observables = compute_observables(targets, reactionModel, reactionSystem, \
     rmg.absoluteTolerance, rmg.relativeTolerance)

    logger.info('Observables of original model:')
    for target, observable in zip(targets, observables):
        logger.info('{}: {:.2f}%'.format(target, observable * 100))

    # optimize reduction tolerance
    tol, important_reactions = optimize(targets, reactionModel, rmg, index, error, observables)
    logger.info('Optimized tolerance: {:.0E}'.format(10**tol))
    logger.info('Number of reactions in optimized reduced model : {}'.format(len(important_reactions)))

    # plug the important reactions into the RMG object and write:
    rmg.reactionModel.core.reactions = important_reactions
    write_model(rmg)

def initializeLog(level):
    """
    Set up a logger for reduction to use to print output to stdout. The
    `level` parameter is an integer specifying the amount of log text seen
    at the console; the levels correspond to those of the :data:`logging` module.
    """
    # Create logger
    logger.setLevel(level)

if __name__ == '__main__':
    main()<|endoftext|>


<commit_before>#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
# protocol.py - Bitcoin protocol access for bitnodes.
#
# Copyright (c) 2013 Addy Yeow Chin Heng <ayeowch@gmail.com>
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
# "Software"), to deal in the Software without restriction, including
# without limitation the rights to use, copy, modify, merge, publish,
# distribute, sublicense, and/or sell copies of the Software, and to
# permit persons to whom the Software is furnished to do so, subject to
# the following conditions:
#
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

"""
Bitcoin protocol access for bitnodes.
Reference: https://en.bitcoin.it/wiki/Protocol_specification

---------------------------------------------------------------------
               PACKET STRUCTURE FOR BITCOIN PROTOCOL
                     protocol version >= 70001
---------------------------------------------------------------------
[---MESSAGE---]
[ 4] MAGIC_NUMBER   (\xF9\xBE\xB4\xD9)                      uint32_t
[12] COMMAND                                                char[12]
[ 4] LENGTH         <I ( len(payload) )                     uint32_t
[ 4] CHECKSUM       ( sha256(sha256(payload))[:4] )         uint32_t
[..] PAYLOAD        see below

    [---VERSION_PAYLOAD---]
    [ 4] VERSION        <i                                  int32_t
    [ 8] SERVICES       <Q                                  uint64_t
    [ 8] TIMESTAMP      <q                                  int64_t
    [26] ADDR_RECV
        [ 8] SERVICES   <Q                                  uint64_t
        [16] IP_ADDR
            [12] IPV6   (\x00 * 10 + \xFF * 2)              char[12]
            [ 4] IPV4                                       char[4]
        [ 2] PORT       >H                                  uint16_t
    [26] ADDR_FROM
        [ 8] SERVICES   <Q                                  uint64_t
        [16] IP_ADDR
            [12] IPV6   (\x00 * 10 + \xFF * 2)              char[12]
            [ 4] IPV4                                       char[4]
        [ 2] PORT       >H                                  uint16_t
    [ 8] NONCE          <Q ( random.getrandbits(64) )       uint64_t
    [..] USER_AGENT     variable string
    [ 4] START_HEIGHT   <i                                  int32_t
    [ 1] RELAY          <? (since version >= 70001)         bool

    [---ADDR_PAYLOAD---]
    [..] COUNT          variable integer
    [..] ADDR_LIST      multiple of COUNT (max 1000)
        [ 4] TIMESTAMP  <I                                  uint32_t
        [ 8] SERVICES   <Q                                  uint64_t
        [16] IP_ADDR
            [12] IPV6   (\x00 * 10 + \xFF * 2)              char[12]
            [ 4] IPV4                                       char[4]
        [ 2] PORT       >H                                  uint16_t

    [---PING_PAYLOAD---]
    [ 8] NONCE          <Q ( random.getrandbits(64) )       uint64_t

    [---PONG_PAYLOAD---]
    [ 8] NONCE          <Q (nonce from ping)                uint64_t

---------------------------------------------------------------------

"""

import binascii
import cStringIO
import hashlib
import random
import socket
import struct
import sys
import time

MAGIC_NUMBER = "\xF9\xBE\xB4\xD9"
PROTOCOL_VERSION = 70001
SERVICES = 1
USER_AGENT = "/getaddr.bitnodes.io:0.1/"
START_HEIGHT = 274475
RELAY = 0
DEFAULT_PORT = 8333
MAX_ADDR_COUNT = 1000

SOCKET_BUFSIZE = 8192
SOCKET_TIMEOUT = 15
HEADER_LEN = 24

def sha256(data):
    return hashlib.sha256(data).digest()

class ProtocolError(Exception):
    pass

class HeaderTooShortError(ProtocolError):
    pass

class InvalidMagicNumberError(ProtocolError):
    pass

class PayloadTooShortError(ProtocolError):
    pass

class InvalidPayloadChecksum(ProtocolError):
    pass

class IncompatibleClientError(ProtocolError):
    pass

class Serializer:
    def __init__(self, **config):
        self.user_agent = config.get('user_agent', USER_AGENT)
        self.start_height = config.get('start_height', START_HEIGHT)
        # This is set prior to throwing PayloadTooShortError exception to
        # allow caller to fetch more data over the network.
        self.required_len = 0

    def serialize_msg(self, **kwargs):
        command = kwargs['command']
        msg = [
            MAGIC_NUMBER,
            command + "\x00" * (12 - len(command)),
        ]

        payload = ""
        if command == "version":
            to_addr = kwargs['to_addr']
            from_addr = kwargs['from_addr']
            payload = self.serialize_version_payload(to_addr, from_addr)
        elif command == "ping" or command == "pong":
            nonce = kwargs['nonce']
            payload = self.serialize_ping_payload(nonce)

        msg.extend([
            struct.pack("<I", len(payload)),
            sha256(sha256(payload))[:4],
            payload,
        ])

        msg = ''.join(msg)
        return msg

    def deserialize_msg(self, data):
        msg = {}

        data_len = len(data)
        if data_len < HEADER_LEN:
            raise HeaderTooShortError("got {} of {} bytes".format(
                data_len, HEADER_LEN))

        data = cStringIO.StringIO(data)
        header = data.read(HEADER_LEN)
        msg.update(self.deserialize_header(header))

        if (data_len - HEADER_LEN) < msg['length']:
            self.required_len = HEADER_LEN + msg['length']
            raise PayloadTooShortError("got {} of {} bytes".format(
                data_len, HEADER_LEN + msg['length']))

        payload = data.read(msg['length'])
        computed_checksum = sha256(sha256(payload))[:4]
        if computed_checksum != msg['checksum']:
            raise InvalidPayloadChecksum("{} != {}".format(
                binascii.hexlify(computed_checksum),
                binascii.hexlify(msg['checksum'])))

        if msg['command'] == "version":
            msg.update(self.deserialize_version_payload(payload))
        elif msg['command'] == "addr":
            msg.update(self.deserialize_addr_payload(payload))
        elif msg['command'] == "ping" or msg['command'] == "pong":
            msg.update(self.deserialize_ping_payload(payload))

        return (msg, data.read())

    def deserialize_header(self, data):
        msg = {}
        data = cStringIO.StringIO(data)

        msg['magic_number'] = data.read(4)
        if msg['magic_number'] != MAGIC_NUMBER:
            raise InvalidMagicNumberError("{} != {}".format(
                binascii.hexlify(msg['magic_number']),
                binascii.hexlify(MAGIC_NUMBER)))

        msg['command'] = data.read(12).strip("\x00")
        msg['length'] = struct.unpack("<I", data.read(4))[0]
        msg['checksum'] = data.read(4)

        return msg

    def serialize_version_payload(self, to_addr, from_addr):
        payload = [
            struct.pack("<i", PROTOCOL_VERSION),
            struct.pack("<Q", SERVICES),
            struct.pack("<q", int(time.time())),
            self.serialize_network_address(to_addr),
            self.serialize_network_address(from_addr),
            struct.pack("<Q", random.getrandbits(64)),
            self.serialize_string(self.user_agent),
            struct.pack("<i", self.start_height),
            struct.pack("<?", RELAY),
        ]
        payload = ''.join(payload)
        return payload

    def deserialize_version_payload(self, data):
        msg = {}
        data = cStringIO.StringIO(data)

        msg['version'] = struct.unpack("<i", data.read(4))[0]
        if msg['version'] < PROTOCOL_VERSION:
            raise IncompatibleClientError("{} < {}".format(
                msg['version'], PROTOCOL_VERSION))

        msg['services'] = struct.unpack("<Q", data.read(8))[0]
        msg['timestamp'] = struct.unpack("<q", data.read(8))[0]
        msg['to_addr'] = self.deserialize_network_address(data)
        msg['from_addr'] = self.deserialize_network_address(data)
        msg['nonce'] = struct.unpack("<Q", data.read(8))[0]
        msg['user_agent'] = self.deserialize_string(data)
        msg['start_height'] = struct.unpack("<i", data.read(4))[0]

        try:
            msg['relay'] = struct.unpack("<?", data.read(1))[0]
        except struct.error:
            msg['relay'] = False

        return msg

    def serialize_ping_payload(self, nonce):
        payload = [
            struct.pack("<Q", nonce),
        ]
        payload = ''.join(payload)
        return payload

    def deserialize_ping_payload(self, data):
        msg = {}
        data = cStringIO.StringIO(data)
        msg['nonce'] = struct.unpack("<Q", data.read(8))[0]
        return msg

    def deserialize_addr_payload(self, data):
        msg = {}
        data = cStringIO.StringIO(data)

        msg['count'] = self.deserialize_int(data)
        msg['addr_list'] = []
        for _ in xrange(msg['count']):
            network_address = self.deserialize_network_address(
                data, has_timestamp=True)
            msg['addr_list'].append(network_address)

        return msg

    def serialize_network_address(self, addr):
        (ip_address, port) = addr
        network_address = [struct.pack("<Q", SERVICES)]
        if "." in ip_address:
            # unused (12 bytes) + ipv4 (4 bytes) = ipv4-mapped ipv6 address
            unused = "\x00" * 10 + "\xFF" * 2
            network_address.append(
                unused + socket.inet_pton(socket.AF_INET, ip_address))
        else:
            # ipv6 (16 bytes)
            network_address.append(
                socket.inet_pton(socket.AF_INET6, ip_address))
        network_address.append(struct.pack(">H", port))
        network_address = ''.join(network_address)
        return network_address

    def deserialize_network_address(self, data, has_timestamp=False):
        timestamp = None
        if has_timestamp:
            timestamp = struct.unpack("<I", data.read(4))[0]

        services = struct.unpack("<Q", data.read(8))[0]
        _ipv6 = data.read(12)
        _ipv4 = data.read(4)
        port = struct.unpack(">H", data.read(2))[0]

        ipv6 = socket.inet_ntop(socket.AF_INET6, _ipv6 + _ipv4)
        ipv4 = socket.inet_ntop(socket.AF_INET, _ipv4)

        if ipv4 in ipv6:
            ipv6 = ""  # use ipv4
        else:
            ipv4 = ""  # use ipv6

        return {
            'timestamp': timestamp,
            'services': services,
            'ipv6': ipv6,
            'ipv4': ipv4,
            'port': port,
        }

    def serialize_string(self, data):
        length = len(data)
        if length < 0xFD:
            return chr(length) + data
        elif length <= 0xFFFF:
            return chr(0xFD) + struct.pack("<H", length) + data
        elif length <= 0xFFFFFFFF:
            return chr(0xFE) + struct.pack("<I", length) + data
        return chr(0xFF) + struct.pack("<Q", length) + data

    def deserialize_string(self, data):
        length = self.deserialize_int(data)
        return data.read(length)

    def deserialize_int(self, data):
        length = struct.unpack("<B", data.read(1))[0]
        if length == 0xFD:
            length = struct.unpack("<H", data.read(2))[0]
        elif length == 0xFE:
            length = struct.unpack("<I", data.read(4))[0]
        elif length == 0xFF:
            length = struct.unpack("<Q", data.read(8))[0]
        return length

class Connection:
    def __init__(self, to_addr, from_addr=("0.0.0.0", 0), **config):
        if to_addr[1] == 0:
            to_addr = (to_addr[0], DEFAULT_PORT)
        self.to_addr = to_addr
        self.from_addr = from_addr
        self.serializer = Serializer(**config)
        self.socket_timeout = config.get('socket_timeout', SOCKET_TIMEOUT)
        self.socket = None

    def open(self):
        self.socket = socket.create_connection(self.to_addr,
                                               self.socket_timeout)

    def close(self):
        if self.socket:
            self.socket.close()

    def send(self, data):
        self.socket.sendall(data)

    def recv(self, length=0):
        if length > 0:
            data = ""
            while length > 0:
                partial_data = self.socket.recv(SOCKET_BUFSIZE)
                if not partial_data:
                    break  # remote host closed connection
                data += partial_data
                length -= len(partial_data)
        else:
            data = self.socket.recv(SOCKET_BUFSIZE)
        return data

    def handshake(self):
        # [version] >>>
        msg = self.serializer.serialize_msg(
            command="version", to_addr=self.to_addr, from_addr=self.from_addr)
        self.send(msg)

        # <<< [version] [verack]
        msgs = []
        data = self.recv(length=148)  # version (124 bytes) + verack (24 bytes)
        while (len(data) > 0):
            (msg, data) = self.serializer.deserialize_msg(data)
            msgs.append(msg)

        return msgs

    def getaddr(self):
        # [getaddr] >>>
        msg = self.serializer.serialize_msg(command="getaddr")
        self.send(msg)

        # <<< [addr]
        data = self.recv()
        try:
            (msg, data) = self.serializer.deserialize_msg(data)
        except PayloadTooShortError:
            data += self.recv(length=self.serializer.required_len - len(data))
            (msg, data) = self.serializer.deserialize_msg(data)

        return msg

def main():
    to_addr = ("162.243.95.129", 8333)
    handshake_msgs = []
    addr_msg = {}

    connection = Connection(to_addr)
    try:
        connection.open()
        print("open")
        handshake_msgs = connection.handshake()
        print("handshake")
        addr_msg = connection.getaddr()
        print("getaddr")
    except (ProtocolError, socket.error) as err:
        print("{}: {}".format(err, to_addr))
    finally:
        connection.close()
        print("close")

    if len(handshake_msgs) > 0:
        print("{}".format(handshake_msgs))
        if 'addr_list' in addr_msg:
            for idx, addr in enumerate(addr_msg['addr_list'][:10], start=1):
                print("[{}] {}".format(idx, addr))
            print("...")

    return 0

if __name__ == '__main__':
    sys.exit(main())
<commit_msg>Sort handshake responses, i.e. version followed by verack<commit_after>#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
# protocol.py - Bitcoin protocol access for bitnodes.
#
# Copyright (c) 2013 Addy Yeow Chin Heng <ayeowch@gmail.com>
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
# "Software"), to deal in the Software without restriction, including
# without limitation the rights to use, copy, modify, merge, publish,
# distribute, sublicense, and/or sell copies of the Software, and to
# permit persons to whom the Software is furnished to do so, subject to
# the following conditions:
#
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

"""
Bitcoin protocol access for bitnodes.
Reference: https://en.bitcoin.it/wiki/Protocol_specification

---------------------------------------------------------------------
               PACKET STRUCTURE FOR BITCOIN PROTOCOL
                     protocol version >= 70001
---------------------------------------------------------------------
[---MESSAGE---]
[ 4] MAGIC_NUMBER   (\xF9\xBE\xB4\xD9)                      uint32_t
[12] COMMAND                                                char[12]
[ 4] LENGTH         <I ( len(payload) )                     uint32_t
[ 4] CHECKSUM       ( sha256(sha256(payload))[:4] )         uint32_t
[..] PAYLOAD        see below

    [---VERSION_PAYLOAD---]
    [ 4] VERSION        <i                                  int32_t
    [ 8] SERVICES       <Q                                  uint64_t
    [ 8] TIMESTAMP      <q                                  int64_t
    [26] ADDR_RECV
        [ 8] SERVICES   <Q                                  uint64_t
        [16] IP_ADDR
            [12] IPV6   (\x00 * 10 + \xFF * 2)              char[12]
            [ 4] IPV4                                       char[4]
        [ 2] PORT       >H                                  uint16_t
    [26] ADDR_FROM
        [ 8] SERVICES   <Q                                  uint64_t
        [16] IP_ADDR
            [12] IPV6   (\x00 * 10 + \xFF * 2)              char[12]
            [ 4] IPV4                                       char[4]
        [ 2] PORT       >H                                  uint16_t
    [ 8] NONCE          <Q ( random.getrandbits(64) )       uint64_t
    [..] USER_AGENT     variable string
    [ 4] START_HEIGHT   <i                                  int32_t
    [ 1] RELAY          <? (since version >= 70001)         bool

    [---ADDR_PAYLOAD---]
    [..] COUNT          variable integer
    [..] ADDR_LIST      multiple of COUNT (max 1000)
        [ 4] TIMESTAMP  <I                                  uint32_t
        [ 8] SERVICES   <Q                                  uint64_t
        [16] IP_ADDR
            [12] IPV6   (\x00 * 10 + \xFF * 2)              char[12]
            [ 4] IPV4                                       char[4]
        [ 2] PORT       >H                                  uint16_t

    [---PING_PAYLOAD---]
    [ 8] NONCE          <Q ( random.getrandbits(64) )       uint64_t

    [---PONG_PAYLOAD---]
    [ 8] NONCE          <Q (nonce from ping)                uint64_t

---------------------------------------------------------------------

"""

import binascii
import cStringIO
import hashlib
import random
import socket
import struct
import sys
import time

MAGIC_NUMBER = "\xF9\xBE\xB4\xD9"
PROTOCOL_VERSION = 70001
SERVICES = 1
USER_AGENT = "/getaddr.bitnodes.io:0.1/"
START_HEIGHT = 274475
RELAY = 0
DEFAULT_PORT = 8333
MAX_ADDR_COUNT = 1000

SOCKET_BUFSIZE = 8192
SOCKET_TIMEOUT = 15
HEADER_LEN = 24

def sha256(data):
    return hashlib.sha256(data).digest()

class ProtocolError(Exception):
    pass

class HeaderTooShortError(ProtocolError):
    pass

class InvalidMagicNumberError(ProtocolError):
    pass

class PayloadTooShortError(ProtocolError):
    pass

class InvalidPayloadChecksum(ProtocolError):
    pass

class IncompatibleClientError(ProtocolError):
    pass

class Serializer:
    def __init__(self, **config):
        self.user_agent = config.get('user_agent', USER_AGENT)
        self.start_height = config.get('start_height', START_HEIGHT)
        # This is set prior to throwing PayloadTooShortError exception to
        # allow caller to fetch more data over the network.
        self.required_len = 0

    def serialize_msg(self, **kwargs):
        command = kwargs['command']
        msg = [
            MAGIC_NUMBER,
            command + "\x00" * (12 - len(command)),
        ]

        payload = ""
        if command == "version":
            to_addr = kwargs['to_addr']
            from_addr = kwargs['from_addr']
            payload = self.serialize_version_payload(to_addr, from_addr)
        elif command == "ping" or command == "pong":
            nonce = kwargs['nonce']
            payload = self.serialize_ping_payload(nonce)

        msg.extend([
            struct.pack("<I", len(payload)),
            sha256(sha256(payload))[:4],
            payload,
        ])

        msg = ''.join(msg)
        return msg

    def deserialize_msg(self, data):
        msg = {}

        data_len = len(data)
        if data_len < HEADER_LEN:
            raise HeaderTooShortError("got {} of {} bytes".format(
                data_len, HEADER_LEN))

        data = cStringIO.StringIO(data)
        header = data.read(HEADER_LEN)
        msg.update(self.deserialize_header(header))

        if (data_len - HEADER_LEN) < msg['length']:
            self.required_len = HEADER_LEN + msg['length']
            raise PayloadTooShortError("got {} of {} bytes".format(
                data_len, HEADER_LEN + msg['length']))

        payload = data.read(msg['length'])
        computed_checksum = sha256(sha256(payload))[:4]
        if computed_checksum != msg['checksum']:
            raise InvalidPayloadChecksum("{} != {}".format(
                binascii.hexlify(computed_checksum),
                binascii.hexlify(msg['checksum'])))

        if msg['command'] == "version":
            msg.update(self.deserialize_version_payload(payload))
        elif msg['command'] == "addr":
            msg.update(self.deserialize_addr_payload(payload))
        elif msg['command'] == "ping" or msg['command'] == "pong":
            msg.update(self.deserialize_ping_payload(payload))

        return (msg, data.read())

    def deserialize_header(self, data):
        msg = {}
        data = cStringIO.StringIO(data)

        msg['magic_number'] = data.read(4)
        if msg['magic_number'] != MAGIC_NUMBER:
            raise InvalidMagicNumberError("{} != {}".format(
                binascii.hexlify(msg['magic_number']),
                binascii.hexlify(MAGIC_NUMBER)))

        msg['command'] = data.read(12).strip("\x00")
        msg['length'] = struct.unpack("<I", data.read(4))[0]
        msg['checksum'] = data.read(4)

        return msg

    def serialize_version_payload(self, to_addr, from_addr):
        payload = [
            struct.pack("<i", PROTOCOL_VERSION),
            struct.pack("<Q", SERVICES),
            struct.pack("<q", int(time.time())),
            self.serialize_network_address(to_addr),
            self.serialize_network_address(from_addr),
            struct.pack("<Q", random.getrandbits(64)),
            self.serialize_string(self.user_agent),
            struct.pack("<i", self.start_height),
            struct.pack("<?", RELAY),
        ]
        payload = ''.join(payload)
        return payload

    def deserialize_version_payload(self, data):
        msg = {}
        data = cStringIO.StringIO(data)

        msg['version'] = struct.unpack("<i", data.read(4))[0]
        if msg['version'] < PROTOCOL_VERSION:
            raise IncompatibleClientError("{} < {}".format(
                msg['version'], PROTOCOL_VERSION))

        msg['services'] = struct.unpack("<Q", data.read(8))[0]
        msg['timestamp'] = struct.unpack("<q", data.read(8))[0]
        msg['to_addr'] = self.deserialize_network_address(data)
        msg['from_addr'] = self.deserialize_network_address(data)
        msg['nonce'] = struct.unpack("<Q", data.read(8))[0]
        msg['user_agent'] = self.deserialize_string(data)
        msg['start_height'] = struct.unpack("<i", data.read(4))[0]

        try:
            msg['relay'] = struct.unpack("<?", data.read(1))[0]
        except struct.error:
            msg['relay'] = False

        return msg

    def serialize_ping_payload(self, nonce):
        payload = [
            struct.pack("<Q", nonce),
        ]
        payload = ''.join(payload)
        return payload

    def deserialize_ping_payload(self, data):
        msg = {}
        data = cStringIO.StringIO(data)
        msg['nonce'] = struct.unpack("<Q", data.read(8))[0]
        return msg

    def deserialize_addr_payload(self, data):
        msg = {}
        data = cStringIO.StringIO(data)

        msg['count'] = self.deserialize_int(data)
        msg['addr_list'] = []
        for _ in xrange(msg['count']):
            network_address = self.deserialize_network_address(
                data, has_timestamp=True)
            msg['addr_list'].append(network_address)

        return msg

    def serialize_network_address(self, addr):
        (ip_address, port) = addr
        network_address = [struct.pack("<Q", SERVICES)]
        if "." in ip_address:
            # unused (12 bytes) + ipv4 (4 bytes) = ipv4-mapped ipv6 address
            unused = "\x00" * 10 + "\xFF" * 2
            network_address.append(
                unused + socket.inet_pton(socket.AF_INET, ip_address))
        else:
            # ipv6 (16 bytes)
            network_address.append(
                socket.inet_pton(socket.AF_INET6, ip_address))
        network_address.append(struct.pack(">H", port))
        network_address = ''.join(network_address)
        return network_address

    def deserialize_network_address(self, data, has_timestamp=False):
        timestamp = None
        if has_timestamp:
            timestamp = struct.unpack("<I", data.read(4))[0]

        services = struct.unpack("<Q", data.read(8))[0]
        _ipv6 = data.read(12)
        _ipv4 = data.read(4)
        port = struct.unpack(">H", data.read(2))[0]

        ipv6 = socket.inet_ntop(socket.AF_INET6, _ipv6 + _ipv4)
        ipv4 = socket.inet_ntop(socket.AF_INET, _ipv4)

        if ipv4 in ipv6:
            ipv6 = ""  # use ipv4
        else:
            ipv4 = ""  # use ipv6

        return {
            'timestamp': timestamp,
            'services': services,
            'ipv6': ipv6,
            'ipv4': ipv4,
            'port': port,
        }

    def serialize_string(self, data):
        length = len(data)
        if length < 0xFD:
            return chr(length) + data
        elif length <= 0xFFFF:
            return chr(0xFD) + struct.pack("<H", length) + data
        elif length <= 0xFFFFFFFF:
            return chr(0xFE) + struct.pack("<I", length) + data
        return chr(0xFF) + struct.pack("<Q", length) + data

    def deserialize_string(self, data):
        length = self.deserialize_int(data)
        return data.read(length)

    def deserialize_int(self, data):
        length = struct.unpack("<B", data.read(1))[0]
        if length == 0xFD:
            length = struct.unpack("<H", data.read(2))[0]
        elif length == 0xFE:
            length = struct.unpack("<I", data.read(4))[0]
        elif length == 0xFF:
            length = struct.unpack("<Q", data.read(8))[0]
        return length

class Connection:
    def __init__(self, to_addr, from_addr=("0.0.0.0", 0), **config):
        if to_addr[1] == 0:
            to_addr = (to_addr[0], DEFAULT_PORT)
        self.to_addr = to_addr
        self.from_addr = from_addr
        self.serializer = Serializer(**config)
        self.socket_timeout = config.get('socket_timeout', SOCKET_TIMEOUT)
        self.socket = None

    def open(self):
        self.socket = socket.create_connection(self.to_addr,
                                               self.socket_timeout)

    def close(self):
        if self.socket:
            self.socket.close()

    def send(self, data):
        self.socket.sendall(data)

    def recv(self, length=0):
        if length > 0:
            data = ""
            while length > 0:
                partial_data = self.socket.recv(SOCKET_BUFSIZE)
                if not partial_data:
                    break  # remote host closed connection
                data += partial_data
                length -= len(partial_data)
        else:
            data = self.socket.recv(SOCKET_BUFSIZE)
        return data

    def handshake(self):
        # [version] >>>
        msg = self.serializer.serialize_msg(
            command="version", to_addr=self.to_addr, from_addr=self.from_addr)
        self.send(msg)

        # <<< [version] [verack]
        msgs = []
        data = self.recv(length=148)  # version (124 bytes) + verack (24 bytes)
        while (len(data) > 0):
            (msg, data) = self.serializer.deserialize_msg(data)
            msgs.append(msg)
        if len(msgs) > 0:
            msgs = sorted(msgs, key=lambda msg: msg['command'], reverse=True)

        return msgs

    def getaddr(self):
        # [getaddr] >>>
        msg = self.serializer.serialize_msg(command="getaddr")
        self.send(msg)

        # <<< [addr]
        data = self.recv()
        try:
            (msg, data) = self.serializer.deserialize_msg(data)
        except PayloadTooShortError:
            data += self.recv(length=self.serializer.required_len - len(data))
            (msg, data) = self.serializer.deserialize_msg(data)

        return msg

def main():
    to_addr = ("162.243.95.129", 8333)
    handshake_msgs = []
    addr_msg = {}

    connection = Connection(to_addr)
    try:
        connection.open()
        print("open")
        handshake_msgs = connection.handshake()
        print("handshake")
        addr_msg = connection.getaddr()
        print("getaddr")
    except (ProtocolError, socket.error) as err:
        print("{}: {}".format(err, to_addr))
    finally:
        connection.close()
        print("close")

    if len(handshake_msgs) > 0:
        print("{}".format(handshake_msgs))
        if 'addr_list' in addr_msg:
            for idx, addr in enumerate(addr_msg['addr_list'][:10], start=1):
                print("[{}] {}".format(idx, addr))
            print("...")

    return 0

if __name__ == '__main__':
    sys.exit(main())
<|endoftext|>


<commit_before># Copyright 2011 James McCauley
#
# This file is part of POX.
#
# POX is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# POX is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with POX.  If not, see <http://www.gnu.org/licenses/>.

"""
This is the world's simplest OpenFlow learning switch.
"""

from pox.core import core
from pox.lib.addresses import EthAddr
import pox.openflow.libopenflow_01 as of

log = core.getLogger()

def _handle_PacketIn (event):
  packet = event.parsed

  # If we get a packet FROM some src address on some input port, we
  # know that if we want to send TO that address, we should send it
  # out that port.  Install a rule for this.
  msg = of.ofp_flow_mod()
  msg.match.dl_dst = packet.src
  msg.actions.append(of.ofp_action_output(port = event.port))
  event.connection.send(msg)

  # Now since we got a packet at the controller, that must mean
  # that we hadn't installed a rule for the destination address
  # yet -- we don't know where it is.  So, we'll just send the
  # packet out all ports (except the one it came in on!) and
  # hope the destination is out there somewhere. :)
  msg = of.ofp_packet_out()
  msg.actions.append(of.ofp_action_output(port = of.OFPP_FLOOD))
  msg.buffer_id = event.ofp.buffer_id # Resend the incoming packet
  msg.in_port = event.port # Don't flood out the incoming port
  event.connection.send(msg)

def _handle_ConnectionUp (event):
  # Install rule so that broadcast packets just get flooded
  msg = of.ofp_flow_mod()
  msg.match.dl_dst = EthAddr("ff:ff:ff:ff:ff:ff") # Broadcast
  msg.actions.append(of.ofp_action_output(port = of.OFPP_FLOOD))
                                                  # FLOOD means all ports
  event.connection.send(msg)
  log.info("Switch connected.")

def launch ():
  core.openflow.addListenerByName("ConnectionUp", _handle_ConnectionUp)
  core.openflow.addListenerByName("PacketIn", _handle_PacketIn)

  log.info("Learning switch running.")
<commit_msg>forwarding: Fix date on new learning switch<commit_after># Copyright 2012 James McCauley
#
# This file is part of POX.
#
# POX is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# POX is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with POX.  If not, see <http://www.gnu.org/licenses/>.

"""
This is the world's simplest OpenFlow learning switch.
"""

from pox.core import core
from pox.lib.addresses import EthAddr
import pox.openflow.libopenflow_01 as of

log = core.getLogger()

def _handle_PacketIn (event):
  packet = event.parsed

  # If we get a packet FROM some src address on some input port, we
  # know that if we want to send TO that address, we should send it
  # out that port.  Install a rule for this.
  msg = of.ofp_flow_mod()
  msg.match.dl_dst = packet.src
  msg.actions.append(of.ofp_action_output(port = event.port))
  event.connection.send(msg)

  # Now since we got a packet at the controller, that must mean
  # that we hadn't installed a rule for the destination address
  # yet -- we don't know where it is.  So, we'll just send the
  # packet out all ports (except the one it came in on!) and
  # hope the destination is out there somewhere. :)
  msg = of.ofp_packet_out()
  msg.actions.append(of.ofp_action_output(port = of.OFPP_FLOOD))
  msg.buffer_id = event.ofp.buffer_id # Resend the incoming packet
  msg.in_port = event.port # Don't flood out the incoming port
  event.connection.send(msg)

def _handle_ConnectionUp (event):
  # Install rule so that broadcast packets just get flooded
  msg = of.ofp_flow_mod()
  msg.match.dl_dst = EthAddr("ff:ff:ff:ff:ff:ff") # Broadcast
  msg.actions.append(of.ofp_action_output(port = of.OFPP_FLOOD))
                                                  # FLOOD means all ports
  event.connection.send(msg)
  log.info("Switch connected.")

def launch ():
  core.openflow.addListenerByName("ConnectionUp", _handle_ConnectionUp)
  core.openflow.addListenerByName("PacketIn", _handle_PacketIn)

  log.info("Learning switch running.")
<|endoftext|>


<commit_before>"""
The latest version of this package is available at:
<http://github.com/jantman/biweeklybudget>

################################################################################
Copyright 2016 Jason Antman <jason@jasonantman.com> <http://www.jasonantman.com>

    This file is part of biweeklybudget, also known as biweeklybudget.

    biweeklybudget is free software: you can redistribute it and/or modify
    it under the terms of the GNU Affero General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    biweeklybudget is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU Affero General Public License for more details.

    You should have received a copy of the GNU Affero General Public License
    along with biweeklybudget.  If not, see <http://www.gnu.org/licenses/>.

The Copyright and Authors attributions contained herein may not be removed or
otherwise altered, except to add the Author attribution of a contributor to
this work. (Additional Terms pursuant to Section 7b of the AGPL v3)
################################################################################
While not legally required, I sincerely request that anyone who finds
bugs please submit them at <https://github.com/jantman/biweeklybudget> or
to me via email, and that you send any contributions or improvements
either as a pull request on GitHub, or to me via email.
################################################################################

AUTHORS:
Jason Antman <jason@jasonantman.com> <http://www.jasonantman.com>
################################################################################
"""

from flask.views import MethodView
from biweeklybudget.settings import BIWEEKLYBUDGET_TEST_TIMESTAMP
from biweeklybudget.utils import dtnow
from biweeklybudget.flaskapp.app import app

class DateTestJS(MethodView):
    """
    Handle GET /utils/datetest.js endpoint.
    """

    def get(self):
        print(BIWEEKLYBUDGET_TEST_TIMESTAMP)
        if BIWEEKLYBUDGET_TEST_TIMESTAMP is None:
            return 'var BIWEEKLYBUDGET_DEFAULT_DATE = new Date();'
        dt = dtnow()
        return 'var BIWEEKLYBUDGET_DEFAULT_DATE = new Date(%s, %s, %s);' % (
            dt.year, (dt.month - 1), dt.day
        )

app.add_url_rule(
    '/utils/datetest.js',
    view_func=DateTestJS.as_view('date_test_js')
)
<commit_msg>cleanup debugging code<commit_after>"""
The latest version of this package is available at:
<http://github.com/jantman/biweeklybudget>

################################################################################
Copyright 2016 Jason Antman <jason@jasonantman.com> <http://www.jasonantman.com>

    This file is part of biweeklybudget, also known as biweeklybudget.

    biweeklybudget is free software: you can redistribute it and/or modify
    it under the terms of the GNU Affero General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    biweeklybudget is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU Affero General Public License for more details.

    You should have received a copy of the GNU Affero General Public License
    along with biweeklybudget.  If not, see <http://www.gnu.org/licenses/>.

The Copyright and Authors attributions contained herein may not be removed or
otherwise altered, except to add the Author attribution of a contributor to
this work. (Additional Terms pursuant to Section 7b of the AGPL v3)
################################################################################
While not legally required, I sincerely request that anyone who finds
bugs please submit them at <https://github.com/jantman/biweeklybudget> or
to me via email, and that you send any contributions or improvements
either as a pull request on GitHub, or to me via email.
################################################################################

AUTHORS:
Jason Antman <jason@jasonantman.com> <http://www.jasonantman.com>
################################################################################
"""

from flask.views import MethodView
from biweeklybudget.settings import BIWEEKLYBUDGET_TEST_TIMESTAMP
from biweeklybudget.utils import dtnow
from biweeklybudget.flaskapp.app import app

class DateTestJS(MethodView):
    """
    Handle GET /utils/datetest.js endpoint.
    """

    def get(self):
        if BIWEEKLYBUDGET_TEST_TIMESTAMP is None:
            return 'var BIWEEKLYBUDGET_DEFAULT_DATE = new Date();'
        dt = dtnow()
        return 'var BIWEEKLYBUDGET_DEFAULT_DATE = new Date(%s, %s, %s);' % (
            dt.year, (dt.month - 1), dt.day
        )

app.add_url_rule(
    '/utils/datetest.js',
    view_func=DateTestJS.as_view('date_test_js')
)
<|endoftext|>


<commit_before>from ete2 import Nexml, TreeStyle, NodeStyle
import tinycss
import sys
import os

if len(sys.argv) < 2:
    print("Command line argument required: NeXML file")
    exit(-1)

custom_stylesheet = None
if len(sys.argv) > 2:
    if sys.argv[2]:
        custom_stylesheet = sys.argv[2]

nexml = Nexml()
nexml.build_from_file(sys.argv[1])

def build_tree_style(tree):
    # use our simple TSS cascade to prepare an ETE TreeStyle object
    ##import pdb; pdb.set_trace()
    sheets = gather_tss_stylesheets(tree)
    if len(sheets) == 0:
        return None
    ts = TreeStyle()
    for s in sheets:
        ts = apply_stylesheet(stylesheet=s, tree_style=ts)

    # TODO: do this again for NodeStyle objects, applied to node subsets?
    # OR apply a layout function to test each node against TSS selectors?

    return ts

def gather_tss_stylesheets(tree):
    sheets = []
    # if a stylesheet was provided, this is all we should use
    if custom_stylesheet:
        sheets.append(custom_stylesheet)
        return sheets

    # TODO: add any default stylesheet for this tool?

    # add any linked stylesheets in the NeXML file
    # add any embedded stylesheets in the NeXML file
    nexml_doc = tree.nexml_project
    if nexml_doc:
        # TODO: can we retrieve <?xml-stylesheet ... ?> elements?
        pass

    # TODO: add any linked stylesheets just for this tree

    # TODO: add any embedded stylesheets in this tree

    return sheets

# Apply styles to an existing TreeStyle object and return it
def apply_stylesheet(stylesheet, tree_style):
    if (not stylesheet):
        print("Missing stylesheet!")
        return tree_style
    if (not tree_style):
        print("Missing tree_style!")
        return None

    # parse the TSS from its CSS-style syntax
    parser = tinycss.make_parser('page3')
    # load the stylesheet using its path+filename
    stylesheet = os.path.abspath(stylesheet)
    style = parser.parse_stylesheet_file(css_file=stylesheet)
    print("Found %i rules, %i errors" %
       (len(style.rules),len(style.errors)))
    if len(style.errors) > 0:
        for e in style.errors:
            print(e)

    # walk the TSS rules and translate them into TreeStyle properties
    for r in style.rules:
        if r.at_keyword:
            # this is an ImportRule, MediaRule, or the like
            # TODO: support @import, etc?
            print("Unsupported at-rule:")
            print(r)
        else:
            # it's a normal CSS RuleSet
            print("TSS RuleSet:")
            print("  selector: %s" % r.selector.as_css())
            print("  as list:  %s" % repr(r.selector))
            print("  declarations: %s" % r.declarations)

            # TODO: interpret each selector to find targets
            # see https://pythonhosted.org/tinycss/parsing.html

            # TODO: modify the current TreeStyle to reflect its declarations
            # TODO: modify n NodeStyle objects and apply them..?

            #tree_style.mode = 'c'  # circular
            #tree_style.show_leaf_name = False
            #tree_style.show_branch_length = True
    return tree_style

# render a series of SVG files (one for each tree)
for trees in nexml.get_trees():
    tree_index = 0
    for tree in trees.get_tree():
        tree_index += 1
        ts = build_tree_style(tree)
        tree.render("output%d.svg" % tree_index, tree_style=ts)

        # TEMP demo of a NodeStyle object applied to a few nodes
        node_size = 2
        for n in tree.traverse():
            ns = NodeStyle()
            ns["shape"] = "sphere"
            ns["fgcolor"] = "darkred"
            ns["hz_line_type"] = 1
            ns["hz_line_color"] = "#cccccc"
            ns["size"] = node_size
            node_size += 2
            n.set_style(ns);

        # let's try the interactive QT viewer
        tree.show(tree_style=ts)

<commit_msg>Adding per-node hook for TSS styling<commit_after>from ete2 import Nexml, TreeStyle, NodeStyle
import tinycss
import sys
import os

if len(sys.argv) < 2:
    print("Command line argument required: NeXML file")
    exit(-1)

custom_stylesheet = None
if len(sys.argv) > 2:
    if sys.argv[2]:
        custom_stylesheet = sys.argv[2]

nexml = Nexml()
nexml.build_from_file(sys.argv[1])

def build_tree_style(tree):
    # use our simple TSS cascade to prepare an ETE TreeStyle object
    sheets = gather_tss_stylesheets(tree)
    if len(sheets) == 0:
        return None

    # Some styles can be applied to the entire tree
    ts = TreeStyle()
    # For nodes (and other elements?), build an ordered set of TSS rules
    # to apply to each element in our layout function
    node_rules = []

    for s in sheets:
        ts, tss_cascade = apply_stylesheet(
            stylesheet=s,
            tree_style=ts,
            node_rules=node_rules)

    # Use a layout function to test each node against TSS selectors?
    def apply_tss(node):
        node_style = NodeStyle()
        for rule in node_rules:
            # Test this node against each selector
            if test_node_against_selector(node, rule.selector):
                node_style, node = apply_node_rule(rule, node_style, node)
        node.set_style(node_style);
        return node

    # apply this layout function to each node as it's rendered
    ts.layout_fn = apply_tss
    return ts

def test_node_against_selector(node, selector):
    # TODO: Here we can interpret our selectors
    # in the context of a live tree (vs. a DOM)
    return True

def apply_node_rule(rule, node_style, node):
    for style in rule.declarations:
        print(style)
    node_style["shape"] = "sphere"
    node_style["fgcolor"] = "orange"
    node_style["hz_line_type"] = 2
    node_style["hz_line_color"] = "#cc99cc"
    node_style["size"] = 10
    return node_style, node

def gather_tss_stylesheets(tree):
    sheets = []
    # if a stylesheet was provided, this is all we should use
    if custom_stylesheet:
        sheets.append(custom_stylesheet)
        return sheets

    # TODO: add any default stylesheet for this tool?

    # add any linked stylesheets in the NeXML file
    # add any embedded stylesheets in the NeXML file
    nexml_doc = tree.nexml_project
    if nexml_doc:
        # TODO: can we retrieve <?xml-stylesheet ... ?> elements?
        pass

    # TODO: add any linked stylesheets just for this tree

    # TODO: add any embedded stylesheets in this tree

    return sheets

# Apply styles to an existing TreeStyle object and return it
def apply_stylesheet(stylesheet, tree_style, node_rules):
    if (not stylesheet):
        print("Missing stylesheet!")
        return tree_style, node_rules
    if (not tree_style):
        print("Missing tree_style!")
        return None, None

    # parse the TSS from its CSS-style syntax
    parser = tinycss.make_parser('page3')
    # load the stylesheet using its path+filename
    stylesheet = os.path.abspath(stylesheet)
    style = parser.parse_stylesheet_file(css_file=stylesheet)
    print("Found %i rules, %i errors" %
       (len(style.rules),len(style.errors)))
    if len(style.errors) > 0:
        for e in style.errors:
            print(e)

    # walk the TSS rules and translate them into TreeStyle properties
    # or add them to the node_rules collection
    for r in style.rules:
        if r.at_keyword:
            # this is an ImportRule, MediaRule, or the like
            # TODO: support @import, etc?
            print("Unsupported at-rule:")
            print(r)
        else:
            # it's a normal CSS RuleSet
            #print("TSS RuleSet:")
            #print("  selector: %s" % r.selector.as_css())
            #print("  as list:  %s" % repr(r.selector))
            #print("  declarations: %s" % r.declarations)

            # add every rule to node tests
            node_rules.append(r)

            # TODO: interpret its selector to find targets
            # see https://pythonhosted.org/tinycss/parsing.html

            # TODO: modify the current TreeStyle to reflect its declarations
            #tree_style.mode = 'c'  # circular
            #tree_style.show_leaf_name = False
            #tree_style.show_branch_length = True

    return tree_style, node_rules

# render a series of SVG files (one for each tree)
for trees in nexml.get_trees():
    tree_index = 0
    for tree in trees.get_tree():
        tree_index += 1
        ts = build_tree_style(tree)
        tree.render("output%d.svg" % tree_index, tree_style=ts)

        # let's try the interactive QT viewer
        tree.show(tree_style=ts)

<|endoftext|>