def setUp(self):
     SimulatedNetwork.clear()
     self.aliceReceivedRequests = []
     self.aliceReceivedResponses = []
     self.atlantaReceivedRequests = []
     self.atlantaReceivedResponses = []
     self.biloxiReceivedRequests = []
     self.biloxiReceivedResponses = []
     self.bobReceivedRequests = []
     self.bobReceivedResponses = []
     self.atlanta = SIPStatelessProxy()
     self.atlanta.transports = [SimulatedSIPTransport(self.atlantaBindAddress, self.atlantaBindPort)]
     self.biloxi = SIPStatelessProxy()
     self.biloxi.transports = [SimulatedSIPTransport(self.biloxiBindAddress, self.biloxiBindPort)]
     self.aliceTransport = SimulatedSIPTransport(self.aliceBindAddress, self.aliceBindPort)
     self.bobTransport = SimulatedSIPTransport(self.bobBindAddress, self.bobBindPort)
     self.aliceTransport.whenEventDo("receivedValidConnectedRequest", self.aliceRequestEventHandler)
     self.aliceTransport.whenEventDo("receivedValidConnectedResponse", self.aliceResponseEventHandler)
     self.atlanta.transports[0].whenEventDo("receivedValidConnectedRequest", self.atlantaRequestEventHandler)
     self.atlanta.transports[0].whenEventDo("receivedValidConnectedResponse", self.atlantaResponseEventHandler)
     self.biloxi.transports[0].whenEventDo("receivedValidConnectedRequest", self.biloxiRequestEventHandler)
     self.biloxi.transports[0].whenEventDo("receivedValidConnectedResponse", self.biloxiResponseEventHandler)
     self.bobTransport.whenEventDo("receivedValidConnectedRequest", self.bobRequestEventHandler)
     self.bobTransport.whenEventDo("receivedValidConnectedResponse", self.bobResponseEventHandler)
     self.aliceTransport.bind()
     self.bobTransport.bind()
     self.aliceTransport.connectToAddressAndPort(self.atlantaBindAddress, self.atlantaBindPort)
 def setUp(self):
     SimulatedNetwork.clear()
     self.hasBound = False
     self.bindHasFailed = False
     self.connectedConnections = []
     self.notConnectedAddressesAndPorts = []
     self.receivedRequests = []
     self.receivedResponses = []
     self.transport1 = SimulatedSIPTransport(self.bindAddress1, self.bindPort1)
     self.transport1.whenEventDo("bound", self.boundEventHandler)
     self.transport1.whenEventDo("bindFailed", self.bindFailedEventHandler)
     self.transport1.whenEventDo("madeConnection", self.madeConnectionEventHandler)
     self.transport1.whenEventDo("couldNotMakeConnection", self.couldNotMakeConnectionEventHandler)
     self.transport1.whenEventDo("lostConnection", self.lostConnectionEventHandler)
     self.transport1.whenEventDo("receivedValidConnectedRequest", self.receivedValidConnectedRequestEventHandler)
     self.transport1.whenEventDo("receivedValidConnectedResponse", self.receivedValidConnectedResponseEventHandler)
     self.transport2 = SimulatedSIPTransport(self.bindAddress2, self.bindPort2)
     self.transport3 = SimulatedSIPTransport(self.bindAddress3, self.bindPort3)
