# Path: conpot/core/protocol_wrapper.py
# def conpot_protocol(cls):
#     class Wrapper(object):
#         def __init__(self, *args, **kwargs):
#             self.wrapped = cls(*args, **kwargs)
#             self.cls = cls
#             if self.cls.__name__ not in "Proxy":
#                 if self.cls not in core_interface.protocols:
#                     core_interface.protocols[self.cls] = []
# 
#                 core_interface.protocols[self.cls].append(self.wrapped)
# 
#             self.__class__.__name__ = self.cls.__name__
# 
#         def __getattr__(self, name):
#             if name == "handle":
#                 # assuming that handle function from a class is only called when a client tries to connect with an
#                 # enabled protocol, update the last_active (last_attacked attribute)
#                 # FIXME: No handle function in HTTPServer
#                 core_interface.last_active = datetime.now().strftime(
#                     "%b %d %Y - %H:%M:%S"
#                 )
#             return self.wrapped.__getattribute__(name)
# 
#         def __repr__(self):
#             return self.wrapped.__repr__()
# 
#         __doc__ = cls.__doc__
#         __module__ = cls.__module__
# 
#     return Wrapper
# 
# Path: conpot/utils/networking.py
# def get_interface_ip(destination_ip: str):
#     # returns interface ip from socket in case direct udp socket access not possible
#     s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
#     s.connect((destination_ip, 80))
#     socket_ip = s.getsockname()[0]
#     s.close()
#     return socket_ip


import socket
import conpot.core as conpot_core
import logging
from lxml import etree
from gevent.server import DatagramServer
from bacpypes.local.device import LocalDeviceObject
from bacpypes.apdu import APDU
from bacpypes.pdu import PDU
from bacpypes.errors import DecodingError
from conpot.protocols.bacnet.bacnet_app import BACnetApp
from conpot.core.protocol_wrapper import conpot_protocol
from conpot.utils.networking import get_interface_ip

@conpot_protocol
class BacnetServer(object):
    def __init__(self, template, template_directory, args):
        self.dom = etree.parse(template)
        device_info_root = self.dom.xpath("//bacnet/device_info")[0]
        name_key = device_info_root.xpath("./device_name/text()")[0]
        id_key = device_info_root.xpath("./device_identifier/text()")[0]
        vendor_name_key = device_info_root.xpath("./vendor_name/text()")[0]
        vendor_identifier_key = device_info_root.xpath("./vendor_identifier/text()")[0]
        apdu_length_key = device_info_root.xpath("./max_apdu_length_accepted/text()")[0]
        segmentation_key = device_info_root.xpath("./segmentation_supported/text()")[0]

        self.thisDevice = LocalDeviceObject(
            objectName=name_key,
            objectIdentifier=int(id_key),
            maxApduLengthAccepted=int(apdu_length_key),
            segmentationSupported=segmentation_key,
            vendorName=vendor_name_key,
            vendorIdentifier=int(vendor_identifier_key),
        )
        self.bacnet_app = None
        self.server = None  # Initialize later
        logger.info("Conpot Bacnet initialized using the %s template.", template)

    def handle(self, data, address):
        session = conpot_core.get_session(
            "bacnet",
            address[0],
            address[1],

# Path: conpot/core/protocol_wrapper.py
# def conpot_protocol(cls):
#     class Wrapper(object):
#         def __init__(self, *args, **kwargs):
#             self.wrapped = cls(*args, **kwargs)
#             self.cls = cls
#             if self.cls.__name__ not in "Proxy":
#                 if self.cls not in core_interface.protocols:
#                     core_interface.protocols[self.cls] = []
# 
#                 core_interface.protocols[self.cls].append(self.wrapped)
# 
#             self.__class__.__name__ = self.cls.__name__
# 
#         def __getattr__(self, name):
#             if name == "handle":
#                 # assuming that handle function from a class is only called when a client tries to connect with an
#                 # enabled protocol, update the last_active (last_attacked attribute)
#                 # FIXME: No handle function in HTTPServer
#                 core_interface.last_active = datetime.now().strftime(
#                     "%b %d %Y - %H:%M:%S"
#                 )
#             return self.wrapped.__getattribute__(name)
# 
#         def __repr__(self):
#             return self.wrapped.__repr__()
# 
#         __doc__ = cls.__doc__
#         __module__ = cls.__module__
# 
#     return Wrapper
# 
# Path: conpot/utils/networking.py
# def get_interface_ip(destination_ip: str):
#     # returns interface ip from socket in case direct udp socket access not possible
#     s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
#     s.connect((destination_ip, 80))
#     socket_ip = s.getsockname()[0]
#     s.close()
#     return socket_ip


# Path: conpot/protocols/bacnet/bacnet_server.py
import socket
import conpot.core as conpot_core
import logging
from lxml import etree
from gevent.server import DatagramServer
from bacpypes.local.device import LocalDeviceObject
from bacpypes.apdu import APDU
from bacpypes.pdu import PDU
from bacpypes.errors import DecodingError
from conpot.protocols.bacnet.bacnet_app import BACnetApp
from conpot.core.protocol_wrapper import conpot_protocol
from conpot.utils.networking import get_interface_ip


@conpot_protocol
class BacnetServer(object):
    def __init__(self, template, template_directory, args):
        self.dom = etree.parse(template)
        device_info_root = self.dom.xpath("//bacnet/device_info")[0]
        name_key = device_info_root.xpath("./device_name/text()")[0]
        id_key = device_info_root.xpath("./device_identifier/text()")[0]
        vendor_name_key = device_info_root.xpath("./vendor_name/text()")[0]
        vendor_identifier_key = device_info_root.xpath("./vendor_identifier/text()")[0]
        apdu_length_key = device_info_root.xpath("./max_apdu_length_accepted/text()")[0]
        segmentation_key = device_info_root.xpath("./segmentation_supported/text()")[0]

        self.thisDevice = LocalDeviceObject(
            objectName=name_key,
            objectIdentifier=int(id_key),
            maxApduLengthAccepted=int(apdu_length_key),
            segmentationSupported=segmentation_key,
            vendorName=vendor_name_key,
            vendorIdentifier=int(vendor_identifier_key),
        )
        self.bacnet_app = None
        self.server = None  # Initialize later
        logger.info("Conpot Bacnet initialized using the %s template.", template)

    def handle(self, data, address):
        session = conpot_core.get_session(
            "bacnet",
            address[0],
            address[1],

            get_interface_ip(address[0]),