def test(q, bus, conn, stream): conn.Connect() _, iq_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, iq_event.stanza) call_async(q, conn, 'RequestHandles', cs.HT_ROOM, ['*****@*****.**']) event = q.expect('stream-iq', to='conf.localhost', query_ns='http://jabber.org/protocol/disco#info') result = make_result_iq(stream, event.stanza) feature = result.firstChildElement().addElement('feature') feature['var'] = 'http://jabber.org/protocol/muc' stream.send(result) event = q.expect('dbus-return', method='RequestHandles') handles = event.value[0] room_handle = handles[0] # join the muc call_async(q, conn, 'RequestChannel', cs.CHANNEL_TYPE_TEXT, cs.HT_ROOM, room_handle, True) _, stream_event = q.expect_many( EventPattern('dbus-signal', signal='MembersChanged', args=[u'', [], [], [], [2], 0, 0]), EventPattern('stream-presence', to='[email protected]/test')) # Send presence for other member of room. stream.send(make_muc_presence('owner', 'moderator', '*****@*****.**', 'bob')) # Send presence for own membership of room. stream.send(make_muc_presence('none', 'participant', '*****@*****.**', 'test')) q.expect('dbus-signal', signal='MembersChanged', args=[u'', [2, 3], [], [], [], 0, 0]) assert conn.InspectHandles(cs.HT_CONTACT, [2, 3]) == \ ['[email protected]/test', '[email protected]/bob'] bob_handle = 3 event = q.expect('dbus-return', method='RequestChannel') text_chan = bus.get_object(conn.bus_name, event.value[0]) # Bob offers a muc tube tube_id = 666 stream_id = 1234 presence = make_muc_presence('owner', 'moderator', '*****@*****.**', 'bob') tubes = presence.addElement((ns.TUBES, 'tubes')) tube = tubes.addElement((None, 'tube')) tube['type'] = 'dbus' tube['service'] = 'org.telepathy.freedesktop.test' tube['id'] = str(tube_id) tube['stream-id'] = str(stream_id) tube['dbus-name'] = ':2.Y2Fzc2lkeS10ZXN0MgAA' tube['initiator'] = '[email protected]/bob' parameters = tube.addElement((None, 'parameters')) parameter = parameters.addElement((None, 'parameter')) parameter['name'] = 's' parameter['type'] = 'str' parameter.addContent('hello') parameter = parameters.addElement((None, 'parameter')) parameter['name'] = 'ay' parameter['type'] = 'bytes' parameter.addContent('aGVsbG8=') parameter = parameters.addElement((None, 'parameter')) parameter['name'] = 'u' parameter['type'] = 'uint' parameter.addContent('123') parameter = parameters.addElement((None, 'parameter')) parameter['name'] = 'i' parameter['type'] = 'int' parameter.addContent('-123') stream.send(presence) # tubes channel is automatically created event = q.expect('dbus-signal', signal='NewChannel') if event.args[1] == cs.CHANNEL_TYPE_TEXT: # skip this one, try the next one event = q.expect('dbus-signal', signal='NewChannel') assert event.args[1] == cs.CHANNEL_TYPE_TUBES, event.args assert event.args[2] == cs.HT_ROOM assert event.args[3] == room_handle tubes_chan = bus.get_object(conn.bus_name, event.args[0]) tubes_iface = dbus.Interface(tubes_chan, event.args[1]) channel_props = tubes_chan.GetAll( cs.CHANNEL, dbus_interface=dbus.PROPERTIES_IFACE) assert channel_props['TargetID'] == '*****@*****.**', channel_props assert channel_props['Requested'] == False assert channel_props['InitiatorID'] == '' assert channel_props['InitiatorHandle'] == 0 tubes_self_handle = tubes_chan.GetSelfHandle( dbus_interface=cs.CHANNEL_IFACE_GROUP) q.expect('dbus-signal', signal='NewTube', args=[tube_id, bob_handle, 0, 'org.telepathy.freedesktop.test', sample_parameters, 0]) expected_tube = (tube_id, bob_handle, cs.TUBE_TYPE_DBUS, 'org.telepathy.freedesktop.test', sample_parameters, cs.TUBE_STATE_LOCAL_PENDING) tubes = tubes_iface.ListTubes(byte_arrays=True) assert len(tubes) == 1, unwrap(tubes) t.check_tube_in_tubes(expected_tube, tubes) # reject the tube tubes_iface.CloseTube(tube_id) q.expect('dbus-signal', signal='TubeClosed', args=[tube_id]) # close the text channel text_chan.Close()
def test(q, bus, conn, stream, bytestream_cls, address_type, access_control, access_control_param): address1 = t.set_up_echo(q, address_type, True, streamfile='stream') address2 = t.set_up_echo(q, address_type, True, streamfile='stream2') t.check_conn_properties(q, conn) vcard_event, roster_event = q.expect_many( EventPattern('stream-iq', to=None, query_ns='vcard-temp', query_name='vCard'), EventPattern('stream-iq', query_ns=ns.ROSTER)) self_handle = conn.GetSelfHandle() acknowledge_iq(stream, vcard_event.stanza) roster = roster_event.stanza roster['type'] = 'result' item = roster_event.query.addElement('item') item['jid'] = 'bob@localhost' # Bob can do tubes item['subscription'] = 'both' stream.send(roster) bob_full_jid = 'bob@localhost/Bob' self_full_jid = 'test@localhost/Resource' # Send Bob presence and his tube caps presence = domish.Element(('jabber:client', 'presence')) presence['from'] = bob_full_jid presence['to'] = self_full_jid c = presence.addElement('c') c['xmlns'] = 'http://jabber.org/protocol/caps' c['node'] = 'http://example.com/ICantBelieveItsNotTelepathy' c['ver'] = '1.2.3' stream.send(presence) event = q.expect('stream-iq', iq_type='get', query_ns='http://jabber.org/protocol/disco#info', to=bob_full_jid) assert event.query['node'] == \ 'http://example.com/ICantBelieveItsNotTelepathy#1.2.3' result = make_result_iq(stream, event.stanza) query = result.firstChildElement() feature = query.addElement('feature') feature['var'] = ns.TUBES stream.send(result) # A tube request can be done only if the contact has tube capabilities # Ensure that Bob's caps have been received sync_stream(q, stream) # Also ensure that all the new contact list channels have been announced, # so that the NewChannel(s) signals we look for after calling # RequestChannel are the ones we wanted. sync_dbus(bus, q, conn) # Test tubes with Bob. Bob has tube capabilities. bob_handle = conn.RequestHandles(1, ['bob@localhost'])[0] # old tubes API call_async(q, conn, 'RequestChannel', cs.CHANNEL_TYPE_TUBES, cs.HT_CONTACT, bob_handle, True) ret, old_sig, new_sig = q.expect_many( EventPattern('dbus-return', method='RequestChannel'), EventPattern('dbus-signal', signal='NewChannel'), EventPattern('dbus-signal', signal='NewChannels'), ) assert len(ret.value) == 1 chan_path = ret.value[0] t.check_NewChannel_signal(old_sig.args, cs.CHANNEL_TYPE_TUBES, chan_path, bob_handle, True) t.check_NewChannels_signal(conn, new_sig.args, cs.CHANNEL_TYPE_TUBES, chan_path, bob_handle, 'bob@localhost', self_handle) old_tubes_channel_properties = new_sig.args[0][0] t.check_conn_properties(q, conn, [old_tubes_channel_properties]) # Try CreateChannel with correct properties # Gabble must succeed call_async(q, conn.Requests, 'CreateChannel', {cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_STREAM_TUBE, cs.TARGET_HANDLE_TYPE: cs.HT_CONTACT, cs.TARGET_HANDLE: bob_handle, cs.STREAM_TUBE_SERVICE: "newecho", }) # the NewTube signal (old API) is not fired now as the tube wasn't offered # yet ret, old_sig, new_sig = q.expect_many( EventPattern('dbus-return', method='CreateChannel'), EventPattern('dbus-signal', signal='NewChannel'), EventPattern('dbus-signal', signal='NewChannels'), ) assert len(ret.value) == 2 # CreateChannel returns 2 values: o, a{sv} new_chan_path = ret.value[0] new_chan_prop_asv = ret.value[1] # State and Parameters are mutables so not announced assert cs.TUBE_STATE not in new_chan_prop_asv assert cs.TUBE_PARAMETERS not in new_chan_prop_asv assert new_chan_path.find("StreamTube") != -1, new_chan_path assert new_chan_path.find("SITubesChannel") == -1, new_chan_path # The path of the Channel.Type.Tubes object MUST be different to the path # of the Channel.Type.StreamTube object ! assert chan_path != new_chan_path new_tube_chan = bus.get_object(conn.bus_name, new_chan_path) new_tube_iface = dbus.Interface(new_tube_chan, cs.CHANNEL_TYPE_STREAM_TUBE) # check State and Parameters new_tube_props = new_tube_chan.GetAll(cs.CHANNEL_IFACE_TUBE, dbus_interface=cs.PROPERTIES_IFACE) # the tube created using the new API is in the "not offered" state assert new_tube_props['State'] == cs.TUBE_CHANNEL_STATE_NOT_OFFERED t.check_NewChannel_signal(old_sig.args, cs.CHANNEL_TYPE_STREAM_TUBE, new_chan_path, bob_handle, True) t.check_NewChannels_signal(conn, new_sig.args, cs.CHANNEL_TYPE_STREAM_TUBE, new_chan_path, bob_handle, 'bob@localhost', self_handle) stream_tube_channel_properties = new_sig.args[0][0] assert cs.TUBE_STATE not in stream_tube_channel_properties assert cs.TUBE_PARAMETERS not in stream_tube_channel_properties t.check_conn_properties(q, conn, [old_tubes_channel_properties, stream_tube_channel_properties]) tubes_chan = bus.get_object(conn.bus_name, chan_path) tubes_iface = dbus.Interface(tubes_chan, cs.CHANNEL_TYPE_TUBES) t.check_channel_properties(q, bus, conn, tubes_chan, cs.CHANNEL_TYPE_TUBES, bob_handle, "bob@localhost") # Create another tube using old API call_async(q, tubes_iface, 'OfferStreamTube', 'echo', sample_parameters, address_type, address1, access_control, access_control_param) event, return_event, new_chan, new_chans = q.expect_many( EventPattern('stream-message'), EventPattern('dbus-return', method='OfferStreamTube'), EventPattern('dbus-signal', signal='NewChannel'), EventPattern('dbus-signal', signal='NewChannels')) message = event.stanza assert message['to'] == bob_full_jid tube_nodes = xpath.queryForNodes('/message/tube[@xmlns="%s"]' % ns.TUBES, message) assert tube_nodes is not None assert len(tube_nodes) == 1 tube = tube_nodes[0] assert tube['service'] == 'echo' assert tube['type'] == 'stream' assert not tube.hasAttribute('initiator') stream_tube_id = long(tube['id']) params = {} parameter_nodes = xpath.queryForNodes('/tube/parameters/parameter', tube) for node in parameter_nodes: assert node['name'] not in params params[node['name']] = (node['type'], str(node)) assert params == {'ay': ('bytes', 'aGVsbG8='), 's': ('str', 'hello'), 'i': ('int', '-123'), 'u': ('uint', '123'), } # the tube channel (new API) is announced t.check_NewChannel_signal(new_chan.args, cs.CHANNEL_TYPE_STREAM_TUBE, None, bob_handle, False) t.check_NewChannels_signal(conn, new_chans.args, cs.CHANNEL_TYPE_STREAM_TUBE, new_chan.args[0], bob_handle, "bob@localhost", self_handle) props = new_chans.args[0][0][1] assert cs.TUBE_STATE not in props assert cs.TUBE_PARAMETERS not in props # We offered a tube using the old tube API and created one with the new # API, so there are 2 tubes. Check the new tube API works assert len(filter(lambda x: x[1] == cs.CHANNEL_TYPE_TUBES, conn.ListChannels())) == 1 channels = filter(lambda x: x[1] == cs.CHANNEL_TYPE_STREAM_TUBE and x[0] == new_chan_path, conn.ListChannels()) assert len(channels) == 1 assert new_chan_path == channels[0][0] old_tube_chan = bus.get_object(conn.bus_name, new_chan.args[0]) tube_basic_props = old_tube_chan.GetAll(cs.CHANNEL, dbus_interface=cs.PROPERTIES_IFACE) assert tube_basic_props.get("InitiatorHandle") == self_handle stream_tube_props = old_tube_chan.GetAll(cs.CHANNEL_TYPE_STREAM_TUBE, dbus_interface=cs.PROPERTIES_IFACE) assert stream_tube_props.get("Service") == "echo", stream_tube_props old_tube_props = old_tube_chan.GetAll(cs.CHANNEL_IFACE_TUBE, dbus_interface=cs.PROPERTIES_IFACE, byte_arrays=True) assert old_tube_props.get("Parameters") == dbus.Dictionary(sample_parameters) # Tube have been created using the old API and so is already offered assert old_tube_props['State'] == cs.TUBE_CHANNEL_STATE_REMOTE_PENDING t.check_channel_properties(q, bus, conn, tubes_chan, cs.CHANNEL_TYPE_TUBES, bob_handle, "bob@localhost") t.check_channel_properties(q, bus, conn, old_tube_chan, cs.CHANNEL_TYPE_STREAM_TUBE, bob_handle, "bob@localhost", cs.TUBE_CHANNEL_STATE_REMOTE_PENDING) # Offer the first tube created (new API) call_async(q, new_tube_iface, 'Offer', address_type, address2, access_control, new_sample_parameters) msg_event, new_tube_sig, state_event = q.expect_many( EventPattern('stream-message'), EventPattern('dbus-signal', signal='NewTube'), EventPattern('dbus-signal', signal='TubeChannelStateChanged')) assert state_event.args[0] == cs.TUBE_CHANNEL_STATE_REMOTE_PENDING message = msg_event.stanza assert message['to'] == bob_full_jid tube_nodes = xpath.queryForNodes('/message/tube[@xmlns="%s"]' % ns.TUBES, message) assert tube_nodes is not None assert len(tube_nodes) == 1 tube = tube_nodes[0] assert tube['service'] == 'newecho' assert tube['type'] == 'stream' assert not tube.hasAttribute('initiator') new_stream_tube_id = long(tube['id']) params = {} parameter_nodes = xpath.queryForNodes('/tube/parameters/parameter', tube) for node in parameter_nodes: assert node['name'] not in params params[node['name']] = (node['type'], str(node)) assert params == {'ay': ('bytes', 'bmV3aGVsbG8='), 's': ('str', 'newhello'), 'i': ('int', '-123'), 'u': ('uint', '123'), } # check NewTube signal (old API) id, initiator_handle, type, service, params, state = new_tube_sig.args assert initiator_handle == self_handle assert type == 1 # stream assert service == 'newecho' assert params == new_sample_parameters assert state == 1 # remote pending # The new tube has been offered, the parameters cannot be changed anymore # We need to use call_async to check the error tube_prop_iface = dbus.Interface(old_tube_chan, cs.PROPERTIES_IFACE) call_async(q, tube_prop_iface, 'Set', cs.CHANNEL_IFACE_TUBE, 'Parameters', dbus.Dictionary( {dbus.String(u'foo2'): dbus.String(u'bar2')}, signature=dbus.Signature('sv')), dbus_interface=cs.PROPERTIES_IFACE) set_error = q.expect('dbus-error') # check it is *not* correctly changed new_tube_props = new_tube_chan.GetAll(cs.CHANNEL_IFACE_TUBE, dbus_interface=cs.PROPERTIES_IFACE, byte_arrays=True) assert new_tube_props.get("Parameters") == new_sample_parameters, \ new_tube_props.get("Parameters") # The CM is the server, so fake a client wanting to talk to it # Old API tube bytestream1 = bytestream_cls(stream, q, 'alpha', bob_full_jid, self_full_jid, True) iq, si = bytestream1.create_si_offer(ns.TUBES) stream_node = si.addElement((ns.TUBES, 'stream')) stream_node['tube'] = str(stream_tube_id) stream.send(iq) si_reply_event, _, _, new_conn_event, socket_event = q.expect_many( EventPattern('stream-iq', iq_type='result'), EventPattern('dbus-signal', signal='TubeStateChanged', args=[stream_tube_id, cs.TUBE_STATE_OPEN]), EventPattern('dbus-signal', signal='StreamTubeNewConnection', args=[stream_tube_id, bob_handle]), EventPattern('dbus-signal', signal='NewRemoteConnection'), EventPattern('socket-connected')) bytestream1.check_si_reply(si_reply_event.stanza) tube = xpath.queryForNodes('/iq/si/tube[@xmlns="%s"]' % ns.TUBES, si_reply_event.stanza) assert len(tube) == 1 handle, access, id = new_conn_event.args assert handle == bob_handle protocol = socket_event.protocol # we don't want to echo the access control byte protocol.echoed = False # start to read from the transport so we can read the control byte protocol.transport.startReading() t.check_new_connection_access(q, access_control, access, protocol) protocol.echoed = True expected_tube = (stream_tube_id, self_handle, cs.TUBE_TYPE_STREAM, 'echo', sample_parameters, cs.TUBE_STATE_OPEN) tubes = tubes_iface.ListTubes(byte_arrays=True) t.check_tube_in_tubes(expected_tube, tubes) # The CM is the server, so fake a client wanting to talk to it # New API tube bytestream2 = bytestream_cls(stream, q, 'beta', bob_full_jid, self_full_jid, True) iq, si = bytestream2.create_si_offer(ns.TUBES) stream_node = si.addElement((ns.TUBES, 'stream')) stream_node['tube'] = str(new_stream_tube_id) stream.send(iq) si_reply_event, _, new_conn_event, socket_event = q.expect_many( EventPattern('stream-iq', iq_type='result'), EventPattern('dbus-signal', signal='TubeChannelStateChanged', args=[cs.TUBE_STATE_OPEN]), EventPattern('dbus-signal', signal='NewRemoteConnection'), EventPattern('socket-connected')) bytestream2.check_si_reply(si_reply_event.stanza) tube = xpath.queryForNodes('/iq/si/tube[@xmlns="%s"]' % ns.TUBES, si_reply_event.stanza) assert len(tube) == 1 handle, access, conn_id = new_conn_event.args assert handle == bob_handle protocol = socket_event.protocol # we don't want to echo the access control byte protocol.echoed = False # start to read from the transport so we can read the control byte protocol.transport.startReading() t.check_new_connection_access(q, access_control, access, protocol) protocol.echoed = True expected_tube = (new_stream_tube_id, self_handle, cs.TUBE_TYPE_STREAM, 'newecho', new_sample_parameters, cs.TUBE_STATE_OPEN) t.check_tube_in_tubes (expected_tube, tubes_iface.ListTubes(byte_arrays=True)) # have the fake client open the stream bytestream1.open_bytestream() # have the fake client send us some data data = 'hello, world' bytestream1.send_data(data) binary = bytestream1.get_data(len(data)) assert binary == data, binary # have the fake client open the stream bytestream2.open_bytestream() # have the fake client send us some data data = 'hello, new world' bytestream2.send_data(data) binary = bytestream2.get_data(len(data)) assert binary == data, binary # peer closes the bytestream bytestream2.close() e = q.expect('dbus-signal', signal='ConnectionClosed') assertEquals(conn_id, e.args[0]) assertEquals(cs.CONNECTION_LOST, e.args[1]) t.cleanup()
def test(q, bus, conn, stream, bytestream_cls, address_type, access_control, access_control_param): if bytestream_cls in [BytestreamS5BRelay, BytestreamS5BRelayBugged]: # disable SOCKS5 relay tests because proxy can't be used with muc # contacts atm return conn.Connect() _, iq_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, iq_event.stanza) self_handle = conn.GetSelfHandle() self_name = conn.InspectHandles(cs.HT_CONTACT, [self_handle])[0] t.check_conn_properties(q, conn) room_handle, tubes_chan, tubes_iface = get_muc_tubes_channel(q, bus, conn, stream, "*****@*****.**") tubes_self_handle = tubes_chan.GetSelfHandle(dbus_interface=cs.CHANNEL_IFACE_GROUP) bob_handle = conn.RequestHandles(cs.HT_CONTACT, ["[email protected]/bob"])[0] address = t.create_server(q, address_type) # offer stream tube (old API) using an Unix socket call_async( q, tubes_iface, "OfferStreamTube", "echo", sample_parameters, address_type, address, access_control, access_control_param, ) new_tube_event, stream_event, _, new_channels_event = q.expect_many( EventPattern("dbus-signal", signal="NewTube"), EventPattern("stream-presence", to="[email protected]/test"), EventPattern("dbus-return", method="OfferStreamTube"), EventPattern("dbus-signal", signal="NewChannels"), ) # handle new_tube_event stream_tube_id = new_tube_event.args[0] assert new_tube_event.args[1] == tubes_self_handle assert new_tube_event.args[2] == 1 # Stream assert new_tube_event.args[3] == "echo" assert new_tube_event.args[4] == sample_parameters assert new_tube_event.args[5] == cs.TUBE_CHANNEL_STATE_OPEN # handle stream_event # We announce our newly created tube in our muc presence presence = stream_event.stanza x_nodes = xpath.queryForNodes('/presence/x[@xmlns="http://jabber.org/' 'protocol/muc"]', presence) assert x_nodes is not None assert len(x_nodes) == 1 tubes_nodes = xpath.queryForNodes('/presence/tubes[@xmlns="%s"]' % ns.TUBES, presence) assert tubes_nodes is not None assert len(tubes_nodes) == 1 tube_nodes = xpath.queryForNodes("/tubes/tube", tubes_nodes[0]) assert tube_nodes is not None assert len(tube_nodes) == 1 for tube in tube_nodes: assert tube["type"] == "stream" assert not tube.hasAttribute("initiator") assert tube["service"] == "echo" assert not tube.hasAttribute("stream-id") assert not tube.hasAttribute("dbus-name") assert tube["id"] == str(stream_tube_id) params = {} parameter_nodes = xpath.queryForNodes("/tube/parameters/parameter", tube) for node in parameter_nodes: assert node["name"] not in params params[node["name"]] = (node["type"], str(node)) assert params == {"ay": ("bytes", "aGVsbG8="), "s": ("str", "hello"), "i": ("int", "-123"), "u": ("uint", "123")} # tube is also announced using new API channels = new_channels_event.args[0] assert len(channels) == 1 path, props = channels[0] assert props[cs.CHANNEL_TYPE] == cs.CHANNEL_TYPE_STREAM_TUBE assert props[cs.INITIATOR_HANDLE] == tubes_self_handle assert props[cs.INITIATOR_ID] == "[email protected]/test" assert props[cs.INTERFACES] == [cs.CHANNEL_IFACE_GROUP, cs.CHANNEL_IFACE_TUBE] assert props[cs.REQUESTED] == True assert props[cs.TARGET_HANDLE] == room_handle assert props[cs.TARGET_ID] == "*****@*****.**" assert props[cs.STREAM_TUBE_SERVICE] == "echo" tube_chan = bus.get_object(conn.bus_name, path) tube_props = tube_chan.GetAll(cs.CHANNEL_IFACE_TUBE, dbus_interface=cs.PROPERTIES_IFACE, byte_arrays=True) assert tube_props["Parameters"] == sample_parameters assert tube_props["State"] == cs.TUBE_CHANNEL_STATE_OPEN tubes = tubes_iface.ListTubes(byte_arrays=True) assert tubes == [ (stream_tube_id, tubes_self_handle, 1, "echo", sample_parameters, cs.TUBE_CHANNEL_STATE_OPEN) # Stream ] assert len(tubes) == 1, unwrap(tubes) expected_tube = ( stream_tube_id, tubes_self_handle, cs.TUBE_TYPE_STREAM, "echo", sample_parameters, cs.TUBE_STATE_OPEN, ) t.check_tube_in_tubes(expected_tube, tubes) # FIXME: if we use an unknown JID here, everything fails # (the code uses lookup where it should use ensure) bytestream = connect_to_tube(stream, q, bytestream_cls, "*****@*****.**", stream_tube_id) iq_event, socket_event, _, conn_event = q.expect_many( EventPattern("stream-iq", iq_type="result"), EventPattern("socket-connected"), EventPattern( "dbus-signal", signal="StreamTubeNewConnection", args=[stream_tube_id, bob_handle], interface=cs.CHANNEL_TYPE_TUBES, ), EventPattern("dbus-signal", signal="NewRemoteConnection", interface=cs.CHANNEL_TYPE_STREAM_TUBE), ) protocol = socket_event.protocol # handle iq_event bytestream.check_si_reply(iq_event.stanza) tube = xpath.queryForNodes('/iq//si/tube[@xmlns="%s"]' % ns.TUBES, iq_event.stanza) assert len(tube) == 1 handle, access, conn_id = conn_event.args assert handle == bob_handle use_tube(q, bytestream, protocol, conn_id) # offer a stream tube to another room (new API) address = t.create_server(q, address_type, block_reading=True) request = { cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_STREAM_TUBE, cs.TARGET_HANDLE_TYPE: cs.HT_ROOM, cs.TARGET_ID: "*****@*****.**", cs.STREAM_TUBE_SERVICE: "newecho", } _, _, new_tube_path, new_tube_props = join_muc(q, bus, conn, stream, "*****@*****.**", request) # first text and tubes channels are announced event = q.expect("dbus-signal", signal="NewChannels") channels = event.args[0] assert len(channels) == 2 path1, prop1 = channels[0] path2, prop2 = channels[1] assert sorted([prop1[cs.CHANNEL_TYPE], prop2[cs.CHANNEL_TYPE]]) == [cs.CHANNEL_TYPE_TEXT, cs.CHANNEL_TYPE_TUBES] got_text, got_tubes = False, False for path, props in channels: if props[cs.CHANNEL_TYPE] == cs.CHANNEL_TYPE_TEXT: got_text = True elif props[cs.CHANNEL_TYPE] == cs.CHANNEL_TYPE_TUBES: got_tubes = True else: assert False assert props[cs.INITIATOR_HANDLE] == self_handle assert props[cs.INITIATOR_ID] == self_name assert cs.CHANNEL_IFACE_GROUP in props[cs.INTERFACES] assert props[cs.TARGET_ID] == "*****@*****.**" assert props[cs.REQUESTED] == False assert (got_text, got_tubes) == (True, True) # now the tube channel is announced # FIXME: in this case, all channels should probably be announced together event = q.expect("dbus-signal", signal="NewChannels") channels = event.args[0] assert len(channels) == 1 path, prop = channels[0] assert prop[cs.CHANNEL_TYPE] == cs.CHANNEL_TYPE_STREAM_TUBE assert prop[cs.INITIATOR_ID] == "[email protected]/test" assert prop[cs.REQUESTED] == True assert prop[cs.TARGET_HANDLE_TYPE] == cs.HT_ROOM assert prop[cs.TARGET_ID] == "*****@*****.**" assert prop[cs.STREAM_TUBE_SERVICE] == "newecho" # check that the tube channel is in the channels list all_channels = conn.Get(cs.CONN_IFACE_REQUESTS, "Channels", dbus_interface=cs.PROPERTIES_IFACE, byte_arrays=True) assertContains((path, prop), all_channels) tube_chan = bus.get_object(conn.bus_name, path) stream_tube_iface = dbus.Interface(tube_chan, cs.CHANNEL_TYPE_STREAM_TUBE) chan_iface = dbus.Interface(tube_chan, cs.CHANNEL) tube_props = tube_chan.GetAll(cs.CHANNEL_IFACE_TUBE, dbus_interface=cs.PROPERTIES_IFACE) assert tube_props["State"] == cs.TUBE_CHANNEL_STATE_NOT_OFFERED # offer the tube call_async(q, stream_tube_iface, "Offer", address_type, address, access_control, {"foo": "bar"}) new_tube_event, stream_event, _, status_event = q.expect_many( EventPattern("dbus-signal", signal="NewTube"), EventPattern("stream-presence", to="[email protected]/test"), EventPattern("dbus-return", method="Offer"), EventPattern("dbus-signal", signal="TubeChannelStateChanged", args=[cs.TUBE_CHANNEL_STATE_OPEN]), ) tube_self_handle = tube_chan.GetSelfHandle(dbus_interface=cs.CHANNEL_IFACE_GROUP) assert conn.InspectHandles(cs.HT_CONTACT, [tube_self_handle]) == ["[email protected]/test"] # handle new_tube_event stream_tube_id = new_tube_event.args[0] assert new_tube_event.args[2] == 1 # Stream assert new_tube_event.args[3] == "newecho" assert new_tube_event.args[4] == {"foo": "bar"} assert new_tube_event.args[5] == cs.TUBE_CHANNEL_STATE_OPEN presence = stream_event.stanza x_nodes = xpath.queryForNodes('/presence/x[@xmlns="http://jabber.org/' 'protocol/muc"]', presence) assert x_nodes is not None assert len(x_nodes) == 1 tubes_nodes = xpath.queryForNodes('/presence/tubes[@xmlns="%s"]' % ns.TUBES, presence) assert tubes_nodes is not None assert len(tubes_nodes) == 1 tube_nodes = xpath.queryForNodes("/tubes/tube", tubes_nodes[0]) assert tube_nodes is not None assert len(tube_nodes) == 1 for tube in tube_nodes: assert tube["type"] == "stream" assert not tube.hasAttribute("initiator") assert tube["service"] == "newecho" assert not tube.hasAttribute("stream-id") assert not tube.hasAttribute("dbus-name") assert tube["id"] == str(stream_tube_id) params = {} parameter_nodes = xpath.queryForNodes("/tube/parameters/parameter", tube) for node in parameter_nodes: assert node["name"] not in params params[node["name"]] = (node["type"], str(node)) assert params == {"foo": ("str", "bar")} bob_handle = conn.RequestHandles(cs.HT_CONTACT, ["[email protected]/bob"])[0] bytestream = connect_to_tube(stream, q, bytestream_cls, "*****@*****.**", stream_tube_id) iq_event, socket_event, conn_event = q.expect_many( EventPattern("stream-iq", iq_type="result"), EventPattern("socket-connected"), EventPattern("dbus-signal", signal="NewRemoteConnection", interface=cs.CHANNEL_TYPE_STREAM_TUBE), ) handle, access, conn_id = conn_event.args assert handle == bob_handle protocol = socket_event.protocol # start to read from the transport so we can read the control byte protocol.transport.startReading() t.check_new_connection_access(q, access_control, access, protocol) # handle iq_event bytestream.check_si_reply(iq_event.stanza) tube = xpath.queryForNodes('/iq//si/tube[@xmlns="%s"]' % ns.TUBES, iq_event.stanza) assert len(tube) == 1 use_tube(q, bytestream, protocol, conn_id) chan_iface.Close() q.expect_many(EventPattern("dbus-signal", signal="Closed"), EventPattern("dbus-signal", signal="ChannelClosed"))
def test(q, bus, conn, stream, access_control): conn.Connect() _, iq_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, iq_event.stanza) # check if we can request muc D-Bus tube t.check_conn_properties(q, conn) self_handle = conn.GetSelfHandle() self_name = conn.InspectHandles(1, [self_handle])[0] handle, tubes_chan, tubes_iface = get_muc_tubes_channel(q, bus, conn, stream, '*****@*****.**') # Exercise basic Channel Properties from spec 0.17.7 channel_props = tubes_chan.GetAll(cs.CHANNEL, dbus_interface=dbus.PROPERTIES_IFACE) assert channel_props.get('TargetHandle') == handle,\ (channel_props.get('TargetHandle'), handle) assert channel_props.get('TargetHandleType') == 2,\ channel_props.get('TargetHandleType') assert channel_props.get('ChannelType') == cs.CHANNEL_TYPE_TUBES,\ channel_props.get('ChannelType') assert 'Interfaces' in channel_props, channel_props assert cs.CHANNEL_IFACE_GROUP in channel_props['Interfaces'], \ channel_props['Interfaces'] assert channel_props['TargetID'] == '*****@*****.**', channel_props assert channel_props['Requested'] == True assert channel_props['InitiatorID'] == 'test@localhost' assert channel_props['InitiatorHandle'] == conn.GetSelfHandle() # Exercise Group Properties from spec 0.17.6 (in a basic way) group_props = tubes_chan.GetAll(cs.CHANNEL_IFACE_GROUP, dbus_interface=dbus.PROPERTIES_IFACE) assert 'SelfHandle' in group_props, group_props assert 'HandleOwners' in group_props, group_props assert 'Members' in group_props, group_props assert 'LocalPendingMembers' in group_props, group_props assert 'RemotePendingMembers' in group_props, group_props assert 'GroupFlags' in group_props, group_props tubes_self_handle = tubes_chan.GetSelfHandle( dbus_interface=cs.CHANNEL_IFACE_GROUP) assert group_props['SelfHandle'] == tubes_self_handle # Offer a D-Bus tube (old API) call_async(q, tubes_iface, 'OfferDBusTube', 'com.example.TestCase', sample_parameters) new_tube_event, presence_event, offer_return_event, dbus_changed_event = \ q.expect_many( EventPattern('dbus-signal', signal='NewTube'), EventPattern('stream-presence', to='[email protected]/test'), EventPattern('dbus-return', method='OfferDBusTube'), EventPattern('dbus-signal', signal='DBusNamesChanged', interface=cs.CHANNEL_TYPE_TUBES)) # handle new_tube_event dbus_tube_id = new_tube_event.args[0] assert new_tube_event.args[1] == tubes_self_handle assert new_tube_event.args[2] == cs.TUBE_TYPE_DBUS assert new_tube_event.args[3] == 'com.example.TestCase' assert new_tube_event.args[4] == sample_parameters assert new_tube_event.args[5] == cs.TUBE_STATE_OPEN # handle offer_return_event assert offer_return_event.value[0] == dbus_tube_id # handle presence_event # We announce our newly created tube in our muc presence presence = presence_event.stanza dbus_stream_id, my_bus_name = check_tube_in_presence(presence, dbus_tube_id, '[email protected]/test') # handle dbus_changed_event assert dbus_changed_event.args[0] == dbus_tube_id assert dbus_changed_event.args[1][0][0] == tubes_self_handle assert dbus_changed_event.args[1][0][1] == my_bus_name # handle offer_return_event assert dbus_tube_id == offer_return_event.value[0] tubes = tubes_iface.ListTubes(byte_arrays=True) assert len(tubes) == 1 expected_tube = (dbus_tube_id, tubes_self_handle, cs.TUBE_TYPE_DBUS, 'com.example.TestCase', sample_parameters, cs.TUBE_STATE_OPEN) t.check_tube_in_tubes(expected_tube, tubes) dbus_tube_adr = tubes_iface.GetDBusTubeAddress(dbus_tube_id) tube = Connection(dbus_tube_adr) fire_signal_on_tube(q, tube, '*****@*****.**', dbus_stream_id, my_bus_name) # offer a D-Bus tube to another room using new API muc = '*****@*****.**' request = { cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_DBUS_TUBE, cs.TARGET_HANDLE_TYPE: cs.HT_ROOM, cs.TARGET_ID: '*****@*****.**', cs.DBUS_TUBE_SERVICE_NAME: 'com.example.TestCase', } join_muc(q, bus, conn, stream, muc, request=request) # first text and tubes channels are announced event = q.expect('dbus-signal', signal='NewChannels') channels = event.args[0] assert len(channels) == 2 path1, prop1 = channels[0] path2, prop2 = channels[1] assert sorted([prop1[cs.CHANNEL_TYPE], prop2[cs.CHANNEL_TYPE]]) == \ [cs.CHANNEL_TYPE_TEXT, cs.CHANNEL_TYPE_TUBES] got_text, got_tubes = False, False for path, props in channels: if props[cs.CHANNEL_TYPE] == cs.CHANNEL_TYPE_TEXT: got_text = True text_chan = dbus.Interface(bus.get_object(conn.bus_name, path), cs.CHANNEL) elif props[cs.CHANNEL_TYPE] == cs.CHANNEL_TYPE_TUBES: got_tubes = True tubes_iface = dbus.Interface(bus.get_object(conn.bus_name, path), cs.CHANNEL_TYPE_TUBES) else: assert False assert props[cs.INITIATOR_HANDLE] == self_handle assert props[cs.INITIATOR_ID] == self_name assert cs.CHANNEL_IFACE_GROUP in props[cs.INTERFACES] assert props[cs.TARGET_ID] == '*****@*****.**' assert props[cs.REQUESTED] == False assert (got_text, got_tubes) == (True, True) # now the tube channel is announced # FIXME: in this case, all channels should probably be announced together event = q.expect('dbus-signal', signal='NewChannels') channels = event.args[0] assert len(channels) == 1 path, prop = channels[0] assert prop[cs.CHANNEL_TYPE] == cs.CHANNEL_TYPE_DBUS_TUBE assert prop[cs.INITIATOR_ID] == '[email protected]/test' assert prop[cs.REQUESTED] == True assert prop[cs.TARGET_HANDLE_TYPE] == cs.HT_ROOM assert prop[cs.TARGET_ID] == '*****@*****.**' assert prop[cs.DBUS_TUBE_SERVICE_NAME] == 'com.example.TestCase' assert prop[cs.DBUS_TUBE_SUPPORTED_ACCESS_CONTROLS] == [cs.SOCKET_ACCESS_CONTROL_CREDENTIALS, cs.SOCKET_ACCESS_CONTROL_LOCALHOST] # check that the tube channel is in the channels list all_channels = conn.Get(cs.CONN_IFACE_REQUESTS, 'Channels', dbus_interface=cs.PROPERTIES_IFACE, byte_arrays=True) assertContains((path, prop), all_channels) tube_chan = bus.get_object(conn.bus_name, path) dbus_tube_iface = dbus.Interface(tube_chan, cs.CHANNEL_TYPE_DBUS_TUBE) chan_iface = dbus.Interface(tube_chan, cs.CHANNEL) tube_props = tube_chan.GetAll(cs.CHANNEL_IFACE_TUBE, dbus_interface=cs.PROPERTIES_IFACE, byte_arrays=True) assert tube_props['State'] == cs.TUBE_CHANNEL_STATE_NOT_OFFERED # try to offer using a wrong access control try: dbus_tube_iface.Offer(sample_parameters, cs.SOCKET_ACCESS_CONTROL_PORT) except dbus.DBusException, e: assertEquals(e.get_dbus_name(), cs.INVALID_ARGUMENT)
def test(q, bus, conn, stream, access_control): iq_event = q.expect("stream-iq", to=None, query_ns="vcard-temp", query_name="vCard") acknowledge_iq(stream, iq_event.stanza) # check if we can request muc D-Bus tube t.check_conn_properties(q, conn) self_handle = conn.GetSelfHandle() self_name = conn.InspectHandles(1, [self_handle])[0] handle, tubes_chan, tubes_iface = get_muc_tubes_channel(q, bus, conn, stream, "*****@*****.**") # Exercise basic Channel Properties from spec 0.17.7 channel_props = tubes_chan.GetAll(cs.CHANNEL, dbus_interface=dbus.PROPERTIES_IFACE) assert channel_props.get("TargetHandle") == handle, (channel_props.get("TargetHandle"), handle) assert channel_props.get("TargetHandleType") == 2, channel_props.get("TargetHandleType") assert channel_props.get("ChannelType") == cs.CHANNEL_TYPE_TUBES, channel_props.get("ChannelType") assert "Interfaces" in channel_props, channel_props assert cs.CHANNEL_IFACE_GROUP in channel_props["Interfaces"], channel_props["Interfaces"] assert channel_props["TargetID"] == "*****@*****.**", channel_props assert channel_props["Requested"] == True assert channel_props["InitiatorID"] == "test@localhost" assert channel_props["InitiatorHandle"] == conn.GetSelfHandle() # Exercise Group Properties from spec 0.17.6 (in a basic way) group_props = tubes_chan.GetAll(cs.CHANNEL_IFACE_GROUP, dbus_interface=dbus.PROPERTIES_IFACE) assert "SelfHandle" in group_props, group_props assert "HandleOwners" in group_props, group_props assert "Members" in group_props, group_props assert "LocalPendingMembers" in group_props, group_props assert "RemotePendingMembers" in group_props, group_props assert "GroupFlags" in group_props, group_props tubes_self_handle = tubes_chan.GetSelfHandle(dbus_interface=cs.CHANNEL_IFACE_GROUP) assert group_props["SelfHandle"] == tubes_self_handle # Offer a D-Bus tube (old API) call_async(q, tubes_iface, "OfferDBusTube", "com.example.TestCase", sample_parameters) new_tube_event, presence_event, offer_return_event, dbus_changed_event = q.expect_many( EventPattern("dbus-signal", signal="NewTube"), EventPattern("stream-presence", to="[email protected]/test"), EventPattern("dbus-return", method="OfferDBusTube"), EventPattern("dbus-signal", signal="DBusNamesChanged", interface=cs.CHANNEL_TYPE_TUBES), ) # handle new_tube_event dbus_tube_id = new_tube_event.args[0] assert new_tube_event.args[1] == tubes_self_handle assert new_tube_event.args[2] == cs.TUBE_TYPE_DBUS assert new_tube_event.args[3] == "com.example.TestCase" assert new_tube_event.args[4] == sample_parameters assert new_tube_event.args[5] == cs.TUBE_STATE_OPEN # handle offer_return_event assert offer_return_event.value[0] == dbus_tube_id # handle presence_event # We announce our newly created tube in our muc presence presence = presence_event.stanza dbus_stream_id, my_bus_name = check_tube_in_presence(presence, dbus_tube_id, "[email protected]/test") # handle dbus_changed_event assert dbus_changed_event.args[0] == dbus_tube_id assert dbus_changed_event.args[1][0][0] == tubes_self_handle assert dbus_changed_event.args[1][0][1] == my_bus_name # handle offer_return_event assert dbus_tube_id == offer_return_event.value[0] tubes = tubes_iface.ListTubes(byte_arrays=True) assert len(tubes) == 1 expected_tube = ( dbus_tube_id, tubes_self_handle, cs.TUBE_TYPE_DBUS, "com.example.TestCase", sample_parameters, cs.TUBE_STATE_OPEN, ) t.check_tube_in_tubes(expected_tube, tubes) dbus_tube_adr = tubes_iface.GetDBusTubeAddress(dbus_tube_id) tube = Connection(dbus_tube_adr) fire_signal_on_tube(q, tube, "*****@*****.**", dbus_stream_id, my_bus_name) # offer a D-Bus tube to another room using new API muc = "*****@*****.**" request = { cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_DBUS_TUBE, cs.TARGET_HANDLE_TYPE: cs.HT_ROOM, cs.TARGET_ID: "*****@*****.**", cs.DBUS_TUBE_SERVICE_NAME: "com.example.TestCase", } join_muc(q, bus, conn, stream, muc, request=request) # The order in which the NewChannels signals are fired is # undefined -- it could be the (tubes, text) channels first, or it # could be the tube channel first; so let's accept either order # here. first, second = q.expect_many( EventPattern("dbus-signal", signal="NewChannels"), EventPattern("dbus-signal", signal="NewChannels") ) # NewChannels signal with the text and tubes channels together. def nc_textandtubes(event): channels = event.args[0] assert len(channels) == 2 path1, prop1 = channels[0] path2, prop2 = channels[1] assert sorted([prop1[cs.CHANNEL_TYPE], prop2[cs.CHANNEL_TYPE]]) == [cs.CHANNEL_TYPE_TEXT, cs.CHANNEL_TYPE_TUBES] got_text, got_tubes = False, False for path, props in channels: if props[cs.CHANNEL_TYPE] == cs.CHANNEL_TYPE_TEXT: got_text = True text_chan = dbus.Interface(bus.get_object(conn.bus_name, path), cs.CHANNEL) elif props[cs.CHANNEL_TYPE] == cs.CHANNEL_TYPE_TUBES: got_tubes = True tubes_iface = dbus.Interface(bus.get_object(conn.bus_name, path), cs.CHANNEL_TYPE_TUBES) else: assert False assert props[cs.INITIATOR_HANDLE] == self_handle assert props[cs.INITIATOR_ID] == self_name assert cs.CHANNEL_IFACE_GROUP in props[cs.INTERFACES] assert props[cs.TARGET_ID] == "*****@*****.**" assert props[cs.REQUESTED] == False assert (got_text, got_tubes) == (True, True) return text_chan # NewChannels signal with the tube channel. def nc_tube(event): # FIXME: in this case, all channels should probably be announced together channels = event.args[0] assert len(channels) == 1 path, prop = channels[0] assert prop[cs.CHANNEL_TYPE] == cs.CHANNEL_TYPE_DBUS_TUBE assert prop[cs.INITIATOR_ID] == "[email protected]/test" assert prop[cs.REQUESTED] == True assert prop[cs.TARGET_HANDLE_TYPE] == cs.HT_ROOM assert prop[cs.TARGET_ID] == "*****@*****.**" assert prop[cs.DBUS_TUBE_SERVICE_NAME] == "com.example.TestCase" assert prop[cs.DBUS_TUBE_SUPPORTED_ACCESS_CONTROLS] == [ cs.SOCKET_ACCESS_CONTROL_CREDENTIALS, cs.SOCKET_ACCESS_CONTROL_LOCALHOST, ] return path, prop if len(first.args[0]) == 1: path, prop = nc_tube(first) text_chan = nc_textandtubes(second) else: text_chan = nc_textandtubes(first) path, prop = nc_tube(second) # check that the tube channel is in the channels list all_channels = conn.Get(cs.CONN_IFACE_REQUESTS, "Channels", dbus_interface=cs.PROPERTIES_IFACE, byte_arrays=True) assertContains((path, prop), all_channels) tube_chan = bus.get_object(conn.bus_name, path) dbus_tube_iface = dbus.Interface(tube_chan, cs.CHANNEL_TYPE_DBUS_TUBE) chan_iface = dbus.Interface(tube_chan, cs.CHANNEL) tube_props = tube_chan.GetAll(cs.CHANNEL_IFACE_TUBE, dbus_interface=cs.PROPERTIES_IFACE, byte_arrays=True) assert tube_props["State"] == cs.TUBE_CHANNEL_STATE_NOT_OFFERED # try to offer using a wrong access control try: dbus_tube_iface.Offer(sample_parameters, cs.SOCKET_ACCESS_CONTROL_PORT) except dbus.DBusException, e: assertEquals(e.get_dbus_name(), cs.INVALID_ARGUMENT)
def test(q, bus, conn, stream, bytestream_cls, address_type, access_control, access_control_param): if bytestream_cls in [BytestreamS5BRelay, BytestreamS5BRelayBugged]: # disable SOCKS5 relay tests because proxy can't be used with muc # contacts atm return iq_event, disco_event = q.expect_many( EventPattern('stream-iq', to=None, query_ns='vcard-temp', query_name='vCard'), EventPattern('stream-iq', to='localhost', query_ns=ns.DISCO_ITEMS)) acknowledge_iq(stream, iq_event.stanza) announce_socks5_proxy(q, stream, disco_event.stanza) call_async(q, conn, 'RequestHandles', 2, ['*****@*****.**']) event = q.expect('dbus-return', method='RequestHandles') handles = event.value[0] room_handle = handles[0] # join the muc call_async(q, conn, 'RequestChannel', cs.CHANNEL_TYPE_TEXT, cs.HT_ROOM, room_handle, True) _, stream_event = q.expect_many( EventPattern('dbus-signal', signal='MembersChanged', args=[u'', [], [], [], [2], 0, 0]), EventPattern('stream-presence', to='[email protected]/test')) # Send presence for other member of room. stream.send(make_muc_presence('owner', 'moderator', '*****@*****.**', 'bob')) # Send presence for own membership of room. stream.send(make_muc_presence('none', 'participant', '*****@*****.**', 'test')) q.expect('dbus-signal', signal='MembersChanged', args=[u'', [2, 3], [], [], [], 0, 0]) assert conn.InspectHandles(1, [2]) == ['[email protected]/test'] assert conn.InspectHandles(1, [3]) == ['[email protected]/bob'] bob_handle = 3 event = q.expect('dbus-return', method='RequestChannel') # Bob offers a stream tube stream_tube_id = 666 presence = make_muc_presence('owner', 'moderator', '*****@*****.**', 'bob') tubes = presence.addElement((ns.TUBES, 'tubes')) tube = tubes.addElement((None, 'tube')) tube['type'] = 'stream' tube['service'] = 'echo' tube['id'] = str(stream_tube_id) parameters = tube.addElement((None, 'parameters')) parameter = parameters.addElement((None, 'parameter')) parameter['name'] = 's' parameter['type'] = 'str' parameter.addContent('hello') parameter = parameters.addElement((None, 'parameter')) parameter['name'] = 'ay' parameter['type'] = 'bytes' parameter.addContent('aGVsbG8=') parameter = parameters.addElement((None, 'parameter')) parameter['name'] = 'u' parameter['type'] = 'uint' parameter.addContent('123') parameter = parameters.addElement((None, 'parameter')) parameter['name'] = 'i' parameter['type'] = 'int' parameter.addContent('-123') stream.send(presence) # text channel event, new_event = q.expect_many( EventPattern('dbus-signal', signal='NewChannel'), EventPattern('dbus-signal', signal='NewChannels')) assert event.args[1] == cs.CHANNEL_TYPE_TEXT, event.args channels = new_event.args[0] assert len(channels) == 1 path, props = channels[0] assert props[cs.CHANNEL_TYPE] == cs.CHANNEL_TYPE_TEXT # tubes channel is automatically created event, new_event = q.expect_many( EventPattern('dbus-signal', signal='NewChannel'), EventPattern('dbus-signal', signal='NewChannels')) assert event.args[1] == cs.CHANNEL_TYPE_TUBES, event.args assert event.args[2] == cs.HT_ROOM assert event.args[3] == room_handle tubes_chan = bus.get_object(conn.bus_name, event.args[0]) tubes_iface = dbus.Interface(tubes_chan, event.args[1]) channel_props = tubes_chan.GetAll(cs.CHANNEL, dbus_interface=cs.PROPERTIES_IFACE) assert channel_props['TargetID'] == '*****@*****.**', channel_props assert channel_props['Requested'] == False assert channel_props['InitiatorID'] == '' assert channel_props['InitiatorHandle'] == 0 channels = new_event.args[0] assert len(channels) == 1 path, props = channels[0] assert props[cs.CHANNEL_TYPE] == cs.CHANNEL_TYPE_TUBES tubes_self_handle = tubes_chan.GetSelfHandle(dbus_interface=cs.CHANNEL_IFACE_GROUP) q.expect('dbus-signal', signal='NewTube', args=[stream_tube_id, bob_handle, 1, 'echo', sample_parameters, 0]) expected_tube = (stream_tube_id, bob_handle, cs.TUBE_TYPE_STREAM, 'echo', sample_parameters, cs.TUBE_STATE_LOCAL_PENDING) tubes = tubes_iface.ListTubes(byte_arrays=True) assert tubes == [( stream_tube_id, bob_handle, 1, # Stream 'echo', sample_parameters, cs.TUBE_CHANNEL_STATE_LOCAL_PENDING )] assert len(tubes) == 1, unwrap(tubes) t.check_tube_in_tubes(expected_tube, tubes) # tube channel is also announced (new API) new_event = q.expect('dbus-signal', signal='NewChannels') channels = new_event.args[0] assert len(channels) == 1 path, props = channels[0] assert props[cs.CHANNEL_TYPE] == cs.CHANNEL_TYPE_STREAM_TUBE assert props[cs.INITIATOR_HANDLE] == bob_handle assert props[cs.INITIATOR_ID] == '[email protected]/bob' assert props[cs.INTERFACES] == [cs.CHANNEL_IFACE_GROUP, cs.CHANNEL_IFACE_TUBE] assert props[cs.REQUESTED] == False assert props[cs.TARGET_HANDLE] == room_handle assert props[cs.TARGET_ID] == '*****@*****.**' assert props[cs.STREAM_TUBE_SERVICE] == 'echo' assert props[cs.TUBE_PARAMETERS] == {'s': 'hello', 'ay': 'hello', 'u': 123, 'i': -123} assert access_control in \ props[cs.STREAM_TUBE_SUPPORTED_SOCKET_TYPES][address_type] tube_chan = bus.get_object(conn.bus_name, path) tube_props = tube_chan.GetAll(cs.CHANNEL_IFACE_TUBE, dbus_interface=cs.PROPERTIES_IFACE, byte_arrays=True) assert tube_props['Parameters'] == sample_parameters assert tube_props['State'] == cs.TUBE_CHANNEL_STATE_LOCAL_PENDING # Accept the tube call_async(q, tubes_iface, 'AcceptStreamTube', stream_tube_id, address_type, access_control, access_control_param, byte_arrays=True) accept_return_event, _ = q.expect_many( EventPattern('dbus-return', method='AcceptStreamTube'), EventPattern('dbus-signal', signal='TubeStateChanged', args=[stream_tube_id, 2])) address = accept_return_event.value[0] socket_event, si_event, conn_id = t.connect_to_cm_socket(q, '[email protected]/bob', address_type, address, access_control, access_control_param) protocol = socket_event.protocol protocol.sendData("hello initiator") def accept_tube_si_connection(): bytestream, profile = create_from_si_offer(stream, q, bytestream_cls, si_event.stanza, '[email protected]/test') assert profile == ns.TUBES muc_stream_node = xpath.queryForNodes('/iq/si/muc-stream[@xmlns="%s"]' % ns.TUBES, si_event.stanza)[0] assert muc_stream_node is not None assert muc_stream_node['tube'] == str(stream_tube_id) # set the real jid of the target as 'to' because the XMPP server changes # it when delivering the IQ result, si = bytestream.create_si_reply(si_event.stanza, 'test@localhost/Resource') si.addElement((ns.TUBES, 'tube')) stream.send(result) bytestream.wait_bytestream_open() return bytestream bytestream = accept_tube_si_connection() binary = bytestream.get_data() assert binary == 'hello initiator' # reply on the socket bytestream.send_data('hi joiner!') q.expect('socket-data', protocol=protocol, data="hi joiner!") # peer closes the bytestream bytestream.close() e = q.expect('dbus-signal', signal='ConnectionClosed') assertEquals(conn_id, e.args[0]) assertEquals(cs.CONNECTION_LOST, e.args[1]) # establish another tube connection socket_event, si_event, conn_id = t.connect_to_cm_socket(q, '[email protected]/bob', address_type, address, access_control, access_control_param) # bytestream is refused send_error_reply(stream, si_event.stanza) e, _ = q.expect_many( EventPattern('dbus-signal', signal='ConnectionClosed'), EventPattern('socket-disconnected')) assertEquals(conn_id, e.args[0]) assertEquals(cs.CONNECTION_REFUSED, e.args[1]) # establish another tube connection socket_event, si_event, conn_id = t.connect_to_cm_socket(q, '[email protected]/bob', address_type, address, access_control, access_control_param) protocol = socket_event.protocol bytestream = accept_tube_si_connection() # disconnect local socket protocol.transport.loseConnection() e, _ = q.expect_many( EventPattern('dbus-signal', signal='ConnectionClosed'), EventPattern('socket-disconnected')) assertEquals(conn_id, e.args[0]) assertEquals(cs.CANCELLED, e.args[1]) # OK, we're done disconnect_conn(q, conn, stream, [EventPattern('dbus-signal', signal='TubeClosed', args=[stream_tube_id])])
def test(q, bus, conn, stream, bytestream_cls, address_type, access_control, access_control_param): if bytestream_cls in [BytestreamS5BRelay, BytestreamS5BRelayBugged]: # disable SOCKS5 relay tests because proxy can't be used with muc # contacts atm return iq_event = q.expect('stream-iq', to=None, query_ns='vcard-temp', query_name='vCard') acknowledge_iq(stream, iq_event.stanza) self_handle = conn.GetSelfHandle() self_name = conn.InspectHandles(cs.HT_CONTACT, [self_handle])[0] t.check_conn_properties(q, conn) room_handle, tubes_chan, tubes_iface = get_muc_tubes_channel(q, bus, conn, stream, '*****@*****.**') tubes_self_handle = tubes_chan.GetSelfHandle(dbus_interface=cs.CHANNEL_IFACE_GROUP) bob_handle = conn.RequestHandles(cs.HT_CONTACT, ['[email protected]/bob'])[0] address = t.create_server(q, address_type) # offer stream tube (old API) using an Unix socket call_async(q, tubes_iface, 'OfferStreamTube', 'echo', sample_parameters, address_type, address, access_control, access_control_param) new_tube_event, stream_event, _, new_channels_event = q.expect_many( EventPattern('dbus-signal', signal='NewTube'), EventPattern('stream-presence', to='[email protected]/test'), EventPattern('dbus-return', method='OfferStreamTube'), EventPattern('dbus-signal', signal='NewChannels')) # handle new_tube_event stream_tube_id = new_tube_event.args[0] assert new_tube_event.args[1] == tubes_self_handle assert new_tube_event.args[2] == 1 # Stream assert new_tube_event.args[3] == 'echo' assert new_tube_event.args[4] == sample_parameters assert new_tube_event.args[5] == cs.TUBE_CHANNEL_STATE_OPEN # handle stream_event # We announce our newly created tube in our muc presence presence = stream_event.stanza tubes_nodes = xpath.queryForNodes('/presence/tubes[@xmlns="%s"]' % ns.TUBES, presence) assert tubes_nodes is not None assert len(tubes_nodes) == 1 tube_nodes = xpath.queryForNodes('/tubes/tube', tubes_nodes[0]) assert tube_nodes is not None assert len(tube_nodes) == 1 for tube in tube_nodes: assert tube['type'] == 'stream' assert not tube.hasAttribute('initiator') assert tube['service'] == 'echo' assert not tube.hasAttribute('stream-id') assert not tube.hasAttribute('dbus-name') assert tube['id'] == str(stream_tube_id) params = {} parameter_nodes = xpath.queryForNodes('/tube/parameters/parameter', tube) for node in parameter_nodes: assert node['name'] not in params params[node['name']] = (node['type'], str(node)) assert params == {'ay': ('bytes', 'aGVsbG8='), 's': ('str', 'hello'), 'i': ('int', '-123'), 'u': ('uint', '123'), } # tube is also announced using new API channels = new_channels_event.args[0] assert len(channels) == 1 path, props = channels[0] assert props[cs.CHANNEL_TYPE] == cs.CHANNEL_TYPE_STREAM_TUBE assert props[cs.INITIATOR_HANDLE] == tubes_self_handle assert props[cs.INITIATOR_ID] == '[email protected]/test' assert props[cs.INTERFACES] == [cs.CHANNEL_IFACE_GROUP, cs.CHANNEL_IFACE_TUBE] assert props[cs.REQUESTED] == True assert props[cs.TARGET_HANDLE] == room_handle assert props[cs.TARGET_ID] == '*****@*****.**' assert props[cs.STREAM_TUBE_SERVICE] == 'echo' tube_chan = bus.get_object(conn.bus_name, path) tube_props = tube_chan.GetAll(cs.CHANNEL_IFACE_TUBE, dbus_interface=cs.PROPERTIES_IFACE, byte_arrays=True) assert tube_props['Parameters'] == sample_parameters assert tube_props['State'] == cs.TUBE_CHANNEL_STATE_OPEN tubes = tubes_iface.ListTubes(byte_arrays=True) assert tubes == [( stream_tube_id, tubes_self_handle, 1, # Stream 'echo', sample_parameters, cs.TUBE_CHANNEL_STATE_OPEN )] assert len(tubes) == 1, unwrap(tubes) expected_tube = (stream_tube_id, tubes_self_handle, cs.TUBE_TYPE_STREAM, 'echo', sample_parameters, cs.TUBE_STATE_OPEN) t.check_tube_in_tubes(expected_tube, tubes) # FIXME: if we use an unknown JID here, everything fails # (the code uses lookup where it should use ensure) bytestream = connect_to_tube(stream, q, bytestream_cls, '*****@*****.**', stream_tube_id) iq_event, socket_event, _, conn_event = q.expect_many( EventPattern('stream-iq', iq_type='result'), EventPattern('socket-connected'), EventPattern('dbus-signal', signal='StreamTubeNewConnection', args=[stream_tube_id, bob_handle], interface=cs.CHANNEL_TYPE_TUBES), EventPattern('dbus-signal', signal='NewRemoteConnection', interface=cs.CHANNEL_TYPE_STREAM_TUBE)) protocol = socket_event.protocol # handle iq_event bytestream.check_si_reply(iq_event.stanza) tube = xpath.queryForNodes('/iq//si/tube[@xmlns="%s"]' % ns.TUBES, iq_event.stanza) assert len(tube) == 1 handle, access, conn_id = conn_event.args assert handle == bob_handle use_tube(q, bytestream, protocol, conn_id) # offer a stream tube to another room (new API) address = t.create_server(q, address_type, block_reading=True) request = { cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_STREAM_TUBE, cs.TARGET_HANDLE_TYPE: cs.HT_ROOM, cs.TARGET_ID: '*****@*****.**', cs.STREAM_TUBE_SERVICE: 'newecho', } _, _, new_tube_path, new_tube_props = \ join_muc(q, bus, conn, stream, '*****@*****.**', request) # The order in which the NewChannels signals are fired is # undefined -- it could be the (tubes, text) channels first, or it # could be the tube channel first; so let's accept either order # here. first, second = q.expect_many( EventPattern('dbus-signal', signal='NewChannels'), EventPattern('dbus-signal', signal='NewChannels')) # NewChannels signal with the text and tubes channels together. def nc_textandtubes(event): channels = event.args[0] assert len(channels) == 2 path1, prop1 = channels[0] path2, prop2 = channels[1] assert sorted([prop1[cs.CHANNEL_TYPE], prop2[cs.CHANNEL_TYPE]]) == \ [cs.CHANNEL_TYPE_TEXT, cs.CHANNEL_TYPE_TUBES] got_text, got_tubes = False, False for path, props in channels: if props[cs.CHANNEL_TYPE] == cs.CHANNEL_TYPE_TEXT: got_text = True elif props[cs.CHANNEL_TYPE] == cs.CHANNEL_TYPE_TUBES: got_tubes = True else: assert False assert props[cs.INITIATOR_HANDLE] == self_handle assert props[cs.INITIATOR_ID] == self_name assert cs.CHANNEL_IFACE_GROUP in props[cs.INTERFACES] assert props[cs.TARGET_ID] == '*****@*****.**' assert props[cs.REQUESTED] == False assert (got_text, got_tubes) == (True, True) # NewChannels signal with the tube channel. def nc_tube(event): # FIXME: in this case, all channels should probably be announced together channels = event.args[0] assert len(channels) == 1 path, prop = channels[0] assert prop[cs.CHANNEL_TYPE] == cs.CHANNEL_TYPE_STREAM_TUBE assert prop[cs.INITIATOR_ID] == '[email protected]/test' assert prop[cs.REQUESTED] == True assert prop[cs.TARGET_HANDLE_TYPE] == cs.HT_ROOM assert prop[cs.TARGET_ID] == '*****@*****.**' assert prop[cs.STREAM_TUBE_SERVICE] == 'newecho' return path, prop if len(first.args[0]) == 1: path, prop = nc_tube(first) nc_textandtubes(second) else: nc_textandtubes(first) path, prop = nc_tube(second) # check that the tube channel is in the channels list all_channels = conn.Get(cs.CONN_IFACE_REQUESTS, 'Channels', dbus_interface=cs.PROPERTIES_IFACE, byte_arrays=True) assertContains((path, prop), all_channels) tube_chan = bus.get_object(conn.bus_name, path) stream_tube_iface = dbus.Interface(tube_chan, cs.CHANNEL_TYPE_STREAM_TUBE) chan_iface = dbus.Interface(tube_chan, cs.CHANNEL) tube_props = tube_chan.GetAll(cs.CHANNEL_IFACE_TUBE, dbus_interface=cs.PROPERTIES_IFACE) assert tube_props['State'] == cs.TUBE_CHANNEL_STATE_NOT_OFFERED # offer the tube call_async(q, stream_tube_iface, 'Offer', address_type, address, access_control, {'foo': 'bar'}) new_tube_event, stream_event, _, status_event = q.expect_many( EventPattern('dbus-signal', signal='NewTube'), EventPattern('stream-presence', to='[email protected]/test'), EventPattern('dbus-return', method='Offer'), EventPattern('dbus-signal', signal='TubeChannelStateChanged', args=[cs.TUBE_CHANNEL_STATE_OPEN])) tube_self_handle = tube_chan.GetSelfHandle(dbus_interface=cs.CHANNEL_IFACE_GROUP) assert conn.InspectHandles(cs.HT_CONTACT, [tube_self_handle]) == ['[email protected]/test'] # handle new_tube_event stream_tube_id = new_tube_event.args[0] assert new_tube_event.args[2] == 1 # Stream assert new_tube_event.args[3] == 'newecho' assert new_tube_event.args[4] == {'foo': 'bar'} assert new_tube_event.args[5] == cs.TUBE_CHANNEL_STATE_OPEN presence = stream_event.stanza tubes_nodes = xpath.queryForNodes('/presence/tubes[@xmlns="%s"]' % ns.TUBES, presence) assert tubes_nodes is not None assert len(tubes_nodes) == 1 tube_nodes = xpath.queryForNodes('/tubes/tube', tubes_nodes[0]) assert tube_nodes is not None assert len(tube_nodes) == 1 for tube in tube_nodes: assert tube['type'] == 'stream' assert not tube.hasAttribute('initiator') assert tube['service'] == 'newecho' assert not tube.hasAttribute('stream-id') assert not tube.hasAttribute('dbus-name') assert tube['id'] == str(stream_tube_id) params = {} parameter_nodes = xpath.queryForNodes('/tube/parameters/parameter', tube) for node in parameter_nodes: assert node['name'] not in params params[node['name']] = (node['type'], str(node)) assert params == {'foo': ('str', 'bar')} bob_handle = conn.RequestHandles(cs.HT_CONTACT, ['[email protected]/bob'])[0] bytestream = connect_to_tube(stream, q, bytestream_cls, '*****@*****.**', stream_tube_id) iq_event, socket_event, conn_event = q.expect_many( EventPattern('stream-iq', iq_type='result'), EventPattern('socket-connected'), EventPattern('dbus-signal', signal='NewRemoteConnection', interface=cs.CHANNEL_TYPE_STREAM_TUBE)) handle, access, conn_id = conn_event.args assert handle == bob_handle protocol = socket_event.protocol # start to read from the transport so we can read the control byte protocol.transport.startReading() t.check_new_connection_access(q, access_control, access, protocol) # handle iq_event bytestream.check_si_reply(iq_event.stanza) tube = xpath.queryForNodes('/iq//si/tube[@xmlns="%s"]' % ns.TUBES, iq_event.stanza) assert len(tube) == 1 use_tube(q, bytestream, protocol, conn_id) chan_iface.Close() q.expect_many( EventPattern('dbus-signal', signal='Closed'), EventPattern('dbus-signal', signal='ChannelClosed'))