class TestStatelessProxyWithSimulatedTransport(AbstractStatelessProxyTestCase):
    def setUp(self):
        SimulatedNetwork.clear()
        self.aliceReceivedRequests = []
        self.aliceReceivedResponses = []
        self.atlantaReceivedRequests = []
        self.atlantaReceivedResponses = []
        self.biloxiReceivedRequests = []
        self.biloxiReceivedResponses = []
        self.bobReceivedRequests = []
        self.bobReceivedResponses = []
        self.atlanta = SIPStatelessProxy()
        self.atlanta.transports = [SimulatedSIPTransport(self.atlantaBindAddress, self.atlantaBindPort)]
        self.biloxi = SIPStatelessProxy()
        self.biloxi.transports = [SimulatedSIPTransport(self.biloxiBindAddress, self.biloxiBindPort)]
        self.aliceTransport = SimulatedSIPTransport(self.aliceBindAddress, self.aliceBindPort)
        self.bobTransport = SimulatedSIPTransport(self.bobBindAddress, self.bobBindPort)
        self.aliceTransport.whenEventDo("receivedValidConnectedRequest", self.aliceRequestEventHandler)
        self.aliceTransport.whenEventDo("receivedValidConnectedResponse", self.aliceResponseEventHandler)
        self.atlanta.transports[0].whenEventDo("receivedValidConnectedRequest", self.atlantaRequestEventHandler)
        self.atlanta.transports[0].whenEventDo("receivedValidConnectedResponse", self.atlantaResponseEventHandler)
        self.biloxi.transports[0].whenEventDo("receivedValidConnectedRequest", self.biloxiRequestEventHandler)
        self.biloxi.transports[0].whenEventDo("receivedValidConnectedResponse", self.biloxiResponseEventHandler)
        self.bobTransport.whenEventDo("receivedValidConnectedRequest", self.bobRequestEventHandler)
        self.bobTransport.whenEventDo("receivedValidConnectedResponse", self.bobResponseEventHandler)
        self.aliceTransport.bind()
        self.bobTransport.bind()
        self.aliceTransport.connectToAddressAndPort(self.atlantaBindAddress, self.atlantaBindPort)
        # Let Biloxi connect to Bob.  Don't pre-connect Bob to Biloxi.
        # self.bobTransport.connectToAddressAndPort(self.biloxiBindAddress, self.biloxiBindPort)
        # TODO:  need to bind?

    def test(self):
        self.run_00_initialSanityCheck()
        self.run_01_atlantaToBiloxi()
        self.run_02_biloxiToAtlanta()

    def run_00_initialSanityCheck(self):
        self.assertEqual(1, len(self.atlanta.transports))
        self.assertEqual(1, len(self.biloxi.transports))
        self.assertEqual(1, len(self.atlanta.transports[0].connections))
        self.assertEqual(0, len(self.biloxi.transports[0].connections))
        self.assertEqual(self.atlantaBindAddress, self.atlanta.transports[0].bindAddress)
        self.assertEqual(self.atlantaBindPort, self.atlanta.transports[0].bindPort)
        self.assertEqual(self.atlantaBindAddress, self.atlanta.transports[0].connections[0].bindAddress)
        self.assertEqual(self.atlantaBindPort, self.atlanta.transports[0].connections[0].bindPort)
        self.assertEqual(self.atlantaBindAddress, self.aliceTransport.connections[0].remoteAddress)
        self.assertEqual(self.atlantaBindPort, self.aliceTransport.connections[0].remotePort)
        self.assertEqual(self.aliceBindAddress, self.atlanta.transports[0].connections[0].remoteAddress)
        self.assertEqual(self.aliceBindPort, self.atlanta.transports[0].connections[0].remotePort)
        self.assertEqual(self.biloxiBindAddress, self.biloxi.transports[0].bindAddress)
        self.assertEqual(self.biloxiBindPort, self.biloxi.transports[0].bindPort)
        self.assertEqual(0, len(self.aliceReceivedRequests))
        self.assertEqual(0, len(self.aliceReceivedResponses))
        self.assertEqual(0, len(self.atlantaReceivedRequests))
        self.assertEqual(0, len(self.atlantaReceivedResponses))
        self.assertEqual(0, len(self.biloxiReceivedRequests))
        self.assertEqual(0, len(self.biloxiReceivedResponses))
        self.assertEqual(0, len(self.bobReceivedRequests))
        self.assertEqual(0, len(self.bobReceivedResponses))

    def run_01_atlantaToBiloxi(self):
        self.aliceTransport.connections[0].sendString(self.aliceRequestString)
        self.assertEqual(0, len(self.aliceReceivedRequests))
        # self.assertEqual(1, len(self.aliceReceivedResponses))
        self.assertEqual(1, len(self.atlantaReceivedRequests))
        self.assertEqual(1, len(self.biloxiReceivedRequests))
        self.assertEqual(1, len(self.atlantaReceivedResponses))
        self.assertEqual(0, len(self.biloxiReceivedResponses))
        self.assertEqual(0, len(self.bobReceivedRequests))
        self.assertEqual(0, len(self.bobReceivedResponses))

        self.assertEqual(self.aliceBindAddress, self.atlantaReceivedRequests[0].connection.remoteAddress)
        self.assertEqual(self.aliceBindPort, self.atlantaReceivedRequests[0].connection.remotePort)
        self.assertEqual(self.atlantaBindAddress, self.atlantaReceivedRequests[0].connection.bindAddress)
        self.assertEqual(self.atlantaBindPort, self.atlantaReceivedRequests[0].connection.bindPort)
        atlantaReceivedRequest = self.atlantaReceivedRequests[0].sipMessage
        rURI = SIPURI.newParsedFrom(atlantaReceivedRequest.startLine.requestURI)
        self.assertEqual(self.aliceRequestString, atlantaReceivedRequest.rawString)
        self.assertEqual('INVITE', atlantaReceivedRequest.startLine.sipMethod)
        self.assertEqual(self.biloxiBindAddress, rURI.host)
        self.assertEqual(1, len(atlantaReceivedRequest.vias))
        self.assertEqual(self.aliceRequestString, atlantaReceivedRequest.rawString)
        self.assertIsNone(atlantaReceivedRequest.header.toTag)

        self.assertEqual(self.atlantaBindAddress, self.biloxiReceivedRequests[0].connection.remoteAddress)
        self.assertEqual(self.atlantaBindPort, self.biloxiReceivedRequests[0].connection.remotePort)
        self.assertEqual(self.biloxiBindAddress, self.biloxiReceivedRequests[0].connection.bindAddress)
        self.assertEqual(self.biloxiBindPort, self.biloxiReceivedRequests[0].connection.bindPort)
        biloxiReceivedRequest = self.biloxiReceivedRequests[0].sipMessage
        self.assertEqual(atlantaReceivedRequest.startLine.requestURI, biloxiReceivedRequest.startLine.requestURI)
        self.assertEqual('INVITE', biloxiReceivedRequest.startLine.sipMethod)
        self.assertEqual(2, len(biloxiReceivedRequest.vias))
        self.assertNotEqual(self.aliceRequestString, biloxiReceivedRequest.rawString)
        self.assertIsNone(biloxiReceivedRequest.header.toTag)

        self.assertEqual(self.biloxiBindAddress, self.atlantaReceivedResponses[0].connection.remoteAddress)
        self.assertEqual(self.biloxiBindPort, self.atlantaReceivedResponses[0].connection.remotePort)
        self.assertEqual(self.atlantaBindAddress, self.atlantaReceivedResponses[0].connection.bindAddress)
        self.assertEqual(self.atlantaBindPort, self.atlantaReceivedResponses[0].connection.bindPort)
        atlantaReceivedResponse = self.atlantaReceivedResponses[0].sipMessage
        self.assertIsNotNone(atlantaReceivedResponse.header.toTag)
        self.assertEqual(2, len(atlantaReceivedResponse.vias))

        self.assertEqual(self.atlantaBindAddress, self.aliceReceivedResponses[0].connection.remoteAddress)
        self.assertEqual(self.atlantaBindPort, self.aliceReceivedResponses[0].connection.remotePort)
        self.assertEqual(self.aliceBindAddress, self.aliceReceivedResponses[0].connection.bindAddress)
        self.assertEqual(self.aliceBindPort, self.aliceReceivedResponses[0].connection.bindPort)
        aliceReceivedResponse = self.aliceReceivedResponses[0].sipMessage
        self.assertIsNotNone(aliceReceivedResponse.header.toTag)
        self.assertEqual(1, len(aliceReceivedResponse.vias))

        self.assertEqual(self.aliceBindAddress, atlantaReceivedRequest.viaHeaderFields[0].host)
        # TODO: This 404 nonsense is temporary.  Alice sends to a biloxi domain via atlanta, atlanta forwards her request to biloxi,
        # Biloxi sees that it is responsible for the request, and for right now, just answers 404.
        self.assertEqual(404, self.atlantaReceivedResponses[0].sipMessage.startLine.statusCode)
        self.assertEqual(404, self.aliceReceivedResponses[0].sipMessage.startLine.statusCode)

        # TODO:  Moar!!!

    def run_02_biloxiToAtlanta(self):
        pass

    @property
    def aliceBindAddress(self):
        # return '192.168.4.4'
        return '127.0.0.2'

    @property
    def aliceBindPort(self):
        # Note the port in the Via header field...
        # return 5060
        return 63354

    @property
    def atlantaBindAddress(self):
        # return '192.168.4.2'
        return '127.0.0.3'

    @property
    def atlantaBindPort(self):
        return 5060

    @property
    def biloxiBindAddress(self):
        # return '192.168.4.3'
        return '127.0.0.4'

    @property
    def biloxiBindPort(self):
        return 5060

    @property
    def bobBindAddress(self):
        # return '192.168.4.5'
        return '127.0.0.5'

    @property
    def bobBindPort(self):
        return 5060

    @property
    def aliceRequestString(self):
        # Bob's extension is 1002
        # atlanta == .2 / .97
        # biloxi == .3 / .96
        # alice == .2 / .188
        # bob == .5 / .204
        # messageString = ('INVITE sip:[email protected] SIP/2.0\r\n'
        #                  'Via: SIP/2.0/UDP 192.168.4.4:63354;branch=z9hG4bK-524287-1---7a462a5d1b6fe13b;rport\r\n'
        #                  'Max-Forwards: 70\r\n'
        #                  'Contact: <sip:[email protected]:63354;rinstance=d875ce4fd8f72441>\r\n'
        #                  'To: <sip:[email protected]>\r\n'
        #                  'From: "Alice"<sip:[email protected]>;tag=9980376d\r\n'
        #                  'Call-ID: YjBhMDliMWMxNzQ4ZTc5Nzg1ZTcyYTExMWMzZDlhNmQ\r\n'
        #                  'CSeq: 1 INVITE\r\n'
        #                  'Allow: INVITE, ACK, CANCEL, BYE, REFER, INFO, NOTIFY, UPDATE, PRACK, MESSAGE, OPTIONS, SUBSCRIBE, OPTIONS\r\n'
        #                  'Content-Type: application/sdp\r\n'
        #                  'Supported: replaces, 100rel\r\n'
        #                  'User-Agent: Bria iOS release 3.6.2 stamp 33024\r\n'
        #                  'Content-Length: 185\r\n'
        #                  '\r\n'
        #                  'v=0\r\n'
        #                  'o=- 1457365987528724 1 IN IP4 192.168.4.4\r\n'
        #                  's=Cpc session\r\n'
        #                  'c=IN IP4 192.168.4.4\r\n'
        #                  't=0 0\r\n'
        #                  'm=audio 60668 RTP/AVP 0 101\r\n'
        #                  'a=rtpmap:101 telephone-event/8000\r\n'
        #                  'a=fmtp:101 0-15\r\n'
        #                  'a=sendrecv\r\n')
        messageString = ('INVITE sip:[email protected] SIP/2.0\r\n'
                         'Via: SIP/2.0/UDP 127.0.0.2:63354;branch=z9hG4bK-524287-1---7a462a5d1b6fe13b;rport\r\n'
                         'Max-Forwards: 70\r\n'
                         'Contact: <sip:[email protected]:63354;rinstance=d875ce4fd8f72441>\r\n'
                         'To: <sip:[email protected]>\r\n'
                         'From: "Alice"<sip:[email protected]>;tag=9980376d\r\n'
                         'Call-ID: YjBhMDliMWMxNzQ4ZTc5Nzg1ZTcyYTExMWMzZDlhNmQ\r\n'
                         'CSeq: 1 INVITE\r\n'
                         'Allow: INVITE, ACK, CANCEL, BYE, REFER, INFO, NOTIFY, UPDATE, PRACK, MESSAGE, OPTIONS, SUBSCRIBE, OPTIONS\r\n'
                         'Content-Type: application/sdp\r\n'
                         'Supported: replaces, 100rel\r\n'
                         'User-Agent: Bria iOS release 3.6.2 stamp 33024\r\n'
                         'Content-Length: 181\r\n'
                         '\r\n'
                         'v=0\r\n'
                         'o=- 1457365987528724 1 IN IP4 127.0.0.2\r\n'
                         's=Cpc session\r\n'
                         'c=IN IP4 127.0.0.2\r\n'
                         't=0 0\r\n'
                         'm=audio 60668 RTP/AVP 0 101\r\n'
                         'a=rtpmap:101 telephone-event/8000\r\n'
                         'a=fmtp:101 0-15\r\n'
                         'a=sendrecv\r\n')
        return messageString

    # @property
    # def aliceResponseString(self):
        # TODO: need to fix up the addresses and transport type and stuff.
        # atlanta == .2 / .97
        # biloxi == .3 / .96
        # alice == .4 / .188
        # bob == .5 / .204
        # messageString = ('SIP/2.0 180 Ringing\r\n'
        #                  'Via: SIP/2.0/UDP 192.168.4.2;branch=z9hG4bKeb83.c2fe646b6c2d21c6f9f113d37c474768.0\r\n'
        #                  'Via: SIP/2.0/UDP 192.168.4.3:56731;received=192.168.4.4;branch=z9hG4bK-524287-1---e500d061e354193a;rport=56731\r\n'
        #                  'Via: SIP/2.0/UDP 192.168.4.5;branch=z9hG4bKeb83.c2fe646b6c2d21c6f9f113d37c474768.0\r\n'
        #                  'Record-Route: <sip:192.168.4.2;lr>\r\n'
        #                  'Record-Route: <sip:192.168.4.3;lr>\r\n'
        #                  'Require: 100rel\r\n'
        #                  'Contact: <sip:[email protected]:52909;rinstance=7caea32dab180286>\r\n'
        #                  'To: "Bob"<sip:[email protected]>;tag=52e9ef73\r\n'
        #                  'From: "Alice"<sip:[email protected]>;tag=2210ba44\r\n'
        #                  'Call-ID: NTM5YzAxN2YwZGRhYTg2YjBkNDgyNWQyNTI3ZGNmNTE\r\n'
        #                  'CSeq: 1 INVITE\r\n'
        #                  'Allow: INVITE, ACK, CANCEL, BYE, REFER, INFO, NOTIFY, UPDATE, PRACK, MESSAGE, OPTIONS, SUBSCRIBE, OPTIONS\r\n'
        #                  'Supported: replaces\r\n'
        #                  'User-Agent: Bria iOS release 3.6.2 stamp 33024\r\n'
        #                  'Allow-Events: talk, hold\r\n'
        #                  'RSeq: 1\r\n'
        #                  'Content-Length: 0\r\n'
        #                  '\r\n')
        # messageString = ('SIP/2.0 180 Ringing\r\n'
        #                  'Via: SIP/2.0/UDP 127.0.0.3;branch=z9hG4bKeb83.c2fe646b6c2d21c6f9f113d37c474768.0\r\n'
        #                  'Via: SIP/2.0/UDP 127.0.0.4:56731;received=127.0.0.2;branch=z9hG4bK-524287-1---e500d061e354193a;rport=56731\r\n'
        #                  'Via: SIP/2.0/UDP 127.0.0.5;branch=z9hG4bKeb83.c2fe646b6c2d21c6f9f113d37c474768.0\r\n'
        #                  'Record-Route: <sip:127.0.0.3;lr>\r\n'
        #                  'Record-Route: <sip:127.0.0.4;lr>\r\n'
        #                  'Require: 100rel\r\n'
        #                  'Contact: <sip:[email protected]:52909;rinstance=7caea32dab180286>\r\n'
        #                  'To: "Bob"<sip:[email protected]>;tag=52e9ef73\r\n'
        #                  'From: "Alice"<sip:[email protected]>;tag=2210ba44\r\n'
        #                  'Call-ID: NTM5YzAxN2YwZGRhYTg2YjBkNDgyNWQyNTI3ZGNmNTE\r\n'
        #                  'CSeq: 1 INVITE\r\n'
        #                  'Allow: INVITE, ACK, CANCEL, BYE, REFER, INFO, NOTIFY, UPDATE, PRACK, MESSAGE, OPTIONS, SUBSCRIBE, OPTIONS\r\n'
        #                  'Supported: replaces\r\n'
        #                  'User-Agent: Bria iOS release 3.6.2 stamp 33024\r\n'
        #                  'Allow-Events: talk, hold\r\n'
        #                  'RSeq: 1\r\n'
        #                  'Content-Length: 0\r\n'
        #                  '\r\n')
        # return messageString

    @property
    def bobRequestString(self):
        # Alice's extension is 1001
        # atlanta == .2
        # biloxi == .3
        # alice == .4
        # bob == .5
        # messageString = ('INVITE sip:[email protected] SIP/2.0\r\n'
        #                  'Via: SIP/2.0/UDP 192.168.4.5:63354;branch=z9hG4bK-524287-1---7a462a5d1b6fe13b;rport\r\n'
        #                  'Max-Forwards: 70\r\n'
        #                  'Contact: <sip:[email protected]:63354;rinstance=d875ce4fd8f72441>\r\n'
        #                  'To: <sip:[email protected]>\r\n'
        #                  'From: "Alice"<sip:[email protected]>;tag=9980376d\r\n'
        #                  'Call-ID: YjBhMDliMWMxNzQ4ZTc5Nzg1ZTcyYTExMWMzZDlhNmQ\r\n'
        #                  'CSeq: 1 INVITE\r\n'
        #                  'Allow: INVITE, ACK, CANCEL, BYE, REFER, INFO, NOTIFY, UPDATE, PRACK, MESSAGE, OPTIONS, SUBSCRIBE, OPTIONS\r\n'
        #                  'Content-Type: application/sdp\r\n'
        #                  'Supported: replaces, 100rel\r\n'
        #                  'User-Agent: Bria iOS release 3.6.2 stamp 33024\r\n'
        #                  'Content-Length: 185\r\n'
        #                  '\r\n'
        #                  'v=0\r\n'
        #                  'o=- 1457365987528724 1 IN IP4 192.168.4.5\r\n'
        #                  's=Cpc session\r\n'
        #                  'c=IN IP4 192.168.4.5\r\n'
        #                  't=0 0\r\n'
        #                  'm=audio 60668 RTP/AVP 0 101\r\n'
        #                  'a=rtpmap:101 telephone-event/8000\r\n'
        #                  'a=fmtp:101 0-15\r\n'
        #                  'a=sendrecv\r\n')
        messageString = ('INVITE sip:[email protected] SIP/2.0\r\n'
                         'Via: SIP/2.0/UDP 127.0.0.5:63354;branch=z9hG4bK-524287-1---7a462a5d1b6fe13b;rport\r\n'
                         'Max-Forwards: 70\r\n'
                         'Contact: <sip:[email protected]:63354;rinstance=d875ce4fd8f72441>\r\n'
                         'To: <sip:[email protected]>\r\n'
                         'From: "Alice"<sip:[email protected]>;tag=9980376d\r\n'
                         'Call-ID: YjBhMDliMWMxNzQ4ZTc5Nzg1ZTcyYTExMWMzZDlhNmQ\r\n'
                         'CSeq: 1 INVITE\r\n'
                         'Allow: INVITE, ACK, CANCEL, BYE, REFER, INFO, NOTIFY, UPDATE, PRACK, MESSAGE, OPTIONS, SUBSCRIBE, OPTIONS\r\n'
                         'Content-Type: application/sdp\r\n'
                         'Supported: replaces, 100rel\r\n'
                         'User-Agent: Bria iOS release 3.6.2 stamp 33024\r\n'
                         'Content-Length: 181\r\n'
                         '\r\n'
                         'v=0\r\n'
                         'o=- 1457365987528724 1 IN IP4 127.0.0.5\r\n'
                         's=Cpc session\r\n'
                         'c=IN IP4 127.0.0.5\r\n'
                         't=0 0\r\n'
                         'm=audio 60668 RTP/AVP 0 101\r\n'
                         'a=rtpmap:101 telephone-event/8000\r\n'
                         'a=fmtp:101 0-15\r\n'
                         'a=sendrecv\r\n')
        return messageString

    # @property
    # def bobResponseString(self):
        # TODO: need to fix up the addresses and transport type and stuff.
        # atlanta == .2 / .97
        # biloxi == .3 / .96
        # alice == .4 / .188
        # bob == .5 / .204
        # messageString = ('SIP/2.0 180 Ringing\r\n'
        #                  'Via: SIP/2.0/UDP 192.168.4.3;branch=z9hG4bKeb83.c2fe646b6c2d21c6f9f113d37c474768.0\r\n'
        #                  'Via: SIP/2.0/UDP 192.168.4.2:56731;received=192.168.4.4;branch=z9hG4bK-524287-1---e500d061e354193a;rport=56731\r\n'
        #                  'Via: SIP/2.0/UDP 192.168.4.4;branch=z9hG4bKeb83.c2fe646b6c2d21c6f9f113d37c474768.0\r\n'
        #                  'Record-Route: <sip:192.168.4.3;lr>\r\n'
        #                  'Record-Route: <sip:192.168.4.2;lr>\r\n'
        #                  'Require: 100rel\r\n'
        #                  'Contact: <sip:[email protected]:52909;rinstance=7caea32dab180286>\r\n'
        #                  'To: "Bob"<sip:[email protected]>;tag=52e9ef73\r\n'
        #                  'From: "Alice"<sip:[email protected]>;tag=2210ba44\r\n'
        #                  'Call-ID: NTM5YzAxN2YwZGRhYTg2YjBkNDgyNWQyNTI3ZGNmNTE\r\n'
        #                  'CSeq: 1 INVITE\r\n'
        #                  'Allow: INVITE, ACK, CANCEL, BYE, REFER, INFO, NOTIFY, UPDATE, PRACK, MESSAGE, OPTIONS, SUBSCRIBE, OPTIONS\r\n'
        #                  'Supported: replaces\r\n'
        #                  'User-Agent: Bria iOS release 3.6.2 stamp 33024\r\n'
        #                  'Allow-Events: talk, hold\r\n'
        #                  'RSeq: 1\r\n'
        #                  'Content-Length: 0\r\n'
        #                  '\r\n')
        # messageString = ('SIP/2.0 180 Ringing\r\n'
        #                  'Via: SIP/2.0/UDP 127.0.0.4;branch=z9hG4bKeb83.c2fe646b6c2d21c6f9f113d37c474768.0\r\n'
        #                  'Via: SIP/2.0/UDP 127.0.0.3:56731;received=127.0.0.2;branch=z9hG4bK-524287-1---e500d061e354193a;rport=56731\r\n'
        #                  'Via: SIP/2.0/UDP 127.0.0.2;branch=z9hG4bKeb83.c2fe646b6c2d21c6f9f113d37c474768.0\r\n'
        #                  'Record-Route: <sip:127.0.0.4;lr>\r\n'
        #                  'Record-Route: <sip:127.0.0.3;lr>\r\n'
        #                  'Require: 100rel\r\n'
        #                  'Contact: <sip:[email protected]:52909;rinstance=7caea32dab180286>\r\n'
        #                  'To: "Bob"<sip:[email protected]>;tag=52e9ef73\r\n'
        #                  'From: "Alice"<sip:[email protected]>;tag=2210ba44\r\n'
        #                  'Call-ID: NTM5YzAxN2YwZGRhYTg2YjBkNDgyNWQyNTI3ZGNmNTE\r\n'
        #                  'CSeq: 1 INVITE\r\n'
        #                  'Allow: INVITE, ACK, CANCEL, BYE, REFER, INFO, NOTIFY, UPDATE, PRACK, MESSAGE, OPTIONS, SUBSCRIBE, OPTIONS\r\n'
        #                  'Supported: replaces\r\n'
        #                  'User-Agent: Bria iOS release 3.6.2 stamp 33024\r\n'
        #                  'Allow-Events: talk, hold\r\n'
        #                  'RSeq: 1\r\n'
        #                  'Content-Length: 0\r\n'
        #                  '\r\n')
        # return messageString

    def aliceRequestEventHandler(self, aConnectedSIPMessage):
        self.aliceReceivedRequests.append(aConnectedSIPMessage)

    def aliceResponseEventHandler(self, aConnectedSIPMessage):
        self.aliceReceivedResponses.append(aConnectedSIPMessage)

    def atlantaRequestEventHandler(self, aConnectedSIPMessage):
        self.atlantaReceivedRequests.append(aConnectedSIPMessage)

    def atlantaResponseEventHandler(self, aConnectedSIPMessage):
        self.atlantaReceivedResponses.append(aConnectedSIPMessage)

    def biloxiRequestEventHandler(self, aConnectedSIPMessage):
        self.biloxiReceivedRequests.append(aConnectedSIPMessage)

    def biloxiResponseEventHandler(self, aConnectedSIPMessage):
        self.biloxiReceivedResponses.append(aConnectedSIPMessage)

    def bobRequestEventHandler(self, aConnectedSIPMessage):
        self.bobReceivedRequests.append(aConnectedSIPMessage)

    def bobResponseEventHandler(self, aConnectedSIPMessage):
        self.bobReceivedResponses.append(aConnectedSIPMessage)
