#Embedded file name: ACEStream\Core\NATFirewall\NatCheckMsgHandler.pyo
from time import strftime
from traceback import print_exc
import datetime
import random
import socket
import sys
import thread
from ACEStream.Core.BitTornado.BT1.MessageID import CRAWLER_NATCHECK, CRAWLER_NATTRAVERSAL
from ACEStream.Core.BitTornado.bencode import bencode, bdecode
from ACEStream.Core.NATFirewall.ConnectionCheck import ConnectionCheck
from ACEStream.Core.NATFirewall.NatTraversal import tryConnect, coordinateHolePunching
from ACEStream.Core.Overlay.SecureOverlay import OLPROTO_VER_EIGHTH, OLPROTO_VER_NINETH, SecureOverlay
from ACEStream.Core.Statistics.Crawler import Crawler
from ACEStream.Core.Utilities.utilities import show_permid, show_permid_short
from types import IntType, StringType, ListType, TupleType
from ACEStream.Core.simpledefs import *
DEBUG = False
PEERLIST_LEN = 100

class NatCheckMsgHandler:
    __single = None

    def __init__(self):
        if NatCheckMsgHandler.__single:
            raise RuntimeError, 'NatCheckMsgHandler is singleton'
        NatCheckMsgHandler.__single = self
        self.crawler_reply_callbacks = []
        self._secure_overlay = SecureOverlay.getInstance()
        self.crawler = Crawler.get_instance()
        if self.crawler.am_crawler():
            self._file = open('natcheckcrawler.txt', 'a')
            self._file.write('\n'.join(('# ' + '*' * 80, strftime('%Y/%m/%d %H:%M:%S'), '# Crawler started\n')))
            self._file.flush()
            self._file2 = open('nattraversalcrawler.txt', 'a')
            self._file2.write('\n'.join(('# ' + '*' * 80, strftime('%Y/%m/%d %H:%M:%S'), '# Crawler started\n')))
            self._file2.flush()
            self.peerlist = []
            self.holePunchingIP = socket.gethostbyname(socket.gethostname())
            self.trav = {}
        else:
            self._file = None

    @staticmethod
    def getInstance(*args, **kw):
        if NatCheckMsgHandler.__single is None:
            NatCheckMsgHandler(*args, **kw)
        return NatCheckMsgHandler.__single

    def register(self, launchmany):
        if DEBUG:
            print >> sys.stderr, 'NatCheckMsgHandler: register'
        self.session = launchmany.session
        self.doNatCheckSender = None
        self.registered = True

    def doNatCheck(self, target_permid, selversion, request_callback):
        if selversion < OLPROTO_VER_NINETH:
            if DEBUG:
                print >> sys.stderr, 'NatCheckMsgHandler: ACEStream version too old for NATCHECK: do nothing'
            return False
        if DEBUG:
            print >> sys.stderr, 'NatCheckMsgHandler: do NATCHECK'
        request_callback(CRAWLER_NATCHECK, '', callback=self.doNatCheckCallback)
        return True

    def doNatCheckCallback(self, exc, permid):
        if exc is not None:
            return False
            if DEBUG:
                print >> sys.stderr, 'NATCHECK_REQUEST was sent to', show_permid_short(permid), exc
        self._file.write('; '.join((strftime('%Y/%m/%d %H:%M:%S'),
         'REQUEST',
         show_permid(permid),
         str(self._secure_overlay.get_dns_from_peerdb(permid)),
         '\n')))
        self._file.flush()
        return True

    def gotDoNatCheckMessage(self, sender_permid, selversion, channel_id, payload, reply_callback):
        self.doNatCheckSender = sender_permid
        self.crawler_reply_callbacks.append(reply_callback)
        try:
            if DEBUG:
                print >> sys.stderr, 'NatCheckMsgHandler: start_nat_type_detect()'
            conn_check = ConnectionCheck.getInstance(self.session)
            conn_check.try_start(self.natthreadcb_natCheckReplyCallback)
        except:
            print_exc()
            return False

        return True

    def natthreadcb_natCheckReplyCallback(self, ncr_data):
        if DEBUG:
            print >> sys.stderr, 'NAT type: ', ncr_data
        if self.doNatCheckSender is not None:
            try:
                ncr_msg = bencode(ncr_data)
            except:
                print_exc()
                if DEBUG:
                    print >> sys.stderr, 'error ncr_data:', ncr_data
                return False

            if DEBUG:
                print >> sys.stderr, 'NatCheckMsgHandler:', ncr_data
            for reply_callback in self.crawler_reply_callbacks:
                reply_callback(ncr_msg, callback=self.natCheckReplySendCallback)

            self.crawler_reply_callbacks = []

    def natCheckReplySendCallback(self, exc, permid):
        if DEBUG:
            print >> sys.stderr, 'NATCHECK_REPLY was sent to', show_permid_short(permid), exc
        if exc is not None:
            return False
        return True

    def gotNatCheckReplyMessage(self, permid, selversion, channel_id, channel_data, error, payload, request_callback):
        if error:
            if DEBUG:
                print >> sys.stderr, 'NatCheckMsgHandler: gotNatCheckReplyMessage'
                print >> sys.stderr, 'NatCheckMsgHandler: error', error
            self._file.write('; '.join((strftime('%Y/%m/%d %H:%M:%S'),
             '  REPLY',
             show_permid(permid),
             str(self._secure_overlay.get_dns_from_peerdb(permid)),
             'ERROR(%d)' % error,
             payload,
             '\n')))
            self._file.flush()
        else:
            try:
                recv_data = bdecode(payload)
            except:
                print_exc()
                print >> sys.stderr, 'bad encoded data:', payload
                return False

            try:
                self.validNatCheckReplyMsg(recv_data)
            except RuntimeError as e:
                print >> sys.stderr, e
                return False

            if DEBUG:
                print >> sys.stderr, 'NatCheckMsgHandler: received NAT_CHECK_REPLY message: ', recv_data
            self._file.write('; '.join((strftime('%Y/%m/%d %H:%M:%S'),
             '  REPLY',
             show_permid(permid),
             str(self._secure_overlay.get_dns_from_peerdb(permid)),
             ':'.join([ str(x) for x in recv_data ]),
             '\n')))
            self._file.flush()
            if selversion < OLPROTO_VER_NINETH:
                if DEBUG:
                    print >> sys.stderr, 'NatCheckMsgHandler: ACEStream version too old for NATTRAVERSAL: do nothing'
                return True
            if DEBUG:
                print >> sys.stderr, 'NatCheckMsgHandler: do NATTRAVERSAL'
            if len(self.peerlist) == PEERLIST_LEN:
                del self.peerlist[0]
            self.peerlist.append([permid, recv_data[1], recv_data[2]])
            if DEBUG:
                print >> sys.stderr, 'NatCheckMsgHandler: peerlist length is: ', len(self.peerlist)
            if len(self.peerlist) >= 2:
                self.tryHolePunching()
        return True

    def validNatCheckReplyMsg(self, ncr_data):
        if not type(ncr_data) == ListType:
            raise RuntimeError, 'NatCheckMsgHandler: received data is not valid. It must be a list of parameters.'
            return False
        if not type(ncr_data[0]) == StringType:
            raise RuntimeError, 'NatCheckMsgHandler: received data is not valid. The first element in the list must be a string.'
            return False
        if not type(ncr_data[1]) == IntType:
            raise RuntimeError, 'NatCheckMsgHandler: received data is not valid. The second element in the list must be an integer.'
            return False
        if not type(ncr_data[2]) == IntType:
            raise RuntimeError, 'NatCheckMsgHandler: received data is not valid. The third element in the list must be an integer.'
            return False
        if not type(ncr_data[3]) == StringType:
            raise RuntimeError, 'NatCheckMsgHandler: received data is not valid. The forth element in the list must be a string.'
            return False
        if not type(ncr_data[4]) == IntType:
            raise RuntimeError, 'NatCheckMsgHandler: received data is not valid. The fifth element in the list must be an integer.'
            return False
        if not type(ncr_data[5]) == StringType:
            raise RuntimeError, 'NatCheckMsgHandler: received data is not valid. The sixth element in the list must be a string.'
            return False
        if not type(ncr_data[6]) == IntType:
            raise RuntimeError, 'NatCheckMsgHandler: received data is not valid. The seventh element in the list must be an integer.'
            return False

    def tryHolePunching(self):
        if DEBUG:
            print >> sys.stderr, 'NatCheckMsgHandler: first element in peerlist', self.peerlist[len(self.peerlist) - 1]
            print >> sys.stderr, 'NatCheckMsgHandler: second element in peerlist', self.peerlist[len(self.peerlist) - 2]
        holePunchingPort = random.randrange(3200, 4200, 1)
        holePunchingAddr = (self.holePunchingIP, holePunchingPort)
        peer1 = self.peerlist[len(self.peerlist) - 1]
        peer2 = self.peerlist[len(self.peerlist) - 2]
        request_id = str(show_permid_short(peer1[0]) + show_permid_short(peer2[0]) + str(random.randrange(0, 1000, 1)))
        self.udpConnect(peer1[0], request_id, holePunchingAddr)
        self.udpConnect(peer2[0], request_id, holePunchingAddr)
        self._file2.write('; '.join((strftime('%Y/%m/%d %H:%M:%S'),
         'REQUEST',
         request_id,
         show_permid(peer1[0]),
         str(peer1[1]),
         str(peer1[2]),
         str(self._secure_overlay.get_dns_from_peerdb(peer1[0])),
         show_permid(peer2[0]),
         str(peer2[1]),
         str(peer2[2]),
         str(self._secure_overlay.get_dns_from_peerdb(peer2[0])),
         '\n')))
        self._file2.flush()
        self.trav[request_id] = (None, None)
        thread.start_new_thread(coordinateHolePunching, (peer1, peer2, holePunchingAddr))

    def udpConnect(self, permid, request_id, holePunchingAddr):
        if DEBUG:
            print >> sys.stderr, 'NatCheckMsgHandler: request UDP connection'
        mh_data = request_id + ':' + holePunchingAddr[0] + ':' + str(holePunchingAddr[1])
        if DEBUG:
            print >> sys.stderr, 'NatCheckMsgHandler: udpConnect message is', mh_data
        try:
            mh_msg = bencode(mh_data)
        except:
            print_exc()
            if DEBUG:
                print >> sys.stderr, 'NatCheckMsgHandler: error mh_data:', mh_data
            return False

        self.crawler.send_request(permid, CRAWLER_NATTRAVERSAL, mh_msg, frequency=0, callback=self.udpConnectCallback)
        if DEBUG:
            print >> sys.stderr, 'NatCheckMsgHandler: request for', show_permid_short(permid), 'sent to crawler'

    def udpConnectCallback(self, exc, permid):
        if exc is not None:
            if DEBUG:
                print >> sys.stderr, 'NATTRAVERSAL_REQUEST failed to', show_permid_short(permid), exc
            self._file2.write('; '.join((strftime('%Y/%m/%d %H:%M:%S'),
             'REQUEST FAILED',
             show_permid(permid),
             str(self._secure_overlay.get_dns_from_peerdb(permid)),
             '\n')))
            return False
        if DEBUG:
            print >> sys.stderr, 'NATTRAVERSAL_REQUEST was sent to', show_permid_short(permid), exc
        return True

    def gotUdpConnectRequest(self, permid, selversion, channel_id, mh_msg, reply_callback):
        if DEBUG:
            print >> sys.stderr, 'NatCheckMsgHandler: gotUdpConnectRequest from', show_permid_short(permid)
        try:
            mh_data = bdecode(mh_msg)
        except:
            print_exc()
            print >> sys.stderr, 'NatCheckMsgHandler: bad encoded data:', mh_msg
            return False

        if DEBUG:
            print >> sys.stderr, 'NatCheckMsgHandler: gotUdpConnectRequest is', mh_data
        try:
            request_id, host, port = mh_data.split(':')
        except:
            print_exc()
            print >> sys.stderr, 'NatCheckMsgHandler: error in received data:', mh_data
            return False

        coordinator = (host, int(port))
        if DEBUG:
            print >> sys.stderr, 'NatCheckMsgHandler: coordinator address is', coordinator
        mhr_data = request_id + ':' + tryConnect(coordinator)
        try:
            mhr_msg = bencode(mhr_data)
        except:
            print_exc()
            print >> sys.stderr, 'NatCheckMsgHandler: error in encoding data:', mhr_data
            return False

        reply_callback(mhr_msg, callback=self.udpConnectReplySendCallback)

    def udpConnectReplySendCallback(self, exc, permid):
        if DEBUG:
            print >> sys.stderr, 'NATTRAVERSAL_REPLY was sent to', show_permid_short(permid), exc
        if exc is not None:
            return False
        return True

    def gotUdpConnectReply(self, permid, selversion, channel_id, channel_data, error, mhr_msg, request_callback):
        if DEBUG:
            print >> sys.stderr, 'NatCheckMsgHandler: gotMakeHoleReplyMessage'
        try:
            mhr_data = bdecode(mhr_msg)
        except:
            print_exc()
            print >> sys.stderr, 'NatCheckMsgHandler: bad encoded data:', mhr_msg
            return False

        if DEBUG:
            print >> sys.stderr, 'NatCheckMsgHandler: message is', mhr_data
        try:
            request_id, reply = mhr_data.split(':')
        except:
            print_exc()
            print >> sys.stderr, 'NatCheckMsgHandler: error in received data:', mhr_data
            return False

        if DEBUG:
            print >> sys.stderr, 'NatCheckMsgHandler: request_id is', request_id
        if request_id in self.trav:
            if DEBUG:
                print >> sys.stderr, 'NatCheckMsgHandler: request_id is in the list'
            peer, value = self.trav[request_id]
            if peer == None:
                if DEBUG:
                    print >> sys.stderr, 'NatCheckMsgHandler: first peer reply'
                self.trav[request_id] = ((permid, self._secure_overlay.get_dns_from_peerdb(permid)), reply)
            elif type(peer) == TupleType:
                if DEBUG:
                    print >> sys.stderr, 'NatCheckMsgHandler: second peer reply'
                self._file2.write('; '.join((strftime('%Y/%m/%d %H:%M:%S'),
                 '  REPLY',
                 request_id,
                 show_permid(peer[0]),
                 str(peer[1]),
                 value,
                 show_permid(permid),
                 str(self._secure_overlay.get_dns_from_peerdb(permid)),
                 reply,
                 '\n')))
                del self.trav[request_id]
        self._file2.flush()

