use of org.jivesoftware.smack.filter.StanzaIdFilter in project Smack by igniterealtime.
the class AbstractXMPPConnection method bindResourceAndEstablishSession.
protected Resourcepart bindResourceAndEstablishSession(Resourcepart resource) throws SmackException, InterruptedException, XMPPException {
// Wait until either:
// - the servers last features stanza has been parsed
// - the timeout occurs
LOGGER.finer("Waiting for last features to be received before continuing with resource binding");
waitForConditionOrThrowConnectionException(() -> lastFeaturesReceived, "last stream features received from server");
if (!hasFeature(Bind.ELEMENT, Bind.NAMESPACE)) {
// server implementations as per RFC6120 7.2
throw new ResourceBindingNotOfferedException();
}
// Resource binding, see RFC6120 7.
// Note that we can not use IQReplyFilter here, since the users full JID is not yet
// available. It will become available right after the resource has been successfully bound.
Bind bindResource = Bind.newSet(resource);
StanzaCollector packetCollector = createStanzaCollectorAndSend(new StanzaIdFilter(bindResource), bindResource);
Bind response = packetCollector.nextResultOrThrow();
// Set the connections user to the result of resource binding. It is important that we don't infer the user
// from the login() arguments and the configurations service name, as, for example, when SASL External is used,
// the username is not given to login but taken from the 'external' certificate.
user = response.getJid();
xmppServiceDomain = user.asDomainBareJid();
Session.Feature sessionFeature = getFeature(Session.Feature.class);
// For more information see http://tools.ietf.org/html/draft-cridland-xmpp-session-01
if (sessionFeature != null && !sessionFeature.isOptional()) {
Session session = new Session();
packetCollector = createStanzaCollectorAndSend(new StanzaIdFilter(session), session);
packetCollector.nextResultOrThrow();
}
return response.getJid().getResourcepart();
}
use of org.jivesoftware.smack.filter.StanzaIdFilter in project Smack by igniterealtime.
the class MultiUserChat method enter.
/**
* Enter a room, as described in XEP-45 7.2.
*
* @param conf the configuration used to enter the room.
* @return the returned presence by the service after the client send the initial presence in order to enter the room.
* @throws NotConnectedException if the XMPP connection is not connected.
* @throws NoResponseException if there was no response from the remote entity.
* @throws XMPPErrorException if there was an XMPP error returned.
* @throws InterruptedException if the calling thread was interrupted.
* @throws NotAMucServiceException if the entity is not a MUC serivce.
* @see <a href="http://xmpp.org/extensions/xep-0045.html#enter">XEP-45 7.2 Entering a Room</a>
*/
private Presence enter(MucEnterConfiguration conf) throws NotConnectedException, NoResponseException, XMPPErrorException, InterruptedException, NotAMucServiceException {
final DomainBareJid mucService = room.asDomainBareJid();
mucServiceDiscoInfo = multiUserChatManager.getMucServiceDiscoInfo(mucService);
if (mucServiceDiscoInfo == null) {
throw new NotAMucServiceException(this);
}
// We enter a room by sending a presence packet where the "to"
// field is in the form "roomName@service/nickname"
Presence joinPresence = conf.getJoinPresence(this);
// Setup the messageListeners and presenceListeners *before* the join presence is send.
connection.addStanzaListener(messageListener, fromRoomGroupchatFilter);
StanzaFilter presenceFromRoomFilter = new AndFilter(fromRoomFilter, StanzaTypeFilter.PRESENCE, PossibleFromTypeFilter.ENTITY_FULL_JID);
connection.addStanzaListener(presenceListener, presenceFromRoomFilter);
// @formatter:off
connection.addStanzaListener(subjectListener, new AndFilter(fromRoomFilter, MessageWithSubjectFilter.INSTANCE, new NotFilter(MessageTypeFilter.ERROR), // legitimate message, but it SHALL NOT be interpreted as a subject change."
new NotFilter(MessageWithBodiesFilter.INSTANCE), new NotFilter(MessageWithThreadFilter.INSTANCE)));
// @formatter:on
connection.addStanzaListener(declinesListener, new AndFilter(fromRoomFilter, DECLINE_FILTER));
connection.addStanzaSendingListener(presenceInterceptor, new AndFilter(ToMatchesFilter.create(room), StanzaTypeFilter.PRESENCE));
messageCollector = connection.createStanzaCollector(fromRoomGroupchatFilter);
// Wait for a presence packet back from the server.
// @formatter:off
StanzaFilter responseFilter = new AndFilter(StanzaTypeFilter.PRESENCE, new OrFilter(// We use a bare JID filter for positive responses, since the MUC service/room may rewrite the nickname.
new AndFilter(FromMatchesFilter.createBare(getRoom()), MUCUserStatusCodeFilter.STATUS_110_PRESENCE_TO_SELF), // JID we send the join presence to.
new AndFilter(FromMatchesFilter.createFull(joinPresence.getTo()), new StanzaIdFilter(joinPresence), PresenceTypeFilter.ERROR)));
// @formatter:on
processedReflectedSelfPresence = false;
StanzaCollector presenceStanzaCollector = null;
final Presence reflectedSelfPresence;
try {
// This stanza collector will collect the final self presence from the MUC, which also signals that we have successful entered the MUC.
StanzaCollector selfPresenceCollector = connection.createStanzaCollectorAndSend(responseFilter, joinPresence);
StanzaCollector.Configuration presenceStanzaCollectorConfguration = StanzaCollector.newConfiguration().setCollectorToReset(selfPresenceCollector).setStanzaFilter(presenceFromRoomFilter);
// This stanza collector is used to reset the timeout of the selfPresenceCollector.
presenceStanzaCollector = connection.createStanzaCollector(presenceStanzaCollectorConfguration);
reflectedSelfPresence = selfPresenceCollector.nextResultOrThrow(conf.getTimeout());
} catch (NotConnectedException | InterruptedException | NoResponseException | XMPPErrorException e) {
// Ensure that all callbacks are removed if there is an exception
removeConnectionCallbacks();
throw e;
} finally {
if (presenceStanzaCollector != null) {
presenceStanzaCollector.cancel();
}
}
synchronized (presenceListener) {
// processing is done.
while (!processedReflectedSelfPresence) {
presenceListener.wait();
}
}
// This presence must be send from a full JID. We use the resourcepart of this JID as nick, since the room may
// performed roomnick rewriting
Resourcepart receivedNickname = reflectedSelfPresence.getFrom().getResourceOrThrow();
setNickname(receivedNickname);
// Update the list of joined rooms
multiUserChatManager.addJoinedRoom(room);
return reflectedSelfPresence;
}
use of org.jivesoftware.smack.filter.StanzaIdFilter in project Spark by igniterealtime.
the class Gateway method getJID.
/**
* Returns the fully qualified JID of a user.
*
* @param serviceName the service the user belongs to.
* @param username the name of the user.
* @return the JID.
*/
public static String getJID(String serviceName, String username) throws SmackException.NotConnectedException {
Gateway registration = new Gateway();
registration.setType(IQ.Type.set);
registration.setTo(serviceName);
registration.setUsername(username);
XMPPConnection con = SparkManager.getConnection();
PacketCollector collector = con.createPacketCollector(new StanzaIdFilter(registration.getStanzaId()));
try {
con.sendStanza(registration);
Gateway response = collector.nextResult(SmackConfiguration.getDefaultPacketReplyTimeout());
return response.getJid();
} finally {
collector.cancel();
}
}
use of org.jivesoftware.smack.filter.StanzaIdFilter in project Spark by igniterealtime.
the class ReversiPlugin method addToolbarButton.
/**
* Adds the Reversi toolbar button.
*/
private void addToolbarButton() {
ChatManager manager = SparkManager.getChatManager();
chatRoomListener = new ChatRoomListenerAdapter() {
ImageIcon icon = ReversiRes.getImageIcon(ReversiRes.REVERSI_ICON);
public void chatRoomOpened(final ChatRoom room) {
if (!(room instanceof ChatRoomImpl)) {
// Don't do anything if this is not a 1on1-Chat
return;
}
ChatRoomButton button = new ChatRoomButton(icon);
button.setToolTipText("Reversi");
room.getToolBar().addChatRoomButton(button);
// Add a button listener that sends out a game invite on a user
// click.
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
// Show "requesting a game panel"
final JPanel request = new JPanel();
request.setLayout(new BorderLayout());
JPanel requestPanel = new JPanel() {
private static final long serialVersionUID = 4490592207923738251L;
protected void paintComponent(Graphics g) {
g.drawImage(icon.getImage(), 0, 0, null);
}
};
requestPanel.setPreferredSize(new Dimension(24, 24));
request.add(requestPanel, BorderLayout.WEST);
String opponentJID = ((ChatRoomImpl) room).getJID();
// TODO:
String opponentName = "[" + opponentJID + "]";
// convert
// to
// more
// readable
// name.
final JPanel content = new JPanel(new BorderLayout());
final JLabel label = new JLabel("Requesting a Reversi game with " + opponentName + ", please wait...");
content.add(label, BorderLayout.CENTER);
JPanel buttonPanel = new JPanel();
final JButton cancelButton = new JButton("Cancel");
cancelButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
GameOffer reply = new GameOffer();
reply.setTo(((ChatRoomImpl) room).getJID());
reply.setType(IQ.Type.error);
try {
SparkManager.getConnection().sendStanza(reply);
} catch (SmackException.NotConnectedException e1) {
Log.warning("Unable to send invitation cancellation to " + reply.getTo(), e1);
}
cancelButton.setText("Canceled");
cancelButton.setEnabled(false);
}
});
buttonPanel.add(cancelButton, BorderLayout.SOUTH);
content.add(buttonPanel, BorderLayout.SOUTH);
request.add(content, BorderLayout.CENTER);
room.getTranscriptWindow().addComponent(request);
final GameOffer offer = new GameOffer();
offer.setTo(opponentJID);
// Add a listener for a reply to our offer.
SparkManager.getConnection().addAsyncStanzaListener(new StanzaListener() {
public void processPacket(Stanza stanza) {
GameOffer offerReply = ((GameOffer) stanza);
if (offerReply.getType() == IQ.Type.result) {
// Remove the offer panel
room.getTranscriptWindow().remove(request);
content.remove(1);
label.setText("Starting game...");
// Show game board (using original offer!).
showReversiBoard(offer.getGameID(), room, offer.isStartingPlayer(), offerReply.getFrom());
} else if (offerReply.getType() == IQ.Type.error) {
cancelButton.setVisible(false);
JPanel userDeclinedPanel = new JPanel(new BorderLayout());
JLabel userDeclined = new JLabel("User declined...");
userDeclinedPanel.add(userDeclined, BorderLayout.SOUTH);
request.add(userDeclinedPanel, BorderLayout.SOUTH);
}
// TODO: Handle error case
}
}, new StanzaIdFilter(offer.getStanzaId()));
try {
SparkManager.getConnection().sendStanza(offer);
} catch (SmackException.NotConnectedException e1) {
Log.warning("Unable to send invitation to " + offer.getTo(), e1);
}
}
});
}
public void chatRoomClosed(ChatRoom room) {
super.chatRoomClosed(room);
// TODO: if game is in progress, close it down. What we need is
// an API that lets us see
// TODO: if there's a transcript alert currently there.
}
};
manager.addChatRoomListener(chatRoomListener);
}
use of org.jivesoftware.smack.filter.StanzaIdFilter in project Smack by igniterealtime.
the class MultiUserChat method leave.
/**
* Leave the chat room.
*
* @return the leave presence as reflected by the MUC.
* @throws NotConnectedException if the XMPP connection is not connected.
* @throws InterruptedException if the calling thread was interrupted.
* @throws XMPPErrorException if there was an XMPP error returned.
* @throws NoResponseException if there was no response from the remote entity.
* @throws MucNotJoinedException if not joined to the Multi-User Chat.
*/
public synchronized Presence leave() throws NotConnectedException, InterruptedException, NoResponseException, XMPPErrorException, MucNotJoinedException {
// Note that this method is intentionally not guarded by
// "if (!joined) return" because it should be always be possible to leave the room in case the instance's
// state does not reflect the actual state.
final EntityFullJid myRoomJid = getMyRoomJid();
if (myRoomJid == null) {
throw new MucNotJoinedException(this);
}
// TODO: Consider adding a origin-id to the presence, once it is moved form smack-experimental into
// smack-extensions, in case the MUC service does not support stable IDs, and modify
// reflectedLeavePresenceFilters accordingly.
// We leave a room by sending a presence packet where the "to"
// field is in the form "roomName@service/nickname"
Presence leavePresence = connection.getStanzaFactory().buildPresenceStanza().ofType(Presence.Type.unavailable).to(myRoomJid).build();
List<StanzaFilter> reflectedLeavePresenceFilters = new ArrayList<>(3);
reflectedLeavePresenceFilters.add(StanzaTypeFilter.PRESENCE);
reflectedLeavePresenceFilters.add(new OrFilter(new AndFilter(FromMatchesFilter.createFull(myRoomJid), PresenceTypeFilter.UNAVAILABLE, MUCUserStatusCodeFilter.STATUS_110_PRESENCE_TO_SELF), new AndFilter(fromRoomFilter, PresenceTypeFilter.ERROR)));
if (serviceSupportsStableIds()) {
reflectedLeavePresenceFilters.add(new StanzaIdFilter(leavePresence));
}
StanzaFilter reflectedLeavePresenceFilter = new AndFilter(reflectedLeavePresenceFilters);
Presence reflectedLeavePresence;
try {
reflectedLeavePresence = connection.createStanzaCollectorAndSend(reflectedLeavePresenceFilter, leavePresence).nextResultOrThrow();
} finally {
// Reset occupant information after we send the leave presence. This ensures that we only call userHasLeft()
// and reset the local MUC state after we successfully left the MUC (or if an exception occurred).
userHasLeft();
}
return reflectedLeavePresence;
}
Aggregations