class TestSimulatedTransportConnection(AbstractTransportConnectionTestCase):
    # TODO:  will push most of this up.

    def setUp(self):
        SimulatedNetwork.clear()
        self.hasBound = False
        self.bindHasFailed = False
        self.connectedConnections = []
        self.notConnectedAddressesAndPorts = []
        self.receivedRequests = []
        self.receivedResponses = []
        self.transport1 = SimulatedSIPTransport(self.bindAddress1, self.bindPort1)
        self.transport1.whenEventDo("bound", self.boundEventHandler)
        self.transport1.whenEventDo("bindFailed", self.bindFailedEventHandler)
        self.transport1.whenEventDo("madeConnection", self.madeConnectionEventHandler)
        self.transport1.whenEventDo("couldNotMakeConnection", self.couldNotMakeConnectionEventHandler)
        self.transport1.whenEventDo("lostConnection", self.lostConnectionEventHandler)
        self.transport1.whenEventDo("receivedValidConnectedRequest", self.receivedValidConnectedRequestEventHandler)
        self.transport1.whenEventDo("receivedValidConnectedResponse", self.receivedValidConnectedResponseEventHandler)
        self.transport2 = SimulatedSIPTransport(self.bindAddress2, self.bindPort2)
        self.transport3 = SimulatedSIPTransport(self.bindAddress3, self.bindPort3)

    def test(self):
        self.run_00_initialSanityCheck()
        self.run_01_bind()
        self.run_02_makeOutboundConnection()
        self.run_03_makeInboundConnection()
        self.run_04_attemptSecondBind()
        self.run_05_attemptConnectToBogusAddressAndPort()
        self.run_06_attemptConnectToOwnAddressAndPort()
        self.run_07_sendRequestsVerifyReceipt()
        self.run_08_sendResponsesVerifyReceipt()

    def run_00_initialSanityCheck(self):
        self.assertIsInstance(self.transport1, SimulatedSIPTransport)
        self.assertEqual(0, len(self.transport1.connections))
        self.assertEqual(0, len(self.connectedConnections))
        self.assertEqual(0, len(self.receivedRequests))
        self.assertEqual(0, len(self.receivedResponses))
        self.assertTrue(self.transport1.isReliable)
        self.assertEqual('SIM', self.transport1.transportParameterName)
        self.assertEqual(self.bindAddress1, self.transport1.bindAddress)
        self.assertEqual(self.bindPort1, self.transport1.bindPort)
        self.assertFalse(self.hasBound)
        self.assertFalse(self.bindHasFailed)
        self.assertIsInstance(self.transport2, SimulatedSIPTransport)
        self.assertEqual(0, len(self.transport2.connections))
        self.assertTrue(self.transport2.isReliable)
        self.assertEqual('SIM', self.transport2.transportParameterName)
        self.assertEqual(self.bindAddress2, self.transport2.bindAddress)
        self.assertEqual(self.bindPort2, self.transport2.bindPort)
        self.assertIsInstance(self.transport3, SimulatedSIPTransport)
        self.assertEqual(0, len(self.transport3.connections))
        self.assertTrue(self.transport3.isReliable)
        self.assertEqual('SIM', self.transport3.transportParameterName)
        self.assertEqual(self.bindAddress3, self.transport3.bindAddress)
        self.assertEqual(self.bindPort3, self.transport3.bindPort)
        self.assertEqual(0, len(SimulatedNetwork.instance.boundTransports))

    def run_01_bind(self):
        self.transport1.bind()
        self.assertEqual(1, len(SimulatedNetwork.instance.boundTransports))
        self.assertTrue(self.hasBound)
        self.assertFalse(self.bindHasFailed)
        self.assertEqual(0, len(self.transport1.connections))
        self.assertEqual(0, len(self.connectedConnections))
        self.transport2.bind()
        self.assertEqual(2, len(SimulatedNetwork.instance.boundTransports))
        self.transport3.bind()
        self.assertEqual(3, len(SimulatedNetwork.instance.boundTransports))
        self.assertEqual(self.transport1, SimulatedNetwork.instance.boundTransports[0])
        self.assertEqual(self.transport2, SimulatedNetwork.instance.boundTransports[1])
        self.assertEqual(self.transport3, SimulatedNetwork.instance.boundTransports[2])
        self.assertIs(self.transport1, SimulatedNetwork.instance.boundTransportWithAddressAndPort(self.bindAddress1, self.bindPort1))
        self.assertIs(self.transport2, SimulatedNetwork.instance.boundTransportWithAddressAndPort(self.bindAddress2, self.bindPort2))
        self.assertIs(self.transport3, SimulatedNetwork.instance.boundTransportWithAddressAndPort(self.bindAddress3, self.bindPort3))

    def run_02_makeOutboundConnection(self):
        # Connect transport1 to transport2
        self.transport1.connectToAddressAndPort(self.bindAddress2, self.bindPort2)
        self.assertEqual(1, len(self.transport1.connections))
        self.assertEqual(1, len(self.connectedConnections))
        self.assertIs(self.connectedConnections[0], self.transport1.connections[0])
        self.assertEqual(self.bindAddress2, self.transport1.connections[0].remoteAddress)
        self.assertIsInstance(self.transport1.connections[0].bindPort, int)
        self.assertIsInstance(self.transport1.connections[0].id, basestring)
        self.assertEqual(self.bindPort2, self.transport1.connections[0].remotePort)
        self.assertEqual(1, len(self.transport2.connections))
        self.assertEqual(0, len(self.transport3.connections))
        self.assertEqual(self.bindAddress1, self.transport2.connections[0].remoteAddress)
        self.assertIsInstance(self.transport2.connections[0].remotePort, int)
        self.assertIsInstance(self.transport2.connections[0].id, basestring)
        self.assertEqual(self.bindPort2, self.transport2.connections[0].bindPort)

    def run_03_makeInboundConnection(self):
        # Connect transport3 to transport1
        self.transport3.connectToAddressAndPort(self.bindAddress1, self.bindPort1)
        self.assertEqual(2, len(self.transport1.connections))
        self.assertEqual(1, len(self.transport2.connections))
        self.assertEqual(1, len(self.transport3.connections))
        self.assertEqual(2, len(self.connectedConnections))
        self.assertIs(self.connectedConnections[1], self.transport1.connections[1])
        self.assertEqual(self.bindAddress3, self.transport1.connections[1].remoteAddress)
        self.assertIsInstance(self.transport3.connections[0].bindPort, int)
        self.assertIsInstance(self.transport3.connections[0].id, basestring)
        self.assertEqual(self.bindPort1, self.transport1.connections[0].bindPort)
        self.assertEqual(self.bindAddress1, self.transport3.connections[0].remoteAddress)
        self.assertIsInstance(self.transport1.connections[0].remotePort, int)
        self.assertEqual(self.bindPort1, self.transport3.connections[0].remotePort)

    def run_04_attemptSecondBind(self):
        self.assertFalse(self.bindHasFailed)
        transport = SimulatedSIPTransport(self.bindAddress1, self.bindPort1)
        transport.whenEventDo("bindFailed", self.bindFailedEventHandler)
        transport.bind()
        self.assertTrue(self.bindHasFailed)

    def run_05_attemptConnectToBogusAddressAndPort(self):
        self.assertEqual(0, len(self.notConnectedAddressesAndPorts))
        self.assertEqual(2, len(self.transport1.connections))
        self.transport1.connectToAddressAndPort('192.168.4.254', 5060)
        self.assertEqual(1, len(self.notConnectedAddressesAndPorts))
        self.assertEqual(2, len(self.transport1.connections))
        self.assertEqual(('192.168.4.254', 5060), self.notConnectedAddressesAndPorts[0])
        self.transport1.connectToAddressAndPort(self.bindAddress2, 5555)
        self.assertEqual(2, len(self.notConnectedAddressesAndPorts))
        self.assertEqual(2, len(self.transport1.connections))
        self.assertEqual((self.bindAddress2, 5555), self.notConnectedAddressesAndPorts[1])

    def run_06_attemptConnectToOwnAddressAndPort(self):
        self.assertEqual(2, len(self.notConnectedAddressesAndPorts))
        self.assertEqual(2, len(self.transport1.connections))
        self.transport1.connectToAddressAndPort(self.bindAddress1, self.bindPort1)
        self.assertEqual(3, len(self.notConnectedAddressesAndPorts))
        self.assertEqual(2, len(self.transport1.connections))
        self.assertEqual((self.bindAddress1, self.bindPort1), self.notConnectedAddressesAndPorts[2])

    def run_07_sendRequestsVerifyReceipt(self):
        self.assertTrue(self.sampleRequest.isRequest)
        self.assertTrue(self.sampleRequest2.isRequest)
        self.assertEqual(0, len(self.receivedRequests))
        self.assertEqual(0, len(self.receivedResponses))
        self.transport2.connections[0].sendMessage(self.sampleRequest)
        self.assertEqual(1, len(self.receivedRequests))
        self.assertEqual(0, len(self.receivedResponses))
        self.assertIs(self.sampleRequest.__class__, self.receivedRequests[0].sipMessage.__class__)
        self.assertEqual(self.sampleRequest.rawString, self.receivedRequests[0].sipMessage.rawString)
        self.transport3.connections[0].sendMessage(self.sampleRequest2)
        self.assertEqual(2, len(self.receivedRequests))
        self.assertEqual(0, len(self.receivedResponses))
        self.assertIs(self.sampleRequest2.__class__, self.receivedRequests[1].sipMessage.__class__)
        self.assertEqual(self.sampleRequest2.rawString, self.receivedRequests[1].sipMessage.rawString)

    def run_08_sendResponsesVerifyReceipt(self):
        self.assertTrue(self.sampleResponse.isResponse)
        self.assertTrue(self.sampleResponse2.isResponse)
        self.assertEqual(2, len(self.receivedRequests))
        self.assertEqual(0, len(self.receivedResponses))
        self.transport2.connections[0].sendMessage(self.sampleResponse)
        self.assertEqual(2, len(self.receivedRequests))
        self.assertEqual(1, len(self.receivedResponses))
        self.assertIs(self.sampleResponse.__class__, self.receivedResponses[0].sipMessage.__class__)
        self.assertEqual(self.sampleResponse.rawString, self.receivedResponses[0].sipMessage.rawString)
        self.transport3.connections[0].sendMessage(self.sampleResponse2)
        self.assertEqual(2, len(self.receivedRequests))
        self.assertEqual(2, len(self.receivedResponses))
        self.assertIs(self.sampleResponse2.__class__, self.receivedResponses[1].sipMessage.__class__)
        self.assertEqual(self.sampleResponse2.rawString, self.receivedResponses[1].sipMessage.rawString)

    def boundEventHandler(self):
        self.hasBound = True

    def bindFailedEventHandler(self):
        self.bindHasFailed = True

    def madeConnectionEventHandler(self, aSimulatedSIPTransportConnection):
        self.connectedConnections.append(aSimulatedSIPTransportConnection)

    def couldNotMakeConnectionEventHandler(self, bindAddressAndPort):
        addressAndPort = bindAddressAndPort
        self.notConnectedAddressesAndPorts.append(addressAndPort)

    def lostConnectionEventHandler(self, aSimulatedSIPTransportConnection):
        if aSimulatedSIPTransportConnection in self.connectedConnections:
            self.connectedConnections.remove(aSimulatedSIPTransportConnection)

    def receivedValidConnectedRequestEventHandler(self, aConnectedSIPMessage):
        print "receivedValidConnectedRequestEventHandler"
        self.receivedRequests.append(aConnectedSIPMessage)

    def receivedValidConnectedResponseEventHandler(self, aConnectedSIPMessage):
        print "receivedValidConnectedResponseEventHandler"
        self.receivedResponses.append(aConnectedSIPMessage)
 def run_04_attemptSecondBind(self):
     self.assertFalse(self.bindHasFailed)
     transport = SimulatedSIPTransport(self.bindAddress1, self.bindPort1)
     transport.whenEventDo("bindFailed", self.bindFailedEventHandler)
     transport.bind()
     self.assertTrue(self.bindHasFailed)