# Written by Arno Bakker # see LICENSE.txt for license information import unittest import os import sys import time import socket from sha import sha from traceback import print_exc from types import StringType from test_as_server import TestAsServer from olconn import OLConnection from btconn import BTConnection from BitTornado.bencode import bencode,bdecode from BitTornado.BT1.MessageID import * from Tribler.NATFirewall.ReturnConnHandler import dialback_infohash from Tribler.utilities import isValidIP DEBUG=True class TestDialbackRequest(TestAsServer): """ Testing DIALBACK_REQUEST message of Dialback extension V1 """ #def setUp(self): # """ override TestAsServer """ # TestAsServer.setUp(self) def setUpPreTriblerInit(self): """ override TestAsServer """ TestAsServer.setUpPreTriblerInit(self) # Enable dialback self.config['dialback'] = 1 self.config['dialback_active'] = 0 self.setUpMyListenSocket() def setUpPreLaunchMany(self): """ override TestAsServer """ TestAsServer.setUpPreLaunchMany(self) self.myip = '127.0.0.1' def setUpMyListenSocket(self): # Start our server side, to with Tribler will try to connect self.mylistenport = 4810 self.myss = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.myss.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) self.myss.bind(('', self.mylistenport)) self.myss.listen(1) def tearDown(self): """ override TestAsServer """ print >> sys.stderr,"test: *** TEARDOWN" TestAsServer.tearDown(self) self.tearDownMyListenSocket() def tearDownMyListenSocket(self): self.myss.close() def test_all(self): """ I want to start a Tribler client once and then connect to it many times. So there must be only one test method to prevent setUp() from creating a new client every time. The code is constructed so unittest will show the name of the (sub)test where the error occured in the traceback it prints. """ # 1. test good DIALBACK_REQUEST self.subtest_good_drequest() # 2. test various bad DIALBACK_REQUEST messages self.subtest_bad_not_empty() # # Good DIALBACK_REQUEST # def subtest_good_drequest(self): """ test good DIALBACK_REQUEST messages """ s = OLConnection(self.my_keypair,'localhost',self.hisport,mylistenport=self.mylistenport) msg = self.create_good_drequest() s.send(msg) time.sleep(5) # And connect back to us conn, addr = self.myss.accept() s2 = BTConnection('',0,conn,mylistenport=self.mylistenport,user_infohash=dialback_infohash) s2.read_handshake_medium_rare() resp = s2.recv() print >> sys.stderr,"test: Me got DIALBACK_REPLY from him, len",len(resp) self.assert_(resp[0] == DIALBACK_REPLY) self.check_drequest(resp[1:]) def create_good_drequest(self): return str(DIALBACK_REQUEST) def check_drequest(self,data): s = bdecode(data) self.assert_(type(s) == StringType) self.assert_(isValidIP(s)) self.assert_(s == self.myip) # # Bad DIALBACK_REQUEST # def subtest_bad_not_empty(self): self._test_bad(self.create_not_empty) # # Main test code for bad DIALBACK_REQUEST messages # def _test_bad(self,gen_drequest_func): s = OLConnection(self.my_keypair,'localhost',self.hisport) print >> sys.stderr,"\ntest: ",gen_drequest_func msg = gen_drequest_func() s.send(msg) time.sleep(5) # the other side should not like this and close the connection resp = s.recv() self.assert_(len(resp)==0) s.close() # However, closing the connection is the specified behaviour, check # that he doesn't connect back try: self.myss.settimeout(10.0) print >> sys.stderr,"test: See if peer connects back (would be bad)" conn, addr = self.myss.accept() s = BTConnection('',0,conn,mylistenport=self.mylistenport,user_infohash=dialback_infohash) s.read_handshake_medium_rare() resp = s.recv() print >> sys.stderr,"test: Got reply back, len",len(resp),"see if expected" self.assert_(len(resp) > 0) self.assert_(resp[0] != DIALBACK_REPLY) print >> sys.stderr,"test: Reply was acceptable",getMessageName(resp[0]) except socket.timeout: self.assert_(True) print >> sys.stderr,"test: Good, accept() timed out" # # Bad message creators # def create_not_empty(self): return DIALBACK_REQUEST+"bla" def test_suite(): suite = unittest.TestSuite() suite.addTest(unittest.makeSuite(TestDialbackRequest)) return suite if __name__ == "__main__": unittest.main()