def disco_caps(q, stream, presence): c_nodes = xpath.queryForNodes('/presence/c', presence.stanza) assert c_nodes is not None assertLength(1, c_nodes) hash = c_nodes[0].attributes['hash'] ver = c_nodes[0].attributes['ver'] node = c_nodes[0].attributes['node'] assertEquals('sha-1', hash) # ask caps request = \ elem_iq(stream, 'get', from_='[email protected]/resource')( elem(ns.DISCO_INFO, 'query', node=(node + '#' + ver)) ) stream.send(request) # receive caps event = q.expect('stream-iq', query_ns=ns.DISCO_INFO, iq_id=request['id']) # Check that Gabble's announcing the identity we think it should be. (identities, features, dataforms) = extract_disco_parts(event.stanza) # Check if the hash matches the announced capabilities assertEquals(compute_caps_hash(identities, features, dataforms), ver) return (event, features, dataforms)
def _cb_disco_iq(self, iq): nodes = xpath.queryForNodes("/iq/query", iq) query = nodes[0] if query.getAttribute('node') is None: return node = query.attributes['node'] ver = node.replace("http://telepathy.freedesktop.org/caps#", "") if iq.getAttribute('type') == 'result': if FileTransferTest.caps_identities is None or \ FileTransferTest.caps_features is None: identity_nodes = xpath.queryForNodes('/iq/query/identity', iq) assertLength(1, identity_nodes) identity_node = identity_nodes[0] identity_category = identity_node['category'] identity_type = identity_node['type'] identity_name = identity_node['name'] identity = '%s/%s//%s' % (identity_category, identity_type, identity_name) FileTransferTest.caps_identities = [identity] FileTransferTest.caps_features = [] for feature in xpath.queryForNodes('/iq/query/feature', iq): FileTransferTest.caps_features.append(feature['var']) # Check if the hash matches the announced capabilities assertEquals(compute_caps_hash(FileTransferTest.caps_identities, FileTransferTest.caps_features, {}), ver) if ver == FileTransferTest.caps_ft: caps_share = compute_caps_hash(FileTransferTest.caps_identities, FileTransferTest.caps_features + \ [ns.GOOGLE_FEAT_SHARE], {}) n = query.attributes['node'].replace(ver, caps_share) query.attributes['node'] = n for feature in xpath.queryForNodes('/iq/query/feature', iq): query.children.remove(feature) for f in FileTransferTest.caps_features + [ns.GOOGLE_FEAT_SHARE]: el = domish.Element((None, 'feature')) el['var'] = f query.addChild(el) elif iq.getAttribute('type') == 'get': caps_share = compute_caps_hash(FileTransferTest.caps_identities, FileTransferTest.caps_features + \ [ns.GOOGLE_FEAT_SHARE], {}) if ver == caps_share: n = query.attributes['node'].replace(ver, FileTransferTest.caps_ft) query.attributes['node'] = n
def run_test(q, bus, conn, stream, jt, decloak_allowed): """ Requests streams on a media channel to jt.remote_jid without having their presence at all. """ call_async(q, conn.Requests, 'CreateChannel', { cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_CALL, cs.TARGET_HANDLE_TYPE: cs.HT_CONTACT, cs.TARGET_ID: jt.peer, cs.CALL_INITIAL_AUDIO: True, cs.CALL_INITIAL_VIDEO: False, }) e = q.expect('stream-presence', to=jt.peer_bare_jid, presence_type=None) nodes = [ node for node in e.stanza.elements(uri=ns.TEMPPRES, name='temppres') ] assertLength(1, nodes) assertEquals('media', nodes[0].getAttribute('reason')) if decloak_allowed: jt.send_presence_and_caps() # RequestStreams should now happily complete q.expect('dbus-return', method='CreateChannel') else: q.expect('dbus-error', method='CreateChannel', name=cs.OFFLINE)
def check_neither(q, conn, bus, stream, remote_handle): """ Make a channel without specifying InitialAudio or InitialVideo; check that it's announced with both False, and that they're both present and false in GetAll(). """ path, props = conn.Requests.CreateChannel({ cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_STREAMED_MEDIA, cs.TARGET_HANDLE_TYPE: cs.HT_CONTACT, cs.TARGET_HANDLE: remote_handle}) assertContains((cs.INITIAL_AUDIO, False), props.items()) assertContains((cs.INITIAL_VIDEO, False), props.items()) chan = wrap_channel(bus.get_object(conn.bus_name, path), cs.CHANNEL_TYPE_STREAMED_MEDIA, ['MediaSignalling']) props = chan.Properties.GetAll(cs.CHANNEL_TYPE_STREAMED_MEDIA) assertContains(('InitialAudio', False), props.items()) assertContains(('InitialVideo', False), props.items()) # We shouldn't have started a session yet, so there shouldn't be any # session handlers. Strictly speaking, there could be a session handler # with no stream handlers, but... session_handlers = chan.MediaSignalling.GetSessionHandlers() assertLength(0, session_handlers)
def test(q, bus, conn, stream): conn.Connect() q.expect('dbus-signal', signal='StatusChanged', args=[cs.CONN_STATUS_CONNECTED, cs.CSR_REQUESTED]) chan = join(q, bus, conn) stream.sendMessage('PRIVMSG', CHANNEL, ":who's underlined you?", prefix='marnie') q.expect('dbus-signal', signal='MessageReceived') # Without acking the message, destroy the channel. call_async(q, chan.Destroyable, "Destroy") q.expect_many( EventPattern('stream-PART'), EventPattern('dbus-signal', signal='Closed', path=chan.object_path), EventPattern('dbus-signal', signal='ChannelClosed', args=[chan.object_path]), EventPattern('dbus-return', method='Destroy'), ) # Now Create it again. If we haven't actually left the channel, this will # fail. chan = join(q, bus, conn) # The message should be gone. messages = chan.Properties.Get(cs.CHANNEL_IFACE_MESSAGES, 'PendingMessages') assertLength(0, messages)
def sending_request_to_cappy_contact(q, bus, conn, stream, chan): """ Test that Gabble requests a receipt from a contact whom we know supports this extension, but only if asked. """ # Convince Gabble that Guybrush supports this extension caps = { 'node': 'http://whatever', 'ver': caps_helper.compute_caps_hash([], [ns.RECEIPTS], {}), 'hash': 'sha-1', } caps_helper.presence_and_disco(q, conn, stream, GUYBRUSH_FULL_JID, disco=True, client=caps['node'], caps=caps, features=[ns.RECEIPTS]) sync_stream(q, stream) # Don't ask, don't tell — even if we know Guybrush does support this. not_sending_request_to_contact(q, bus, conn, stream, chan) # Ask, tell. message = [ { 'message-type': cs.MT_NORMAL, }, { 'content-type': 'text/plain', 'content': 'Ulysses?', }] chan.Messages.SendMessage(message, cs.MSG_SENDING_FLAGS_REPORT_DELIVERY) e = q.expect('stream-message', to=GUYBRUSH) assertLength(1, list(e.stanza.elements(uri=ns.RECEIPTS, name='request')))
def try_to_join_muc(q, bus, conn, stream, muc, request=None): """ Ask Gabble to join a MUC, and expect it to send <presence/> Returns: the stream-presence Event object. """ if request is None: request = { cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_TEXT, cs.TARGET_HANDLE_TYPE: cs.HT_ROOM, cs.TARGET_ID: muc, } call_async(q, conn.Requests, 'CreateChannel', dbus.Dictionary(request, signature='sv')) join_event = q.expect('stream-presence', to='%s/test' % muc) # XEP-0045 §7.1.2 sez: # “MUC clients SHOULD signal their ability to speak the MUC protocol by # including in the initial presence stanza an empty <x/> element # qualified by the 'http://jabber.org/protocol/muc' namespace.” x_muc_nodes = xpath.queryForNodes('/presence/x[@xmlns="%s"]' % ns.MUC, join_event.stanza) assertLength(1, x_muc_nodes) return join_event
def test(q, bus, conn, stream): """ Check that when we receive a roster update we emit a single AliasesChanged for all the contacts. """ conn.Connect() # Gabble asks the server for the initial roster event = q.expect('stream-iq', iq_type='get', query_ns=ns.ROSTER) result = make_result_iq(stream, event.stanza) # We reply with a roster with two contacts bob_jid = '*****@*****.**' bob_alias = 'Bob Smith' add_contact(result, bob_jid, bob_alias) alice_jid = '*****@*****.**' alice_alias = 'Alice' add_contact(result, alice_jid, alice_alias) stream.send(result) # Check we get a single AliasesChanged for both contacts event = q.expect('dbus-signal', signal='AliasesChanged') added = event.args[0] bob_handle, alice_handle = conn.get_contact_handles_sync( [bob_jid, alice_jid]) assertLength(2, added) assertContains((bob_handle, bob_alias), added) assertContains((alice_handle, alice_alias), added)
def incoming(jp, q, bus, conn, stream): remote_jid = 'skinny.fists@heaven/antennas' jt = JingleTest2(jp, conn, q, stream, 'test@localhost', remote_jid) jt.prepare() self_handle = conn.GetSelfHandle() remote_handle = conn.RequestHandles(cs.HT_CONTACT, [remote_jid])[0] for a, v in [(True, False), (False, True), (True, True)]: if v and not jp.can_do_video(): continue if not a and v and not jp.can_do_video_only(): continue jt.incoming_call(audio=a, video=v) e = q.expect('dbus-signal', signal='NewChannels') chans = e.args[0] assertLength(1, chans) path, props = chans[0] assertEquals(cs.CHANNEL_TYPE_STREAMED_MEDIA, props[cs.CHANNEL_TYPE]) assertEquals(a, props[cs.INITIAL_AUDIO]) assertEquals(v, props[cs.INITIAL_VIDEO]) chan = wrap_channel(bus.get_object(conn.bus_name, path), cs.CHANNEL_TYPE_STREAMED_MEDIA) chan.Close()
def test(q, bus, conn, stream): conn.Connect() q.expect('dbus-signal', signal='StatusChanged', args=[0, 1]) e = q.expect('stream-PING') assertLength(1, e.data) timestamp = e.data[0] stream.sendMessage('PONG', 'idle.test.server', ':%s' % timestamp, prefix='idle.test.server') # Apparently bip replies like this: e = q.expect('stream-PING') assertLength(1, e.data) timestamp = e.data[0] stream.sendMessage('PONG', timestamp, prefix='idle.test.server') q.expect('stream-PING') # If we don't answer Idle's ping, after some period of time Idle should # give up and close the connection. q.expect_many( EventPattern('irc-disconnected'), EventPattern('dbus-signal', signal='StatusChanged', args=[cs.CONN_STATUS_DISCONNECTED, cs.CSR_NETWORK_ERROR]), )
def test_contact_blocking(q, bus, conn, stream, stored, deny): """test ContactBlocking API""" assertContains(cs.CONN_IFACE_CONTACT_BLOCKING, conn.Properties.Get(cs.CONN, "Interfaces")) # 3 contacts are blocked blocked = conn.RequestBlockedContacts(dbus_interface=cs.CONN_IFACE_CONTACT_BLOCKING) assertLength(3, blocked)
def check_contact_list_signals(q, bus, conn, signals, ht, name, contacts, lp_contacts=[], rp_contacts=[]): """ Looks at NewChannel and NewChannels signals for the contact list with ID 'name' and checks that its members, lp members and rp members are exactly 'contacts', 'lp_contacts' and 'rp_contacts'. Returns a proxy for the channel. """ old_signal, new_signal = signals path, type, handle_type, handle, suppress_handler = old_signal.args assertEquals(cs.CHANNEL_TYPE_CONTACT_LIST, type) assertEquals(name, conn.InspectHandles(handle_type, [handle])[0]) chan = wrap_channel(bus.get_object(conn.bus_name, path), cs.CHANNEL_TYPE_CONTACT_LIST) members = chan.Group.GetMembers() assertEquals(sorted(contacts), sorted(conn.InspectHandles(cs.HT_CONTACT, members))) lp_handles = conn.RequestHandles(cs.HT_CONTACT, lp_contacts) rp_handles = conn.RequestHandles(cs.HT_CONTACT, rp_contacts) # NB. comma: we're unpacking args. Thython! info, = new_signal.args assertLength(1, info) # one channel path_, emitted_props = info[0] assertEquals(path_, path) assertEquals(cs.CHANNEL_TYPE_CONTACT_LIST, emitted_props[cs.CHANNEL_TYPE]) assertEquals(ht, emitted_props[cs.TARGET_HANDLE_TYPE]) assertEquals(handle, emitted_props[cs.TARGET_HANDLE]) channel_props = chan.Properties.GetAll(cs.CHANNEL) assertEquals(handle, channel_props.get('TargetHandle')) assertEquals(ht, channel_props.get('TargetHandleType')) assertEquals(cs.CHANNEL_TYPE_CONTACT_LIST, channel_props.get('ChannelType')) assertContains(cs.CHANNEL_IFACE_GROUP, channel_props.get('Interfaces')) assertEquals(name, channel_props['TargetID']) assertEquals(False, channel_props['Requested']) assertEquals('', channel_props['InitiatorID']) assertEquals(0, channel_props['InitiatorHandle']) group_props = chan.Properties.GetAll(cs.CHANNEL_IFACE_GROUP) assertContains('HandleOwners', group_props) assertContains('Members', group_props) assertEquals(members, group_props['Members']) assertContains('LocalPendingMembers', group_props) actual_lp_handles = [x[0] for x in group_props['LocalPendingMembers']] assertEquals(sorted(lp_handles), sorted(actual_lp_handles)) assertContains('RemotePendingMembers', group_props) assertEquals(sorted(rp_handles), sorted(group_props['RemotePendingMembers'])) assertContains('GroupFlags', group_props) return chan
def add_content(self, content_path, initial=False, incoming=None): if initial: incoming = self.incoming else: assert incoming is not None content = self.bus.get_object(self.conn.bus_name, content_path) content_props = content.GetAll(cs.CALL_CONTENT) if initial: assertEquals(cs.CALL_DISPOSITION_INITIAL, content_props['Disposition']) if content_props['Type'] == cs.MEDIA_STREAM_TYPE_AUDIO: assertEquals(self.initial_audio_content_name, content_props['Name']) elif content_props['Type'] == cs.MEDIA_STREAM_TYPE_VIDEO: assertEquals(self.initial_video_content_name, content_props['Name']) else: assert Fale else: assertEquals(cs.CALL_DISPOSITION_NONE, content_props['Disposition']) content.media_type = content_props['Type'] cmedia_props = content.GetAll(cs.CALL_CONTENT_IFACE_MEDIA) assertLength(0, cmedia_props['RemoteMediaDescriptions']) assertLength(0, cmedia_props['LocalMediaDescriptions']) if incoming: assertNotEquals('/', cmedia_props['MediaDescriptionOffer'][0]) else: assertNotEquals('/', cmedia_props['MediaDescriptionOffer'][0]) assertEquals(cs.CALL_CONTENT_PACKETIZATION_RTP, cmedia_props['Packetization']) assertEquals(cs.CALL_SENDING_STATE_NONE, cmedia_props['CurrentDTMFState']) self.contents.append(content) self.__add_stream(content, content_props['Streams'][0], initial, incoming) if incoming: md = self.bus.get_object(self.conn.bus_name, cmedia_props['MediaDescriptionOffer'][0]) md.Accept(self.context.get_audio_md_dbus(self.remote_handle)) o = self.q.expect_many( EventPattern('dbus-signal', signal='MediaDescriptionOfferDone'), EventPattern('dbus-signal', signal='LocalMediaDescriptionChanged'), EventPattern('dbus-signal', signal='RemoteMediaDescriptionsChanged')) return content
def test(q, bus, conn, stream): event = q.expect('stream-iq', query_ns=ns.ROSTER) event.stanza['type'] = 'result' item = event.query.addElement('item') item['jid'] = '*****@*****.**' item['subscription'] = 'both' item.addElement('group', content='women') item.addElement('group', content='affected-by-fdo-12791') # This is a broken roster - Amy appears twice. This should only happen # if the server is somehow buggy. This was my initial attempt at # reproducing fd.o #12791 - I doubt it's very realistic, but we shouldn't # assert, regardless of what input we get! item = event.query.addElement('item') item['jid'] = '*****@*****.**' item['subscription'] = 'both' item.addElement('group', content='women') item = event.query.addElement('item') item['jid'] = '*****@*****.**' item['subscription'] = 'from' item.addElement('group', content='men') # This is what was *actually* strange about the #12791 submitter's roster - # Bob appears, fully subscribed, but also there's an attempt to subscribe # to one of Bob's resources. We now ignore such items item = event.query.addElement('item') item['jid'] = '[email protected]/Resource' item['subscription'] = 'none' item['ask'] = 'subscribe' item = event.query.addElement('item') item['jid'] = '*****@*****.**' item['subscription'] = 'to' item.addElement('group', content='men') stream.send(event.stanza) pairs = expect_contact_list_signals(q, bus, conn, ['publish', 'subscribe', 'stored'], ['men', 'women', 'affected-by-fdo-12791']) check_contact_list_signals(q, bus, conn, pairs.pop(0), cs.HT_LIST, 'publish', ['*****@*****.**', '*****@*****.**']) check_contact_list_signals(q, bus, conn, pairs.pop(0), cs.HT_LIST, 'subscribe', ['*****@*****.**', '*****@*****.**']) check_contact_list_signals(q, bus, conn, pairs.pop(0), cs.HT_LIST, 'stored', ['*****@*****.**', '*****@*****.**', '*****@*****.**']) check_contact_list_signals(q, bus, conn, pairs.pop(0), cs.HT_GROUP, 'men', ['*****@*****.**', '*****@*****.**']) check_contact_list_signals(q, bus, conn, pairs.pop(0), cs.HT_GROUP, 'women', ['*****@*****.**']) check_contact_list_signals(q, bus, conn, pairs.pop(0), cs.HT_GROUP, 'affected-by-fdo-12791', []) assertLength(0, pairs) # i.e. we've checked all of them
def general_tests (jp, q, bus, conn, stream, path, props): assertEquals (cs.HT_ROOM, props[cs.TARGET_HANDLE_TYPE]) channel = bus.get_object (conn.bus_name, path) chan_props = channel.GetAll (cs.CHANNEL_TYPE_CALL, dbus_interface = dbus.PROPERTIES_IFACE) contents = chan_props['Contents'] assertLength(1, contents)
def test_contact_blocking(q, bus, conn, stream): """test ContactBlocking API""" assertContains(cs.CONN_IFACE_CONTACT_BLOCKING, conn.Properties.Get(cs.CONN, "Interfaces")) # 3 contacts are blocked blocked = conn.RequestBlockedContacts(dbus_interface=cs.CONN_IFACE_CONTACT_BLOCKING) assertLength(3, blocked)
def test(q, bus, conn, stream): conn.Connect() _, event = q.expect_many( EventPattern('dbus-signal', signal='StatusChanged', args=[cs.CONN_STATUS_CONNECTED, cs.CSR_REQUESTED]), EventPattern('stream-iq', to=None, query_ns='vcard-temp', query_name='vCard')) acknowledge_iq(stream, event.stanza) handle = conn.RequestHandles(cs.HT_CONTACT, ['*****@*****.**'])[0] call_async(q, conn.Aliasing, 'RequestAliases', [handle]) event = q.expect('stream-iq', to='*****@*****.**', iq_type='get', query_ns=ns.PUBSUB, query_name='pubsub') items = event.query.firstChildElement() assertEquals('items', items.name) assertEquals(ns.NICK, items['node']) result = make_result_iq(stream, event.stanza) pubsub = result.firstChildElement() items = pubsub.addElement('items') items['node'] = ns.NICK item = items.addElement('item') item.addElement('nick', ns.NICK, content='Bobby') stream.send(result) q.expect('dbus-signal', signal='AliasesChanged', args=[[(handle, u'Bobby')]]) q.expect('dbus-return', method='RequestAliases', value=(['Bobby'],)) # A second request should be satisfied from the cache. assertEquals(['Bobby'], conn.Aliasing.RequestAliases([handle])) # Bobby grows up, decides he hates his nickname. # This is a regression test for # <https://bugs.freedesktop.org/show_bug.cgi?id=21817>, where this would # crash Gabble. message = elem('message', from_='*****@*****.**')( elem((ns.PUBSUB + "#event"), 'event')( elem('items', node=ns.NICK)( elem('item')( elem(ns.NICK, 'nick') ) ) ) ) stream.send(message.toXml()) event = q.expect('dbus-signal', signal='AliasesChanged') aliases = event.args[0] assertLength(1, aliases) h, a = aliases[0] assertEquals(handle, h) # The contact explicitly cleared their PEP nick; Gabble should fall back to # their JID. assertEquals(a, '*****@*****.**')
def reject_start_receiving(self, content): self.stop_receiving(content) content.stream.RequestReceiving(self.remote_handle, True) self.q.expect('dbus-signal', signal='ReceivingStateChanged', args=[cs.CALL_STREAM_FLOW_STATE_PENDING_START], path=content.stream.__dbus_object_path__), content.stream.Media.CompleteReceivingStateChange( cs.CALL_STREAM_FLOW_STATE_STARTED) o = self.q.expect_many( EventPattern('dbus-signal', signal='ReceivingStateChanged', args=[cs.CALL_STREAM_FLOW_STATE_STARTED], path=content.stream.__dbus_object_path__), EventPattern('dbus-signal', signal='RemoteMembersChanged', path=content.stream.__dbus_object_path__), EventPattern('sip-invite')) assertLength(0, o[1].args[2]) assertLength(1, o[1].args[0]) assertEquals(cs.CALL_SENDING_STATE_PENDING_SEND, o[1].args[0][self.remote_handle]) assertEquals(self.self_handle, o[1].args[3][0]) assertEquals(cs.CALL_STATE_CHANGE_REASON_USER_REQUESTED, o[1].args[3][1]) reinvite_event = o[2] assertDoesNotContain('a=sendonly', reinvite_event.sip_message.body) assertDoesNotContain('a=inactive', reinvite_event.sip_message.body) self.context.check_call_sdp(reinvite_event.sip_message.body) body = reinvite_event.sip_message.body + 'a=recvonly\r\r' self.context.accept(reinvite_event.sip_message, body) ack_cseq = "%s ACK" % reinvite_event.cseq.split()[0] self.q.expect_many(EventPattern('sip-ack', cseq=ack_cseq)) # Now let's restart receiving for real self.receiving = True self.context.reinvite() acc, rmb = self.q.expect_many( EventPattern('sip-response', code=200), EventPattern('dbus-signal', signal='RemoteMembersChanged', path=content.stream.__dbus_object_path__, predicate=lambda e: e.args[0] == {self.remote_handle: cs.CALL_SENDING_STATE_SENDING})) self.context.check_call_sdp(acc.sip_message.body, self.medias) self.context.ack(acc.sip_message)
def check_endpoint(self, content, endpoint_path): endpoint = self.bus.get_object(self.conn.bus_name, endpoint_path) endpoint_props = endpoint.GetAll(cs.CALL_STREAM_ENDPOINT) assertEquals(('', ''), endpoint_props['RemoteCredentials']) assertEquals(self.context.get_remote_candidates_dbus(), endpoint_props['RemoteCandidates']) assertLength(0, endpoint_props['EndpointState']) assertEquals(cs.CALL_STREAM_TRANSPORT_RAW_UDP, endpoint_props['Transport']) assertEquals(False, endpoint_props['IsICELite'])
def check_endpoint(self, content, endpoint_path): endpoint = self.bus.get_object(self.conn.bus_name, endpoint_path) endpoint_props = endpoint.GetAll(cs.CALL_STREAM_ENDPOINT) assertEquals(('',''), endpoint_props['RemoteCredentials']) assertEquals(self.context.get_remote_candidates_dbus(), endpoint_props['RemoteCandidates']) assertLength(0, endpoint_props['EndpointState']) assertEquals(cs.CALL_STREAM_TRANSPORT_RAW_UDP, endpoint_props['Transport']) assertEquals(False, endpoint_props['IsICELite'])
def validate_pep_update(pep_update, expected_nickname): publish = next(pep_update.query.elements(uri=ns.PUBSUB, name='publish')) assertEquals(ns.NICK, publish['node']) item = next(publish.elements(uri=ns.PUBSUB, name='item')) nick = next(item.elements(uri=ns.NICK, name='nick')) if expected_nickname is not None: assertEquals(expected_nickname, nick.children[0]) else: assertLength(0, nick.children)
def validate_pep_update(pep_update, expected_nickname): publish = pep_update.query.elements(uri=ns.PUBSUB, name='publish').next() assertEquals(ns.NICK, publish['node']) item = publish.elements(uri=ns.PUBSUB, name='item').next() nick = item.elements(uri=ns.NICK, name='nick').next() if expected_nickname is not None: assertEquals(expected_nickname, nick.children[0]) else: assertLength(0, nick.children)
def not_sending_request_to_contact(q, bus, conn, stream, chan): message = [ { 'message-type': cs.MT_NORMAL, }, { 'content-type': 'text/plain', 'content': 'Mancomb Seepgood?', }] chan.Messages.SendMessage(message, 0) e = q.expect('stream-message', to=GUYBRUSH) assertLength(0, list(e.stanza.elements(uri=ns.RECEIPTS, name='request')))
def add_content(self, content_path, initial = False, incoming = None): if initial: incoming = self.incoming else: assert incoming is not None content = self.bus.get_object (self.conn.bus_name, content_path) content_props = content.GetAll(cs.CALL_CONTENT) if initial: assertEquals(cs.CALL_DISPOSITION_INITIAL, content_props['Disposition']) if content_props['Type'] == cs.MEDIA_STREAM_TYPE_AUDIO: assertEquals(self.initial_audio_content_name, content_props['Name']) elif content_props['Type'] == cs.MEDIA_STREAM_TYPE_VIDEO: assertEquals(self.initial_video_content_name, content_props['Name']) else: assert Fale else: assertEquals(cs.CALL_DISPOSITION_NONE, content_props['Disposition']) content.media_type = content_props['Type'] cmedia_props = content.GetAll(cs.CALL_CONTENT_IFACE_MEDIA) assertLength(0, cmedia_props['RemoteMediaDescriptions']) assertLength(0, cmedia_props['LocalMediaDescriptions']) if incoming: assertNotEquals('/', cmedia_props['MediaDescriptionOffer'][0]) else: assertNotEquals('/', cmedia_props['MediaDescriptionOffer'][0]) assertEquals(cs.CALL_CONTENT_PACKETIZATION_RTP, cmedia_props['Packetization']) assertEquals(cs.CALL_SENDING_STATE_NONE, cmedia_props['CurrentDTMFState']) self.contents.append(content) self.__add_stream(content, content_props['Streams'][0], initial, incoming) if incoming: md = self.bus.get_object (self.conn.bus_name, cmedia_props['MediaDescriptionOffer'][0]) md.Accept(self.context.get_audio_md_dbus(self.remote_handle)) o = self.q.expect_many( EventPattern('dbus-signal', signal='MediaDescriptionOfferDone'), EventPattern('dbus-signal', signal='LocalMediaDescriptionChanged'), EventPattern('dbus-signal', signal='RemoteMediaDescriptionsChanged')) return content
def test(q, bus, conn, stream): def send_own_message(to, text): iq = elem_iq(stream, 'set', from_='chat.facebook.com')(elem(NS_FACEBOOK_MESSAGES, 'own-message', to=to, self='false')( elem('body')(text))) stream.send(iq) q.expect('stream-iq', iq_type='result', iq_id=iq['id']) # First, test receiving an own-message stanza for a message sent to a # contact we have an open channel for. jid = '*****@*****.**' _, path, props = conn.Requests.EnsureChannel({ cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_TEXT, cs.TARGET_HANDLE_TYPE: cs.HT_CONTACT, cs.TARGET_ID: jid, }) channel = wrap_channel(bus.get_object(conn.bus_name, path), 'Text', ['Messages']) handle = props[cs.TARGET_HANDLE] text = u'omg omg its ur birthdayy <3 <3 xoxoxoxo' send_own_message(to=jid, text=text) e = q.expect('dbus-signal', signal='MessageReceived') message, = e.args assertLength(1, message) header = message[0] assertEquals(handle, header['message-sender']) assertEquals(cs.MT_DELIVERY_REPORT, header['message-type']) assertEquals(cs.DELIVERY_STATUS_ACCEPTED, header['delivery-status']) assertContains('delivery-echo', header) echo = header['delivery-echo'] echo_header, echo_body = echo assertEquals(conn.Properties.Get(cs.CONN, "SelfHandle"), echo_header['message-sender']) assertEquals('text/plain', echo_body['content-type']) assertEquals(text, echo_body['content']) channel.Text.AcknowledgePendingMessages([header['pending-message-id']]) channel.Close() # Now test receiving an own-message stanza for a message sent to a contact # we don't have a channel open for. It should be ignored (but acked). This # is consistent with delivery failure reports. q.forbid_events([EventPattern('dbus-signal', signal='MessageReceived')]) send_own_message(to='*****@*****.**', text=u'please ignore this message') sync_dbus(bus, q, conn)
def expect_sasl_channel(q, bus, conn): new_signal = q.expect('dbus-signal', signal='NewChannels', predicate=lambda e: e.args[0][0][1].get(cs.CHANNEL_TYPE) == cs.CHANNEL_TYPE_SERVER_AUTHENTICATION) path, props = new_signal.args[0][0] chan = SaslChannelWrapper(bus.get_object(conn.bus_name, path)) assertLength(1, new_signal.args[0]) assertEquals(cs.CHANNEL_IFACE_SASL_AUTH, props.get(cs.AUTH_METHOD)) return chan, props
def test(q, bus, conn, stream): event = q.expect('stream-iq', to=None, query_ns='vcard-temp', query_name='vCard') acknowledge_iq(stream, event.stanza) handle = conn.get_contact_handle_sync('*****@*****.**') call_async(q, conn.Aliasing, 'RequestAliases', [handle]) event = q.expect('stream-iq', to='*****@*****.**', iq_type='get', query_ns=ns.PUBSUB, query_name='pubsub') items = event.query.firstChildElement() assertEquals('items', items.name) assertEquals(ns.NICK, items['node']) result = make_result_iq(stream, event.stanza) pubsub = result.firstChildElement() items = pubsub.addElement('items') items['node'] = ns.NICK item = items.addElement('item') item.addElement('nick', ns.NICK, content='Bobby') stream.send(result) q.expect('dbus-signal', signal='AliasesChanged', args=[[(handle, u'Bobby')]]) q.expect('dbus-return', method='RequestAliases', value=(['Bobby'],)) # A second request should be satisfied from the cache. assertEquals(['Bobby'], conn.Aliasing.RequestAliases([handle])) # Bobby grows up, decides he hates his nickname. # This is a regression test for # <https://bugs.freedesktop.org/show_bug.cgi?id=21817>, where this would # crash Gabble. message = elem('message', from_='*****@*****.**')( elem((ns.PUBSUB_EVENT), 'event')( elem('items', node=ns.NICK)( elem('item')( elem(ns.NICK, 'nick') ) ) ) ) stream.send(message.toXml()) event = q.expect('dbus-signal', signal='AliasesChanged') aliases = event.args[0] assertLength(1, aliases) h, a = aliases[0] assertEquals(handle, h) # The contact explicitly cleared their PEP nick; Gabble should fall back to # their JID. assertEquals(a, '*****@*****.**')
def test(q, bus, conns, streams): conn1, conn2 = conns stream1, stream2 = streams # Connection 1 conn1.Connect() q.expect('dbus-signal', signal='StatusChanged', args=[cs.CONN_STATUS_CONNECTING, cs.CSR_REQUESTED], path=conn1.object.object_path) q.expect('stream-authenticated') q.expect('dbus-signal', signal='PresencesChanged', args=[{1L: (cs.PRESENCE_AVAILABLE, 'available', '')}], path=conn1.object.object_path) q.expect('dbus-signal', signal='StatusChanged', args=[cs.CONN_STATUS_CONNECTED, cs.CSR_REQUESTED], path=conn1.object.object_path) pairs = expect_contact_list_signals(q, bus, conn1, ['publish', 'subscribe', 'stored']) check_contact_list_signals(q, bus, conn1, pairs.pop(0), cs.HT_LIST, 'publish', []) check_contact_list_signals(q, bus, conn1, pairs.pop(0), cs.HT_LIST, 'subscribe', []) check_contact_list_signals(q, bus, conn1, pairs.pop(0), cs.HT_LIST, 'stored', []) assertLength(0, pairs) # i.e. we popped and checked all of them # Connection 2 conn2.Connect() q.expect('dbus-signal', signal='StatusChanged', args=[cs.CONN_STATUS_CONNECTING, cs.CSR_REQUESTED], path=conn2.object.object_path) q.expect('stream-authenticated') q.expect('dbus-signal', signal='PresencesChanged', args=[{1L: (cs.PRESENCE_AVAILABLE, 'available', '')}], path=conn2.object.object_path) q.expect('dbus-signal', signal='StatusChanged', args=[cs.CONN_STATUS_CONNECTED, cs.CSR_REQUESTED], path=conn2.object.object_path) pairs = expect_contact_list_signals(q, bus, conn2, ['publish', 'subscribe', 'stored']) check_contact_list_signals(q, bus, conn2, pairs.pop(0), cs.HT_LIST, 'publish', []) check_contact_list_signals(q, bus, conn2, pairs.pop(0), cs.HT_LIST, 'subscribe', []) check_contact_list_signals(q, bus, conn2, pairs.pop(0), cs.HT_LIST, 'stored', []) assertLength(0, pairs) # i.e. we popped and checked all of them
def reject_start_receiving(self, content): self.stop_receiving(content) content.stream.RequestReceiving(self.remote_handle, True) self.q.expect('dbus-signal', signal='ReceivingStateChanged', args=[cs.CALL_STREAM_FLOW_STATE_PENDING_START], path=content.stream.__dbus_object_path__), content.stream.Media.CompleteReceivingStateChange( cs.CALL_STREAM_FLOW_STATE_STARTED) o = self.q.expect_many( EventPattern('dbus-signal', signal='ReceivingStateChanged', args=[cs.CALL_STREAM_FLOW_STATE_STARTED], path=content.stream.__dbus_object_path__), EventPattern('dbus-signal', signal='RemoteMembersChanged', path=content.stream.__dbus_object_path__), EventPattern('sip-invite')) assertLength(0, o[1].args[2]) assertLength(1, o[1].args[0]) assertEquals(cs.CALL_SENDING_STATE_PENDING_SEND, o[1].args[0][self.remote_handle]) assertEquals(self.self_handle, o[1].args[3][0]) assertEquals(cs.CALL_STATE_CHANGE_REASON_USER_REQUESTED, o[1].args[3][1]) reinvite_event = o[2] assertDoesNotContain('a=sendonly', reinvite_event.sip_message.body) assertDoesNotContain('a=inactive', reinvite_event.sip_message.body) self.context.check_call_sdp(reinvite_event.sip_message.body) body = reinvite_event.sip_message.body + 'a=recvonly\r\r' self.context.accept(reinvite_event.sip_message, body) ack_cseq = "%s ACK" % reinvite_event.cseq.split()[0] self.q.expect_many( EventPattern('sip-ack', cseq=ack_cseq)) # Now let's restart receiving for real self.receiving = True self.context.reinvite() acc , rmb = self.q.expect_many( EventPattern('sip-response', code=200), EventPattern('dbus-signal', signal='RemoteMembersChanged', path=content.stream.__dbus_object_path__, predicate=lambda e: e.args[0] == {self.remote_handle: cs.CALL_SENDING_STATE_SENDING})) self.context.check_call_sdp(acc.sip_message.body, self.medias) self.context.ack(acc.sip_message)
def receive_presence_and_ask_caps(q, stream, expect_dbus=True): # receive presence stanza if expect_dbus: presence, event_dbus = q.expect_many( EventPattern('stream-presence'), EventPattern('dbus-signal', signal='ContactCapabilitiesChanged')) assertLength(1, event_dbus.args) signaled_caps = event_dbus.args[0] else: presence = q.expect('stream-presence') signaled_caps = None return disco_caps(q, stream, presence) + (signaled_caps, )
def test(q, bus, conn, stream): def send_own_message(to, text): iq = elem_iq(stream, 'set', from_='chat.facebook.com')( elem(NS_FACEBOOK_MESSAGES, 'own-message', to=to, self='false')( elem('body')(text) ) ) stream.send(iq) q.expect('stream-iq', iq_type='result', iq_id=iq['id']) # First, test receiving an own-message stanza for a message sent to a # contact we have an open channel for. jid = '*****@*****.**' _, path, props = conn.Requests.EnsureChannel({ cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_TEXT, cs.TARGET_HANDLE_TYPE: cs.HT_CONTACT, cs.TARGET_ID: jid, }) channel = wrap_channel(bus.get_object(conn.bus_name, path), 'Text', ['Messages']) handle = props[cs.TARGET_HANDLE] text = u'omg omg its ur birthdayy <3 <3 xoxoxoxo' send_own_message(to=jid, text=text) e = q.expect('dbus-signal', signal='MessageReceived') message, = e.args assertLength(1, message) header = message[0] assertEquals(handle, header['message-sender']) assertEquals(cs.MT_DELIVERY_REPORT, header['message-type']) assertEquals(cs.DELIVERY_STATUS_ACCEPTED, header['delivery-status']) assertContains('delivery-echo', header) echo = header['delivery-echo'] echo_header, echo_body = echo assertEquals(conn.GetSelfHandle(), echo_header['message-sender']) assertEquals('text/plain', echo_body['content-type']) assertEquals(text, echo_body['content']) channel.Text.AcknowledgePendingMessages([header['pending-message-id']]) channel.Close() # Now test receiving an own-message stanza for a message sent to a contact # we don't have a channel open for. It should be ignored (but acked). This # is consistent with delivery failure reports. q.forbid_events([EventPattern('dbus-signal', signal='MessageReceived')]) send_own_message(to='*****@*****.**', text=u'please ignore this message') sync_dbus(bus, q, conn)
def rccs(q, bus, conn, stream): """ Tests that the connection's RequestableChannelClasses for StreamedMedia are sane. """ rccs = conn.Properties.Get(cs.CONN_IFACE_REQUESTS, 'RequestableChannelClasses') # Test Channel.Type.StreamedMedia media_classes = [ rcc for rcc in rccs if rcc[0][cs.CHANNEL_TYPE] == cs.CHANNEL_TYPE_STREAMED_MEDIA ] assertLength(1, media_classes) fixed, allowed = media_classes[0] assertEquals(cs.HT_CONTACT, fixed[cs.TARGET_HANDLE_TYPE]) expected_allowed = [ cs.TARGET_ID, cs.TARGET_HANDLE, cs.INITIAL_VIDEO, cs.INITIAL_AUDIO ] allowed.sort() expected_allowed.sort() assertEquals(expected_allowed, allowed) # Test Channel.Type.Call media_classes = [ rcc for rcc in rccs if rcc[0][cs.CHANNEL_TYPE] == cs.CHANNEL_TYPE_CALL ] assertLength(2, media_classes) hts = [] for mc in media_classes: fixed, allowed = mc hts.append (fixed[cs.TARGET_HANDLE_TYPE]) expected_allowed = [ cs.TARGET_ID, cs.TARGET_HANDLE, cs.CALL_INITIAL_VIDEO, cs.CALL_INITIAL_AUDIO, cs.CALL_INITIAL_VIDEO_NAME, cs.CALL_INITIAL_AUDIO_NAME, cs.CALL_MUTABLE_CONTENTS ] allowed.sort() expected_allowed.sort() assertEquals(expected_allowed, allowed) assertEquals(sorted([cs.HT_CONTACT, cs.HT_ROOM]), sorted(hts))
def receive_presence_and_ask_caps(q, stream, expect_dbus=True): # receive presence stanza if expect_dbus: presence, event_dbus = q.expect_many( EventPattern('stream-presence'), EventPattern('dbus-signal', signal='ContactCapabilitiesChanged') ) assertLength(1, event_dbus.args) signaled_caps = event_dbus.args[0] else: presence = q.expect('stream-presence') signaled_caps = None return disco_caps(q, stream, presence) + (signaled_caps,)
def test_connect_disconnect_endpoint(self): endpoints = self.audio_stream.Get(cs.CALL_STREAM_IFACE_MEDIA, "Endpoints", dbus_interface=dbus.PROPERTIES_IFACE) assertLength(1, endpoints) endpoint = self.bus.get_object(self.conn.bus_name, endpoints[0]) # Lets try disconnecting one endpoint.SetEndpointState(1, cs.CALL_STREAM_ENDPOINT_STATE_CONNECTING, dbus_interface=cs.CALL_STREAM_ENDPOINT) ret = self.q.expect_many( EventPattern('dbus-signal', signal='EndpointStateChanged'), EventPattern('dbus-signal', signal='CallStateChanged')) assertEquals(1, ret[0].args[0]) assertEquals(cs.CALL_STREAM_ENDPOINT_STATE_CONNECTING, ret[0].args[1]) assertEquals(cs.CALL_STATE_ACCEPTED, ret[1].args[0]) state = endpoint.Get(cs.CALL_STREAM_ENDPOINT, "EndpointState", dbus_interface=dbus.PROPERTIES_IFACE) assertEquals(cs.CALL_STREAM_ENDPOINT_STATE_CONNECTING, state[1]) # And reconnecting it endpoint.SetEndpointState( 1, cs.CALL_STREAM_ENDPOINT_STATE_FULLY_CONNECTED, dbus_interface=cs.CALL_STREAM_ENDPOINT) ret = self.q.expect_many( EventPattern('dbus-signal', signal='EndpointStateChanged'), EventPattern('dbus-signal', signal='CallStateChanged')) assertEquals(1, ret[0].args[0]) assertEquals(cs.CALL_STREAM_ENDPOINT_STATE_FULLY_CONNECTED, ret[0].args[1]) assertEquals(cs.CALL_STATE_ACTIVE, ret[1].args[0]) state = endpoint.Get(cs.CALL_STREAM_ENDPOINT, "EndpointState", dbus_interface=dbus.PROPERTIES_IFACE) assertEquals(cs.CALL_STREAM_ENDPOINT_STATE_FULLY_CONNECTED, state[1]) # All Direction should still be both now stream_props = self.audio_stream.GetAll( cs.CALL_STREAM, dbus_interface=dbus.PROPERTIES_IFACE) assertEquals({self.peer_handle: cs.CALL_SENDING_STATE_SENDING}, stream_props["RemoteMembers"]) assertEquals(cs.CALL_SENDING_STATE_SENDING, stream_props["LocalSendingState"])
def expect_sasl_channel(q, bus, conn): new_signal = q.expect( 'dbus-signal', signal='NewChannels', predicate=lambda e: e.args[0][0][1].get( cs.CHANNEL_TYPE) == cs.CHANNEL_TYPE_SERVER_AUTHENTICATION) path, props = new_signal.args[0][0] chan = SaslChannelWrapper(bus.get_object(conn.bus_name, path)) assertLength(1, new_signal.args[0]) assertEquals(cs.CHANNEL_IFACE_SASL_AUTH, props.get(cs.AUTH_METHOD)) return chan, props
def sending_request_to_presenceless_contact(q, bus, conn, stream, chan): """ Initially we know nothing of Guybrush's presence, so should just try our level best if asked to. """ message = [ { 'message-type': cs.MT_NORMAL, }, { 'content-type': 'text/plain', 'content': 'Thriftweed?', }] chan.Messages.SendMessage(message, cs.MSG_SENDING_FLAGS_REPORT_DELIVERY) e = q.expect('stream-message', to=GUYBRUSH) assertLength(1, list(e.stanza.elements(uri=ns.RECEIPTS, name='request')))
def advertise_caps(q, bus, conn, service, filters, expected_features, unexpected_features, expected_caps): # make sure nothing from a previous update is still running sync_dbus(bus, q, conn) self_handle = conn.Properties.Get(cs.CONN, "SelfHandle") self_handle_name = conn.Properties.Get(cs.CONN, "SelfID") ret_caps = conn.ContactCapabilities.UpdateCapabilities( [(cs.CLIENT + '.Foo', filters, [])]) presence, event_dbus = q.expect_many( EventPattern('service-resolved', service=service), EventPattern('dbus-signal', signal='ContactCapabilitiesChanged') ) assertLength(1, event_dbus.args) signaled_caps = event_dbus.args[0] outbound = connect_to_stream(q, 'test@foobar', self_handle_name, str(presence.pt), presence.port) e = q.expect('connection-result') assert e.succeeded, e.reason e = q.expect('stream-opened', connection=outbound) # Expect Salut to reply with the correct caps event, namespaces = disco_caps(q, outbound, presence.txt) assertSameElements(expected_caps, signaled_caps[self_handle]) assertContains(ns.TP_FT_METADATA, namespaces) for var in expected_features: assertContains(var, namespaces) for var in unexpected_features: assertDoesNotContain(var, namespaces) # check the Contacts interface give the same caps caps_via_contacts_iface = conn.Contacts.GetContactAttributes( [self_handle], [cs.CONN_IFACE_CONTACT_CAPS], False) \ [self_handle][cs.ATTR_CONTACT_CAPABILITIES] assertSameElements(expected_caps, caps_via_contacts_iface) # close things... outbound.send('</stream:stream>') sync_dbus(bus, q, conn) outbound.transport.loseConnection()
def advertise_caps(q, bus, conn, service, filters, expected_features, unexpected_features, expected_caps): # make sure nothing from a previous update is still running sync_dbus(bus, q, conn) self_handle = conn.Properties.Get(cs.CONN, "SelfHandle") self_handle_name = conn.Properties.Get(cs.CONN, "SelfID") ret_caps = conn.ContactCapabilities.UpdateCapabilities([ (cs.CLIENT + '.Foo', filters, []) ]) presence, event_dbus = q.expect_many( EventPattern('service-resolved', service=service), EventPattern('dbus-signal', signal='ContactCapabilitiesChanged')) assertLength(1, event_dbus.args) signaled_caps = event_dbus.args[0] outbound = connect_to_stream(q, 'test@foobar', self_handle_name, str(presence.pt), presence.port) e = q.expect('connection-result') assert e.succeeded, e.reason e = q.expect('stream-opened', connection=outbound) # Expect Salut to reply with the correct caps event, namespaces = disco_caps(q, outbound, presence.txt) assertSameElements(expected_caps, signaled_caps[self_handle]) assertContains(ns.TP_FT_METADATA, namespaces) for var in expected_features: assertContains(var, namespaces) for var in unexpected_features: assertDoesNotContain(var, namespaces) # check the Contacts interface give the same caps caps_via_contacts_iface = conn.Contacts.GetContactAttributes( [self_handle], [cs.CONN_IFACE_CONTACT_CAPS], False) \ [self_handle][cs.ATTR_CONTACT_CAPABILITIES] assertSameElements(expected_caps, caps_via_contacts_iface) # close things... outbound.send('</stream:stream>') sync_dbus(bus, q, conn) outbound.transport.loseConnection()
def __add_stream (self, content, stream_path, initial, incoming): tmpstream = self.bus.get_object (self.conn.bus_name, stream_path) content.stream = ProxyWrapper (tmpstream, cs.CALL_STREAM, {'Media': cs.CALL_STREAM_IFACE_MEDIA}) stream_props = content.stream.Properties.GetAll(cs.CALL_STREAM) assertEquals(True, stream_props['CanRequestReceiving']) if incoming: assertEquals(cs.CALL_SENDING_STATE_PENDING_SEND, stream_props['LocalSendingState']) else: assertEquals(cs.CALL_SENDING_STATE_SENDING, stream_props['LocalSendingState']) if incoming: assertEquals( {self.remote_handle: cs.CALL_SENDING_STATE_SENDING}, stream_props['RemoteMembers']) else: assertEquals( {self.remote_handle: cs.CALL_SENDING_STATE_PENDING_SEND}, stream_props['RemoteMembers']) smedia_props = content.stream.Properties.GetAll( cs.CALL_STREAM_IFACE_MEDIA) assertEquals(cs.CALL_SENDING_STATE_NONE, smedia_props['SendingState']) if initial: assertEquals(cs.CALL_SENDING_STATE_NONE, smedia_props['ReceivingState']) else: assertEquals(cs.CALL_SENDING_STATE_PENDING_SEND, smedia_props['ReceivingState']) assertEquals(cs.CALL_STREAM_TRANSPORT_RAW_UDP, smedia_props['Transport']) assertEquals([], smedia_props['LocalCandidates']) assertEquals(("",""), smedia_props['LocalCredentials']) assertEquals([], smedia_props['STUNServers']) assertEquals([], smedia_props['RelayInfo']) assertEquals(True, smedia_props['HasServerInfo']) if incoming: assertLength(1, smedia_props['Endpoints']) self.check_endpoint(content, smedia_props['Endpoints'][0]) else: assertEquals([], smedia_props['Endpoints']) assertEquals(False, smedia_props['ICERestartPending'])
def accept_outgoing(self): if self.incoming: return self.context.check_call_sdp(self.invite_event.sip_message.body, self.medias) self.context.accept(self.invite_event.sip_message) ack_cseq = "%s ACK" % self.invite_event.cseq.split()[0] del self.invite_event events = self.content_dbus_signal_event('NewMediaDescriptionOffer') + \ self.stream_dbus_signal_event('EndpointsChanged') o = self.q.expect_many( EventPattern('sip-ack', cseq=ack_cseq), # Call accepted *events) for i in o: if i.type != 'dbus-signal' or \ i.signal != 'NewMediaDescriptionOffer': continue md = self.bus.get_object (self.conn.bus_name, i.args[0]) md.Accept(self.context.get_audio_md_dbus(self.remote_handle)) o = self.q.expect_many( # Call accepted EventPattern('dbus-signal', signal='CallStateChanged')) assertEquals(cs.CALL_STATE_ACCEPTED, o[0].args[0]) for c in self.contents: mdo = c.Get(cs.CALL_CONTENT_IFACE_MEDIA, 'MediaDescriptionOffer') assertEquals(('/', {}), mdo) for c in self.contents: c.stream.Media.CompleteSendingStateChange( cs.CALL_STREAM_FLOW_STATE_STARTED) self.q.expect('dbus-signal', signal='SendingStateChanged', args=[cs.CALL_STREAM_FLOW_STATE_STARTED], path=c.stream.__dbus_object_path__) for i in o: if i.type == 'dbus-signal' and i.signal == 'EndpointsChanged': assertLength(1, i.args[0]) assertLength(0, i.args[1]) self.check_endpoint(c, i.args[0][0])
def accept_outgoing(self): if self.incoming: return self.context.check_call_sdp(self.invite_event.sip_message.body, self.medias) self.context.accept(self.invite_event.sip_message) ack_cseq = "%s ACK" % self.invite_event.cseq.split()[0] del self.invite_event events = self.content_dbus_signal_event('NewMediaDescriptionOffer') + \ self.stream_dbus_signal_event('EndpointsChanged') o = self.q.expect_many( EventPattern('sip-ack', cseq=ack_cseq), # Call accepted *events) for i in o: if i.type != 'dbus-signal' or \ i.signal != 'NewMediaDescriptionOffer': continue md = self.bus.get_object(self.conn.bus_name, i.args[0]) md.Accept(self.context.get_audio_md_dbus(self.remote_handle)) o = self.q.expect_many( # Call accepted EventPattern('dbus-signal', signal='CallStateChanged')) assertEquals(cs.CALL_STATE_ACCEPTED, o[0].args[0]) for c in self.contents: mdo = c.Get(cs.CALL_CONTENT_IFACE_MEDIA, 'MediaDescriptionOffer') assertEquals(('/', {}), mdo) for c in self.contents: c.stream.Media.CompleteSendingStateChange( cs.CALL_STREAM_FLOW_STATE_STARTED) self.q.expect('dbus-signal', signal='SendingStateChanged', args=[cs.CALL_STREAM_FLOW_STATE_STARTED], path=c.stream.__dbus_object_path__) for i in o: if i.type == 'dbus-signal' and i.signal == 'EndpointsChanged': assertLength(1, i.args[0]) assertLength(0, i.args[1]) self.check_endpoint(c, i.args[0][0])
def __add_stream(self, content, stream_path, initial, incoming): tmpstream = self.bus.get_object(self.conn.bus_name, stream_path) content.stream = ProxyWrapper(tmpstream, cs.CALL_STREAM, {'Media': cs.CALL_STREAM_IFACE_MEDIA}) stream_props = content.stream.Properties.GetAll(cs.CALL_STREAM) assertEquals(True, stream_props['CanRequestReceiving']) if incoming: assertEquals(cs.CALL_SENDING_STATE_PENDING_SEND, stream_props['LocalSendingState']) else: assertEquals(cs.CALL_SENDING_STATE_SENDING, stream_props['LocalSendingState']) if incoming: assertEquals({self.remote_handle: cs.CALL_SENDING_STATE_SENDING}, stream_props['RemoteMembers']) else: assertEquals( {self.remote_handle: cs.CALL_SENDING_STATE_PENDING_SEND}, stream_props['RemoteMembers']) smedia_props = content.stream.Properties.GetAll( cs.CALL_STREAM_IFACE_MEDIA) assertEquals(cs.CALL_SENDING_STATE_NONE, smedia_props['SendingState']) if initial: assertEquals(cs.CALL_SENDING_STATE_NONE, smedia_props['ReceivingState']) else: assertEquals(cs.CALL_SENDING_STATE_PENDING_SEND, smedia_props['ReceivingState']) assertEquals(cs.CALL_STREAM_TRANSPORT_RAW_UDP, smedia_props['Transport']) assertEquals([], smedia_props['LocalCandidates']) assertEquals(("", ""), smedia_props['LocalCredentials']) assertEquals([], smedia_props['STUNServers']) assertEquals([], smedia_props['RelayInfo']) assertEquals(True, smedia_props['HasServerInfo']) if incoming: assertLength(1, smedia_props['Endpoints']) self.check_endpoint(content, smedia_props['Endpoints'][0]) else: assertEquals([], smedia_props['Endpoints']) assertEquals(False, smedia_props['ICERestartPending'])
def rccs(q, bus, conn, stream): """ Tests that the connection's RequestableChannelClasses for StreamedMedia are sane. """ conn.Connect() a = q.expect('dbus-signal', signal='StatusChanged', args=[cs.CONN_STATUS_CONNECTING, cs.CSR_REQUESTED]) a = q.expect('dbus-signal', signal='StatusChanged', args=[cs.CONN_STATUS_CONNECTED, cs.CSR_REQUESTED]) rccs = conn.Properties.Get(cs.CONN_IFACE_REQUESTS, 'RequestableChannelClasses') # Test Channel.Type.StreamedMedia media_classes = [ rcc for rcc in rccs if rcc[0][cs.CHANNEL_TYPE] == cs.CHANNEL_TYPE_CALL ] assertLength(2, media_classes) for media_class in media_classes: fixed, allowed = media_class assertEquals(cs.HT_CONTACT, fixed[cs.TARGET_HANDLE_TYPE]) assert fixed.has_key(cs.CALL_INITIAL_AUDIO) or fixed.has_key( cs.CALL_INITIAL_VIDEO) expected_allowed = [ cs.TARGET_ID, cs.TARGET_HANDLE, cs.CALL_INITIAL_VIDEO, cs.CALL_INITIAL_AUDIO, cs.CALL_INITIAL_VIDEO_NAME, cs.CALL_INITIAL_AUDIO_NAME, cs.CALL_INITIAL_TRANSPORT, cs.DTMF_INITIAL_TONES, ] allowed.sort() expected_allowed.sort() assertSameSets(expected_allowed, allowed)
def secondIq(self, iq): username = xpath.queryForNodes('/iq/query/username', iq) assert map(str, username) == [self.username] digest = xpath.queryForNodes('/iq/query/digest', iq) expect = hashlib.sha1(self.xmlstream.sid + self.password).hexdigest() assert map(str, digest) == [expect] resource = xpath.queryForNodes('/iq/query/resource', iq) assertLength(1, resource) if self.resource is not None: assertEquals(self.resource, str(resource[0])) result = IQ(self.xmlstream, "result") result["id"] = iq["id"] self.xmlstream.send(result) self.xmlstream.dispatch(self.xmlstream, xmlstream.STREAM_AUTHD_EVENT)
def test_connect_disconnect_endpoint(self): endpoints = self.audio_stream.Get(cs.CALL_STREAM_IFACE_MEDIA, "Endpoints", dbus_interface=dbus.PROPERTIES_IFACE) assertLength(1, endpoints) endpoint = self.bus.get_object(self.conn.bus_name, endpoints[0]) # Lets try disconnecting one endpoint.SetEndpointState(1, cs.CALL_STREAM_ENDPOINT_STATE_CONNECTING, dbus_interface=cs.CALL_STREAM_ENDPOINT) ret = self.q.expect_many( EventPattern('dbus-signal', signal='EndpointStateChanged'), EventPattern('dbus-signal', signal='CallStateChanged')) assertEquals(1, ret[0].args[0]) assertEquals(cs.CALL_STREAM_ENDPOINT_STATE_CONNECTING, ret[0].args[1]) assertEquals(cs.CALL_STATE_ACCEPTED, ret[1].args[0]) state = endpoint.Get(cs.CALL_STREAM_ENDPOINT, "EndpointState", dbus_interface=dbus.PROPERTIES_IFACE) assertEquals(cs.CALL_STREAM_ENDPOINT_STATE_CONNECTING, state[1]) # And reconnecting it endpoint.SetEndpointState(1, cs.CALL_STREAM_ENDPOINT_STATE_FULLY_CONNECTED, dbus_interface=cs.CALL_STREAM_ENDPOINT) ret = self.q.expect_many( EventPattern('dbus-signal', signal='EndpointStateChanged'), EventPattern('dbus-signal', signal='CallStateChanged')) assertEquals(1,ret[0].args[0]) assertEquals(cs.CALL_STREAM_ENDPOINT_STATE_FULLY_CONNECTED, ret[0].args[1]) assertEquals(cs.CALL_STATE_ACTIVE, ret[1].args[0]) state = endpoint.Get(cs.CALL_STREAM_ENDPOINT, "EndpointState", dbus_interface=dbus.PROPERTIES_IFACE) assertEquals(cs.CALL_STREAM_ENDPOINT_STATE_FULLY_CONNECTED, state[1]) # All Direction should still be both now stream_props = self.audio_stream.GetAll(cs.CALL_STREAM, dbus_interface = dbus.PROPERTIES_IFACE) assertEquals({self.peer_handle: cs.CALL_SENDING_STATE_SENDING}, stream_props["RemoteMembers"]) assertEquals(cs.CALL_SENDING_STATE_SENDING, stream_props["LocalSendingState"])
def stop_receiving(self, content): self.receiving = False content.stream.RequestReceiving(self.remote_handle, False) o = self.q.expect_many( EventPattern('dbus-signal', signal='ReceivingStateChanged', args=[cs.CALL_STREAM_FLOW_STATE_PENDING_STOP], path=content.stream.__dbus_object_path__), EventPattern('dbus-signal', signal='RemoteMembersChanged', path=content.stream.__dbus_object_path__), EventPattern('sip-invite')) assertLength(0, o[1].args[2]) assertLength(1, o[1].args[0]) assertEquals(cs.CALL_SENDING_STATE_PENDING_STOP_SENDING, o[1].args[0][self.remote_handle]) assertEquals(self.self_handle, o[1].args[3][0]) assertEquals(cs.CALL_STATE_CHANGE_REASON_USER_REQUESTED, o[1].args[3][1]) reinvite_event = o[2] self.context.check_call_sdp(reinvite_event.sip_message.body, [('audio', None, 'sendonly')]) body = reinvite_event.sip_message.body.replace( 'sendonly', self.sending and 'recvonly' or 'inactive') self.context.accept(reinvite_event.sip_message, body) ack_cseq = "%s ACK" % reinvite_event.cseq.split()[0] o = self.q.expect_many( EventPattern('sip-ack', cseq=ack_cseq), EventPattern('dbus-signal', signal='RemoteMembersChanged', path=content.stream.__dbus_object_path__)) assertLength(1, o[1].args[0]) assertLength(0, o[1].args[2]) assertEquals(cs.CALL_SENDING_STATE_NONE, o[1].args[0][self.remote_handle]) #assertEquals(self.remote_handle, o[1].args[3][0]) #assertEquals(cs.CALL_STATE_CHANGE_REASON_USER_REQUESTED, o[1].args[3][1]) content.stream.Media.CompleteReceivingStateChange( cs.CALL_STREAM_FLOW_STATE_STOPPED) self.q.expect('dbus-signal', signal='ReceivingStateChanged', args=[cs.CALL_STREAM_FLOW_STATE_STOPPED], path=content.stream.__dbus_object_path__),
def extract_disco_parts(stanza): identity_nodes = xpath.queryForNodes('/iq/query/identity', stanza) assertLength(1, identity_nodes) identity_node = identity_nodes[0] assertEquals('client', identity_node['category']) assertEquals(config.CLIENT_TYPE, identity_node['type']) assertEquals(config.PACKAGE_STRING, identity_node['name']) assertDoesNotContain('xml:lang', identity_node.attributes) identity = 'client/%s//%s' % (config.CLIENT_TYPE, config.PACKAGE_STRING) features = [] for feature in xpath.queryForNodes('/iq/query/feature', stanza): features.append(feature['var']) # a quick and ugly data form extractor x_nodes = xpath.queryForNodes('/iq/query/x', stanza) or [] dataforms = extract_data_forms(x_nodes) return ([identity], features, dataforms)
def respondToSecondIq(self, iq): username = xpath.queryForNodes('/iq/query/username', iq) assert map(str, username) == [self.username] digest = xpath.queryForNodes('/iq/query/digest', iq) expect = hashlib.sha1(self.xmlstream.sid + self.password).hexdigest() assert map(str, digest) == [expect] resource = xpath.queryForNodes('/iq/query/resource', iq) assertLength(1, resource) if self.resource is not None: assertEquals(self.resource, str(resource[0])) self.bare_jid = '%s@%s' % (self.username, self.xmlstream.domain) self.full_jid = '%s/%s' % (self.bare_jid, resource) result = IQ(self.xmlstream, "result") result["id"] = iq["id"] self.xmlstream.send(result) self.xmlstream.dispatch(self.xmlstream, xmlstream.STREAM_AUTHD_EVENT)
def start_receiving(self, content, already_receiving=False): self.receiving = True content.stream.RequestReceiving(self.remote_handle, True) self.q.expect('dbus-signal', signal='ReceivingStateChanged', args=[cs.CALL_STREAM_FLOW_STATE_PENDING_START], path=content.stream.__dbus_object_path__), content.stream.Media.CompleteReceivingStateChange( cs.CALL_STREAM_FLOW_STATE_STARTED) o = self.q.expect_many( EventPattern('dbus-signal', signal='ReceivingStateChanged', args=[cs.CALL_STREAM_FLOW_STATE_STARTED], path=content.stream.__dbus_object_path__), EventPattern('dbus-signal', signal='RemoteMembersChanged', path=content.stream.__dbus_object_path__), EventPattern('sip-invite')) assertLength(0, o[1].args[2]) assertLength(1, o[1].args[0]) assertEquals(cs.CALL_SENDING_STATE_PENDING_SEND, o[1].args[0][self.remote_handle]) assertEquals(self.self_handle, o[1].args[3][0]) assertEquals(cs.CALL_STATE_CHANGE_REASON_USER_REQUESTED, o[1].args[3][1]) reinvite_event = o[2] assertDoesNotContain('a=sendonly', reinvite_event.sip_message.body) assertDoesNotContain('a=inactive', reinvite_event.sip_message.body) self.context.check_call_sdp(reinvite_event.sip_message.body) self.context.accept(reinvite_event.sip_message) ack_cseq = "%s ACK" % reinvite_event.cseq.split()[0] o = self.q.expect_many( EventPattern('sip-ack', cseq=ack_cseq), EventPattern('dbus-signal', signal='RemoteMembersChanged', path=content.stream.__dbus_object_path__)) assertLength(1, o[1].args[0]) assertLength(0, o[1].args[2]) assertEquals(cs.CALL_SENDING_STATE_SENDING, o[1].args[0][self.remote_handle])
def test_connect_success(q, bus, conn, stream): chan, hostname, certificate_path = connect_and_get_tls_objects(q, bus, conn) certificate = TlsCertificateWrapper(bus.get_object(conn.bus_name, certificate_path)) certificate.TLSCertificate.Accept() q.expect('dbus-signal', signal='Accepted') cert_props = dbus.Interface(certificate, cs.PROPERTIES_IFACE) state = cert_props.Get(cs.AUTH_TLS_CERT, 'State') rejections = cert_props.Get(cs.AUTH_TLS_CERT, 'Rejections') assertLength(0, rejections) chan.Close() q.expect_many( EventPattern('dbus-signal', signal='Closed'), EventPattern('dbus-signal', signal='ChannelClosed'), EventPattern('dbus-signal', signal='StatusChanged', args=[cs.CONN_STATUS_CONNECTED, cs.CSR_REQUESTED]) )
def check_call_properties(self, call_props): if self.incoming: assertEquals(cs.CALL_STATE_INITIALISED, call_props['CallState']) else: assertEquals(cs.CALL_STATE_PENDING_INITIATOR, call_props['CallState']) assertEquals(0, call_props['CallFlags']) assertEquals(False, call_props['HardwareStreaming']) assertEquals(True, call_props['MutableContents']) assertEquals(self.initial_audio_content_name is not None, call_props['InitialAudio']) assertEquals(self.initial_audio_content_name or "", call_props['InitialAudioName']) assertEquals(self.initial_video_content_name is not None, call_props['InitialVideo']) assertEquals(self.initial_video_content_name or "", call_props['InitialVideoName']) assertEquals(cs.CALL_STREAM_TRANSPORT_RAW_UDP, call_props['InitialTransport']) assertEquals({self.remote_handle: 0}, call_props['CallMembers']) assertLength(self.content_count, call_props['Contents'])