2894106329b89c0df0092318a85e1028faf6a4a1
#Embedded file name: ACEStream\Core\NATFirewall\NatCheckMsgHandler.pyo
from time import strftime
from traceback import print_exc
import datetime
import random
import socket
import sys
import thread
from ACEStream.Core.BitTornado.BT1.MessageID import CRAWLER_NATCHECK, CRAWLER_NATTRAVERSAL
from ACEStream.Core.BitTornado.bencode import bencode, bdecode
from ACEStream.Core.NATFirewall.ConnectionCheck import ConnectionCheck
from ACEStream.Core.NATFirewall.NatTraversal import tryConnect, coordinateHolePunching
from ACEStream.Core.Overlay.SecureOverlay import OLPROTO_VER_EIGHTH, OLPROTO_VER_NINETH, SecureOverlay
from ACEStream.Core.Statistics.Crawler import Crawler
from ACEStream.Core.Utilities.utilities import show_permid, show_permid_short
from types import IntType, StringType, ListType, TupleType
from ACEStream.Core.simpledefs import *
DEBUG = False
PEERLIST_LEN = 100

class NatCheckMsgHandler:
    __single = None

    def __init__(self):
        if NatCheckMsgHandler.__single:
            raise RuntimeError, 'NatCheckMsgHandler is singleton'
        NatCheckMsgHandler.__single = self
        self.crawler_reply_callbacks = []
        self._secure_overlay = SecureOverlay.getInstance()
        self.crawler = Crawler.get_instance()
        if self.crawler.am_crawler():
            self._file = open('natcheckcrawler.txt', 'a')
            self._file.write('\n'.join(('# ' + '*' * 80, strftime('%Y/%m/%d %H:%M:%S'), '# Crawler started\n')))
            self._file.flush()
            self._file2 = open('nattraversalcrawler.txt', 'a')
            self._file2.write('\n'.join(('# ' + '*' * 80, strftime('%Y/%m/%d %H:%M:%S'), '# Crawler started\n')))
            self._file2.flush()
            self.peerlist = []
            self.holePunchingIP = socket.gethostbyname(socket.gethostname())
            self.trav = {}
        else:
            self._file = None

    @staticmethod
    def getInstance(*args, **kw):
        if NatCheckMsgHandler.__single is None:
            NatCheckMsgHandler(*args, **kw)
        return NatCheckMsgHandler.__single

    def register(self, launchmany):
        if DEBUG:
            print >> sys.stderr, 'NatCheckMsgHandler: register'
        self.session = launchmany.session
        self.doNatCheckSender = None
        self.registered = True

    def doNatCheck(self, target_permid, selversion, request_callback):
        if selversion < OLPROTO_VER_NINETH:
            if DEBUG:
                print >> sys.stderr, 'NatCheckMsgHandler: ACEStream version too old for NATCHECK: do nothing'
            return False
        if DEBUG:
            print >> sys.stderr, 'NatCheckMsgHandler: do NATCHECK'
        request_callback(CRAWLER_NATCHECK, '', callback=self.doNatCheckCallback)
        return True

    def doNatCheckCallback(self, exc, permid):
        if exc is not None:
            return False
            if DEBUG:
                print >> sys.stderr, 'NATCHECK_REQUEST was sent to', show_permid_short(permid), exc
        self._file.write('; '.join((strftime('%Y/%m/%d %H:%M:%S'),
         'REQUEST',
         show_permid(permid),
         str(self._secure_overlay.get_dns_from_peerdb(permid)),
         '\n')))
        self._file.flush()
        return True

    def gotDoNatCheckMessage(self, sender_permid, selversion, channel_id, payload, reply_callback):
        self.doNatCheckSender = sender_permid
        self.crawler_reply_callbacks.append(reply_callback)
        try:
            if DEBUG:
                print >> sys.stderr, 'NatCheckMsgHandler: start_nat_type_detect()'
            conn_check = ConnectionCheck.getInstance(self.session)
            conn_check.try_start(self.natthreadcb_natCheckReplyCallback)
        except:
            print_exc()
            return False

        return True

    def natthreadcb_natCheckReplyCallback(self, ncr_data):
        if DEBUG:
            print >> sys.stderr, 'NAT type: ', ncr_data
        if self.doNatCheckSender is not None:
            try:
                ncr_msg = bencode(ncr_data)
            except:
                print_exc()
                if DEBUG:
                    print >> sys.stderr, 'error ncr_data:', ncr_data
                return False

            if DEBUG:
                print >> sys.stderr, 'NatCheckMsgHandler:', ncr_data
            for reply_callback in self.crawler_reply_callbacks:
                reply_callback(ncr_msg, callback=self.natCheckReplySendCallback)

            self.crawler_reply_callbacks = []

    def natCheckReplySendCallback(self, exc, permid):
        if DEBUG:
            print >> sys.stderr, 'NATCHECK_REPLY was sent to', show_permid_short(permid), exc
        if exc is not None:
            return False
        return True

    def gotNatCheckReplyMessage(self, permid, selversion, channel_id, channel_data, error, payload, request_callback):
        if error:
            if DEBUG:
                print >> sys.stderr, 'NatCheckMsgHandler: gotNatCheckReplyMessage'
                print >> sys.stderr, 'NatCheckMsgHandler: error', error
            self._file.write('; '.join((strftime('%Y/%m/%d %H:%M:%S'),
             '  REPLY',
             show_permid(permid),
             str(self._secure_overlay.get_dns_from_peerdb(permid)),
             'ERROR(%d)' % error,
             payload,
             '\n')))
            self._file.flush()
        else:
            try:
                recv_data = bdecode(payload)
            except:
                print_exc()
                print >> sys.stderr, 'bad encoded data:', payload
                return False

            try:
                self.validNatCheckReplyMsg(recv_data)
            except RuntimeError as e:
                print >> sys.stderr, e
                return False

            if DEBUG:
                print >> sys.stderr, 'NatCheckMsgHandler: received NAT_CHECK_REPLY message: ', recv_data
            self._file.write('; '.join((strftime('%Y/%m/%d %H:%M:%S'),
             '  REPLY',
             show_permid(permid),
             str(self._secure_overlay.get_dns_from_peerdb(permid)),
             ':'.join([ str(x) for x in recv_data ]),
             '\n')))
            self._file.flush()
            if selversion < OLPROTO_VER_NINETH:
                if DEBUG:
                    print >> sys.stderr, 'NatCheckMsgHandler: ACEStream version too old for NATTRAVERSAL: do nothing'
                return True
            if DEBUG:
                print >> sys.stderr, 'NatCheckMsgHandler: do NATTRAVERSAL'
            if len(self.peerlist) == PEERLIST_LEN:
                del self.peerlist[0]
            self.peerlist.append([permid, recv_data[1], recv_data[2]])
            if DEBUG:
                print >> sys.stderr, 'NatCheckMsgHandler: peerlist length is: ', len(self.peerlist)
            if len(self.peerlist) >= 2:
                self.tryHolePunching()
        return True

    def validNatCheckReplyMsg(self, ncr_data):
        if not type(ncr_data) == ListType:
            raise RuntimeError, 'NatCheckMsgHandler: received data is not valid. It must be a list of parameters.'
            return False
        if not type(ncr_data[0]) == StringType:
            raise RuntimeError, 'NatCheckMsgHandler: received data is not valid. The first element in the list must be a string.'
            return False
        if not type(ncr_data[1]) == IntType:
            raise RuntimeError, 'NatCheckMsgHandler: received data is not valid. The second element in the list must be an integer.'
            return False
        if not type(ncr_data[2]) == IntType:
            raise RuntimeError, 'NatCheckMsgHandler: received data is not valid. The third element in the list must be an integer.'
            return False
        if not type(ncr_data[3]) == StringType:
            raise RuntimeError, 'NatCheckMsgHandler: received data is not valid. The forth element in the list must be a string.'
            return False
        if not type(ncr_data[4]) == IntType:
            raise RuntimeError, 'NatCheckMsgHandler: received data is not valid. The fifth element in the list must be an integer.'
            return False
        if not type(ncr_data[5]) == StringType:
            raise RuntimeError, 'NatCheckMsgHandler: received data is not valid. The sixth element in the list must be a string.'
            return False
        if not type(ncr_data[6]) == IntType:
            raise RuntimeError, 'NatCheckMsgHandler: received data is not valid. The seventh element in the list must be an integer.'
            return False

    def tryHolePunching(self):
        if DEBUG:
            print >> sys.stderr, 'NatCheckMsgHandler: first element in peerlist', self.peerlist[len(self.peerlist) - 1]
            print >> sys.stderr, 'NatCheckMsgHandler: second element in peerlist', self.peerlist[len(self.peerlist) - 2]
        holePunchingPort = random.randrange(3200, 4200, 1)
        holePunchingAddr = (self.holePunchingIP, holePunchingPort)
        peer1 = self.peerlist[len(self.peerlist) - 1]
        peer2 = self.peerlist[len(self.peerlist) - 2]
        request_id = str(show_permid_short(peer1[0]) + show_permid_short(peer2[0]) + str(random.randrange(0, 1000, 1)))
        self.udpConnect(peer1[0], request_id, holePunchingAddr)
        self.udpConnect(peer2[0], request_id, holePunchingAddr)
        self._file2.write('; '.join((strftime('%Y/%m/%d %H:%M:%S'),
         'REQUEST',
         request_id,
         show_permid(peer1[0]),
         str(peer1[1]),
         str(peer1[2]),
         str(self._secure_overlay.get_dns_from_peerdb(peer1[0])),
         show_permid(peer2[0]),
         str(peer2[1]),
         str(peer2[2]),
         str(self._secure_overlay.get_dns_from_peerdb(peer2[0])),
         '\n')))
        self._file2.flush()
        self.trav[request_id] = (None, None)
        thread.start_new_thread(coordinateHolePunching, (peer1, peer2, holePunchingAddr))

    def udpConnect(self, permid, request_id, holePunchingAddr):
        if DEBUG:
            print >> sys.stderr, 'NatCheckMsgHandler: request UDP connection'
        mh_data = request_id + ':' + holePunchingAddr[0] + ':' + str(holePunchingAddr[1])
        if DEBUG:
            print >> sys.stderr, 'NatCheckMsgHandler: udpConnect message is', mh_data
        try:
            mh_msg = bencode(mh_data)
        except:
            print_exc()
            if DEBUG:
                print >> sys.stderr, 'NatCheckMsgHandler: error mh_data:', mh_data
            return False

        self.crawler.send_request(permid, CRAWLER_NATTRAVERSAL, mh_msg, frequency=0, callback=self.udpConnectCallback)
        if DEBUG:
            print >> sys.stderr, 'NatCheckMsgHandler: request for', show_permid_short(permid), 'sent to crawler'

    def udpConnectCallback(self, exc, permid):
        if exc is not None:
            if DEBUG:
                print >> sys.stderr, 'NATTRAVERSAL_REQUEST failed to', show_permid_short(permid), exc
            self._file2.write('; '.join((strftime('%Y/%m/%d %H:%M:%S'),
             'REQUEST FAILED',
             show_permid(permid),
             str(self._secure_overlay.get_dns_from_peerdb(permid)),
             '\n')))
            return False
        if DEBUG:
            print >> sys.stderr, 'NATTRAVERSAL_REQUEST was sent to', show_permid_short(permid), exc
        return True

    def gotUdpConnectRequest(self, permid, selversion, channel_id, mh_msg, reply_callback):
        if DEBUG:
            print >> sys.stderr, 'NatCheckMsgHandler: gotUdpConnectRequest from', show_permid_short(permid)
        try:
            mh_data = bdecode(mh_msg)
        except:
            print_exc()
            print >> sys.stderr, 'NatCheckMsgHandler: bad encoded data:', mh_msg
            return False

        if DEBUG:
            print >> sys.stderr, 'NatCheckMsgHandler: gotUdpConnectRequest is', mh_data
        try:
            request_id, host, port = mh_data.split(':')
        except:
            print_exc()
            print >> sys.stderr, 'NatCheckMsgHandler: error in received data:', mh_data
            return False

        coordinator = (host, int(port))
        if DEBUG:
            print >> sys.stderr, 'NatCheckMsgHandler: coordinator address is', coordinator
        mhr_data = request_id + ':' + tryConnect(coordinator)
        try:
            mhr_msg = bencode(mhr_data)
        except:
            print_exc()
            print >> sys.stderr, 'NatCheckMsgHandler: error in encoding data:', mhr_data
            return False

        reply_callback(mhr_msg, callback=self.udpConnectReplySendCallback)

    def udpConnectReplySendCallback(self, exc, permid):
        if DEBUG:
            print >> sys.stderr, 'NATTRAVERSAL_REPLY was sent to', show_permid_short(permid), exc
        if exc is not None:
            return False
        return True

    def gotUdpConnectReply(self, permid, selversion, channel_id, channel_data, error, mhr_msg, request_callback):
        if DEBUG:
            print >> sys.stderr, 'NatCheckMsgHandler: gotMakeHoleReplyMessage'
        try:
            mhr_data = bdecode(mhr_msg)
        except:
            print_exc()
            print >> sys.stderr, 'NatCheckMsgHandler: bad encoded data:', mhr_msg
            return False

        if DEBUG:
            print >> sys.stderr, 'NatCheckMsgHandler: message is', mhr_data
        try:
            request_id, reply = mhr_data.split(':')
        except:
            print_exc()
            print >> sys.stderr, 'NatCheckMsgHandler: error in received data:', mhr_data
            return False

        if DEBUG:
            print >> sys.stderr, 'NatCheckMsgHandler: request_id is', request_id
        if request_id in self.trav:
            if DEBUG:
                print >> sys.stderr, 'NatCheckMsgHandler: request_id is in the list'
            peer, value = self.trav[request_id]
            if peer == None:
                if DEBUG:
                    print >> sys.stderr, 'NatCheckMsgHandler: first peer reply'
                self.trav[request_id] = ((permid, self._secure_overlay.get_dns_from_peerdb(permid)), reply)
            elif type(peer) == TupleType:
                if DEBUG:
                    print >> sys.stderr, 'NatCheckMsgHandler: second peer reply'
                self._file2.write('; '.join((strftime('%Y/%m/%d %H:%M:%S'),
                 '  REPLY',
                 request_id,
                 show_permid(peer[0]),
                 str(peer[1]),
                 value,
                 show_permid(permid),
                 str(self._secure_overlay.get_dns_from_peerdb(permid)),
                 reply,
                 '\n')))
                del self.trav[request_id]
        self._file2.flush()
