/** * Selects an appropriate stream negotiator after examining the incoming file transfer request. * * @param request The related file transfer request. * @return The file transfer object that handles the transfer * @throws XMPPException If there are either no stream methods contained in the packet, or there * is not an appropriate stream method. */ public StreamNegotiator selectStreamNegotiator(FileTransferRequest request) throws XMPPException { final StreamInitiation si = request.getStreamInitiation(); final FormField streamMethodField = getStreamMethodField(si.getFeatureNegotiationForm()); if (streamMethodField == null) { final String errorMessage = "No stream methods contained in packet."; final XMPPError error = new XMPPError(XMPPError.Condition.bad_request, errorMessage); final IQ iqPacket = createIQ(si.getPacketID(), si.getFrom(), si.getTo(), IQ.Type.ERROR); iqPacket.setError(error); connection.sendPacket(iqPacket); throw new XMPPException(errorMessage, error); } // select the appropriate protocol StreamNegotiator selectedStreamNegotiator; try { selectedStreamNegotiator = getNegotiator(streamMethodField); } catch (final XMPPException e) { final IQ iqPacket = createIQ(si.getPacketID(), si.getFrom(), si.getTo(), IQ.Type.ERROR); iqPacket.setError(e.getXMPPError()); connection.sendPacket(iqPacket); throw e; } // return the appropriate negotiator return selectedStreamNegotiator; }
/** * Returns the discovered items of a given XMPP entity addressed by its JID and note attribute. * Use this message only when trying to query information which is not directly addressable. * * @param entityID the address of the XMPP entity. * @param node the attribute that supplements the 'jid' attribute. * @return the discovered items. * @throws XMPPException if the operation failed for some reason. */ public DiscoverItems discoverItems(String entityID, String node) throws XMPPException { // Discover the entity's items DiscoverItems disco = new DiscoverItems(); disco.setType(IQ.Type.GET); disco.setTo(entityID); disco.setNode(node); // Create a packet collector to listen for a response. PacketCollector collector = connection.createPacketCollector(new PacketIDFilter(disco.getPacketID())); connection.sendPacket(disco); // Wait up to 5 seconds for a result. IQ result = (IQ) collector.nextResult(SmackConfiguration.getPacketReplyTimeout()); // Stop queuing results collector.cancel(); if (result == null) { throw new XMPPException("No response from the server."); } if (result.getType() == IQ.Type.ERROR) { throw new XMPPException(result.getError()); } return (DiscoverItems) result; }
/** * Sends a reply to a previously received packet that was sent to multiple recipients. Before * attempting to send the reply message some checkings are performed. If any of those checkings * fail then an XMPPException is going to be thrown with the specific error detail. * * @param connection the connection to use to send the reply. * @param original the previously received packet that was sent to multiple recipients. * @param reply the new message to send as a reply. * @throws XMPPException if the original message was not sent to multiple recipients, or the * original message cannot be replied or reply should be sent to a room. */ public static void reply(Connection connection, Message original, Message reply) throws XMPPException { MultipleRecipientInfo info = getMultipleRecipientInfo(original); if (info == null) { throw new XMPPException("Original message does not contain multiple recipient info"); } if (info.shouldNotReply()) { throw new XMPPException("Original message should not be replied"); } if (info.getReplyRoom() != null) { throw new XMPPException("Reply should be sent through a room"); } // Any <thread/> element from the initial message MUST be copied into the reply. if (original.getThread() != null) { reply.setThread(original.getThread()); } MultipleAddresses.Address replyAddress = info.getReplyAddress(); if (replyAddress != null && replyAddress.getJid() != null) { // Send reply to the reply_to address reply.setTo(replyAddress.getJid()); connection.sendPacket(reply); } else { // Send reply to multiple recipients List<String> to = new ArrayList<String>(); List<String> cc = new ArrayList<String>(); for (Iterator<MultipleAddresses.Address> it = info.getTOAddresses().iterator(); it.hasNext(); ) { String jid = it.next().getJid(); to.add(jid); } for (Iterator<MultipleAddresses.Address> it = info.getCCAddresses().iterator(); it.hasNext(); ) { String jid = it.next().getJid(); cc.add(jid); } // Add original sender as a 'to' address (if not already present) if (!to.contains(original.getFrom()) && !cc.contains(original.getFrom())) { to.add(original.getFrom()); } // Remove the sender from the TO/CC list (try with bare JID too) String from = connection.getUser(); if (!to.remove(from) && !cc.remove(from)) { String bareJID = StringUtils.parseBareAddress(from); to.remove(bareJID); cc.remove(bareJID); } String serviceAddress = getMultipleRecipienServiceAddress(connection); if (serviceAddress != null) { // Send packet to target users using multiple recipient service provided by the server sendThroughService(connection, reply, to, cc, null, null, null, false, serviceAddress); } else { // Server does not support JEP-33 so try to send the packet to each recipient sendToIndividualRecipients(connection, reply, to, cc, null); } } }
protected void rejectIncomingFileTransfer(FileTransferRequest request) { StreamInitiation initiation = request.getStreamInitiation(); IQ rejection = FileTransferNegotiator.createIQ( initiation.getPacketID(), initiation.getFrom(), initiation.getTo(), IQ.Type.ERROR); rejection.setError(new XMPPError(XMPPError.Condition.no_acceptable)); connection.sendPacket(rejection); }
public InputStream createIncomingStream(StreamInitiation initiation) throws XMPPException { PacketCollector collector = connection.createPacketCollector( getInitiationPacketFilter(initiation.getFrom(), initiation.getSessionID())); connection.sendPacket(super.createInitiationAccept(initiation, getNamespaces())); ExecutorService threadPoolExecutor = Executors.newFixedThreadPool(2); CompletionService<InputStream> service = new ExecutorCompletionService<InputStream>(threadPoolExecutor); List<Future<InputStream>> futures = new ArrayList<Future<InputStream>>(); InputStream stream = null; XMPPException exception = null; try { futures.add(service.submit(new NegotiatorService(collector))); futures.add(service.submit(new NegotiatorService(collector))); int i = 0; while (stream == null && i < futures.size()) { Future<InputStream> future; try { i++; future = service.poll(10, TimeUnit.SECONDS); } catch (InterruptedException e) { continue; } if (future == null) { continue; } try { stream = future.get(); } catch (InterruptedException e) { /* Do Nothing */ } catch (ExecutionException e) { exception = new XMPPException(e.getCause()); } } } finally { for (Future<InputStream> future : futures) { future.cancel(true); } collector.cancel(); threadPoolExecutor.shutdownNow(); } if (stream == null) { if (exception != null) { throw exception; } else { throw new XMPPException("File transfer negotiation failed."); } } return stream; }
/** * Sends a roster to userID. All the entries of the roster will be sent to the target user. * * @param roster the roster to send * @param targetUserID the user that will receive the roster entries */ public void send(Roster roster, String targetUserID) { // Create a new message to send the roster Message msg = new Message(targetUserID); // Create a RosterExchange Package and add it to the message RosterExchange rosterExchange = new RosterExchange(roster); msg.addExtension(rosterExchange); // Send the message that contains the roster con.sendPacket(msg); }
/** * Sets the name associated with this entry. * * @param name the name. */ public void setName(String name) { // Do nothing if the name hasn't changed. if (name != null && name.equals(this.name)) { return; } this.name = name; RosterPacket packet = new RosterPacket(); packet.setType(IQ.Type.SET); packet.addRosterItem(toRosterItem(this)); connection.sendPacket(packet); }
/** * Returns true if the workgroup is available for receiving new requests. The workgroup will be * available only when agents are available for this workgroup. * * @return true if the workgroup is available for receiving new requests. * @throws XMPPException */ public boolean isAvailable() throws XMPPException { Presence directedPresence = new Presence(Presence.Type.available); directedPresence.setTo(workgroupJID); PacketFilter typeFilter = new PacketTypeFilter(Presence.class); PacketFilter fromFilter = FromMatchesFilter.create(workgroupJID); PacketCollector collector = connection.createPacketCollector(new AndFilter(fromFilter, typeFilter)); connection.sendPacket(directedPresence); Presence response = (Presence) collector.nextResultOrThrow(); return Presence.Type.available == response.getType(); }
/** * Sends a roster group to userID. All the entries of the group will be sent to the target user. * * @param rosterGroup the roster group to send * @param targetUserID the user that will receive the roster entries */ public void send(RosterGroup rosterGroup, String targetUserID) { // Create a new message to send the roster Message msg = new Message(targetUserID); // Create a RosterExchange Package and add it to the message RosterExchange rosterExchange = new RosterExchange(); for (RosterEntry entry : rosterGroup.getEntries()) { rosterExchange.addRosterEntry(entry); } msg.addExtension(rosterExchange); // Send the message that contains the roster con.sendPacket(msg); }
private static void sendToIndividualRecipients( Connection connection, Packet packet, List<String> to, List<String> cc, List<String> bcc) { if (to != null) { for (Iterator<String> it = to.iterator(); it.hasNext(); ) { String jid = it.next(); packet.setTo(jid); connection.sendPacket(new PacketCopy(packet.toXML())); } } if (cc != null) { for (Iterator<String> it = cc.iterator(); it.hasNext(); ) { String jid = it.next(); packet.setTo(jid); connection.sendPacket(new PacketCopy(packet.toXML())); } } if (bcc != null) { for (Iterator<String> it = bcc.iterator(); it.hasNext(); ) { String jid = it.next(); packet.setTo(jid); connection.sendPacket(new PacketCopy(packet.toXML())); } } }
private static void sendThroughService( Connection connection, Packet packet, List<String> to, List<String> cc, List<String> bcc, String replyTo, String replyRoom, boolean noReply, String serviceAddress) { // Create multiple recipient extension MultipleAddresses multipleAddresses = new MultipleAddresses(); if (to != null) { for (Iterator<String> it = to.iterator(); it.hasNext(); ) { String jid = it.next(); multipleAddresses.addAddress(MultipleAddresses.TO, jid, null, null, false, null); } } if (cc != null) { for (Iterator<String> it = cc.iterator(); it.hasNext(); ) { String jid = it.next(); multipleAddresses.addAddress(MultipleAddresses.CC, jid, null, null, false, null); } } if (bcc != null) { for (Iterator<String> it = bcc.iterator(); it.hasNext(); ) { String jid = it.next(); multipleAddresses.addAddress(MultipleAddresses.BCC, jid, null, null, false, null); } } if (noReply) { multipleAddresses.setNoReply(); } else { if (replyTo != null && replyTo.trim().length() > 0) { multipleAddresses.addAddress(MultipleAddresses.REPLY_TO, replyTo, null, null, false, null); } if (replyRoom != null && replyRoom.trim().length() > 0) { multipleAddresses.addAddress( MultipleAddresses.REPLY_ROOM, replyRoom, null, null, false, null); } } // Set the multiple recipient service address as the target address packet.setTo(serviceAddress); // Add extension to packet packet.addExtension(multipleAddresses); // Send the packet connection.sendPacket(packet); }
/** * Notify server to change the carbons state. This method returns immediately and changes the * variable when the reply arrives. * * <p>You should first check for support using isSupportedByServer(). * * @param new_state whether carbons should be enabled or disabled */ public void sendCarbonsEnabled(final boolean new_state) { final Connection connection = weakRefConnection.get(); IQ setIQ = carbonsEnabledIQ(new_state); connection.addPacketListener( new PacketListener() { public void processPacket(Packet packet) { IQ result = (IQ) packet; if (result.getType() == IQ.Type.RESULT) { enabled_state = new_state; } connection.removePacketListener(this); } }, new IQReplyFilter(setIQ, connection)); connection.sendPacket(setIQ); }
/** * Gets the account registration info from the server. * * @throws XMPPException if an error occurs. */ private synchronized void getRegistrationInfo() throws XMPPException { Registration reg = new Registration(); reg.setTo(connection.getServiceName()); PacketFilter filter = new AndFilter(new PacketIDFilter(reg.getPacketID()), new PacketTypeFilter(IQ.class)); PacketCollector collector = connection.createPacketCollector(filter); connection.sendPacket(reg); IQ result = (IQ) collector.nextResult(SmackConfiguration.getPacketReplyTimeout()); // Stop queuing results collector.cancel(); if (result == null) { throw new XMPPException("No response from server."); } else if (result.getType() == IQ.Type.ERROR) { throw new XMPPException(result.getError()); } else { info = (Registration) result; } }
/** * Send a request to another user to send them a file. The other user has the option of, * accepting, rejecting, or not responding to a received file transfer request. * * <p>If they accept, the packet will contain the other user's chosen stream type to send the file * across. The two choices this implementation provides to the other user for file transfer are <a * href="http://www.jabber.org/jeps/jep-0065.html">SOCKS5 Bytestreams</a>, which is the preferred * method of transfer, and <a href="http://www.jabber.org/jeps/jep-0047.html">In-Band * Bytestreams</a>, which is the fallback mechanism. * * <p>The other user may choose to decline the file request if they do not desire the file, their * client does not support JEP-0096, or if there are no acceptable means to transfer the file. * * <p>Finally, if the other user does not respond this method will return null after the specified * timeout. * * @param userID The userID of the user to whom the file will be sent. * @param streamID The unique identifier for this file transfer. * @param fileName The name of this file. Preferably it should include an extension as it is used * to determine what type of file it is. * @param size The size, in bytes, of the file. * @param desc A description of the file. * @param responseTimeout The amount of time, in milliseconds, to wait for the remote user to * respond. If they do not respond in time, this * @return Returns the stream negotiator selected by the peer. * @throws XMPPException Thrown if there is an error negotiating the file transfer. */ public StreamNegotiator negotiateOutgoingTransfer( final String userID, final String streamID, final String fileName, final long size, final String desc, int responseTimeout) throws XMPPException { final StreamInitiation si = new StreamInitiation(); si.setSesssionID(streamID); si.setMimeType(URLConnection.guessContentTypeFromName(fileName)); final StreamInitiation.File siFile = new StreamInitiation.File(fileName, size); siFile.setDesc(desc); si.setFile(siFile); si.setFeatureNegotiationForm(createDefaultInitiationForm()); si.setFrom(connection.getUser()); si.setTo(userID); si.setType(IQ.Type.SET); final PacketCollector collector = connection.createPacketCollector(new PacketIDFilter(si.getPacketID())); connection.sendPacket(si); final Packet siResponse = collector.nextResult(responseTimeout); collector.cancel(); if (siResponse instanceof IQ) { final IQ iqResponse = (IQ) siResponse; if (iqResponse.getType().equals(IQ.Type.RESULT)) { final StreamInitiation response = (StreamInitiation) siResponse; return getOutgoingNegotiator(getStreamMethodField(response.getFeatureNegotiationForm())); } else if (iqResponse.getType().equals(IQ.Type.ERROR)) { throw new XMPPException(iqResponse.getError()); } else { throw new XMPPException("File transfer response unreadable"); } } else { return null; } }
/** * Changes the password of the currently logged-in account. This operation can only be performed * after a successful login operation has been completed. Not all servers support changing * passwords; an XMPPException will be thrown when that is the case. * * @throws IllegalStateException if not currently logged-in to the server. * @throws XMPPException if an error occurs when changing the password. */ public void changePassword(String newPassword) throws XMPPException { Registration reg = new Registration(); reg.setType(IQ.Type.SET); reg.setTo(connection.getServiceName()); Map<String, String> map = new HashMap<String, String>(); map.put("username", StringUtils.parseName(connection.getUser())); map.put("password", newPassword); reg.setAttributes(map); PacketFilter filter = new AndFilter(new PacketIDFilter(reg.getPacketID()), new PacketTypeFilter(IQ.class)); PacketCollector collector = connection.createPacketCollector(filter); connection.sendPacket(reg); IQ result = (IQ) collector.nextResult(SmackConfiguration.getPacketReplyTimeout()); // Stop queuing results collector.cancel(); if (result == null) { throw new XMPPException("No response from server."); } else if (result.getType() == IQ.Type.ERROR) { throw new XMPPException(result.getError()); } }
/** * Returns the transcripts of a given user. The answer will contain the complete history of * conversations that a user had. * * @param userID the id of the user to get his conversations. * @param workgroupJID the JID of the workgroup that will process the request. * @return the transcripts of a given user. * @throws XMPPException if an error occurs while getting the information. */ public Transcripts getTranscripts(String workgroupJID, String userID) throws XMPPException { Transcripts request = new Transcripts(userID); request.setTo(workgroupJID); PacketCollector collector = connection.createPacketCollector(new PacketIDFilter(request.getPacketID())); // Send the request connection.sendPacket(request); Transcripts response = (Transcripts) collector.nextResult(SmackConfiguration.getPacketReplyTimeout()); // Cancel the collector. collector.cancel(); if (response == null) { throw new XMPPException("No response from server on status set."); } if (response.getError() != null) { throw new XMPPException(response.getError()); } return response; }
/** * Creates a new account using the specified username, password and account attributes. The * attributes Map must contain only String name/value pairs and must also have values for all * required attributes. * * @param username the username. * @param password the password. * @param attributes the account attributes. * @throws XMPPException if an error occurs creating the account. * @see #getAccountAttributes() */ public void createAccount(String username, String password, Map<String, String> attributes) throws XMPPException { if (!supportsAccountCreation()) { throw new XMPPException("Server does not support account creation."); } Registration reg = new Registration(); reg.setType(IQ.Type.SET); reg.setTo(connection.getServiceName()); attributes.put("username", username); attributes.put("password", password); reg.setAttributes(attributes); PacketFilter filter = new AndFilter(new PacketIDFilter(reg.getPacketID()), new PacketTypeFilter(IQ.class)); PacketCollector collector = connection.createPacketCollector(filter); connection.sendPacket(reg); IQ result = (IQ) collector.nextResult(SmackConfiguration.getPacketReplyTimeout()); // Stop queuing results collector.cancel(); if (result == null) { throw new XMPPException("No response from server."); } else if (result.getType() == IQ.Type.ERROR) { throw new XMPPException(result.getError()); } }
/** * Deletes the currently logged-in account from the server. This operation can only be performed * after a successful login operation has been completed. Not all servers support deleting * accounts; an XMPPException will be thrown when that is the case. * * @throws IllegalStateException if not currently logged-in to the server. * @throws XMPPException if an error occurs when deleting the account. */ public void deleteAccount() throws XMPPException { if (!connection.isAuthenticated()) { throw new IllegalStateException("Must be logged in to delete a account."); } Registration reg = new Registration(); reg.setType(IQ.Type.SET); reg.setTo(connection.getServiceName()); Map<String, String> attributes = new HashMap<String, String>(); // To delete an account, we add a single attribute, "remove", that is blank. attributes.put("remove", ""); reg.setAttributes(attributes); PacketFilter filter = new AndFilter(new PacketIDFilter(reg.getPacketID()), new PacketTypeFilter(IQ.class)); PacketCollector collector = connection.createPacketCollector(filter); connection.sendPacket(reg); IQ result = (IQ) collector.nextResult(SmackConfiguration.getPacketReplyTimeout()); // Stop queuing results collector.cancel(); if (result == null) { throw new XMPPException("No response from server."); } else if (result.getType() == IQ.Type.ERROR) { throw new XMPPException(result.getError()); } }
public void send(String destination, String text) { Message response = new Message(destination, Message.Type.chat); response.setBody("*" + text); connection.sendPacket(response); }
/** * Process the AdHoc-Command packet that request the execution of some action of a command. If * this is the first request, this method checks, before executing the command, if: * * <ul> * <li>The requested command exists * <li>The requester has permissions to execute it * <li>The command has more than one stage, if so, it saves the command and session ID for * further use * </ul> * * <br> * <br> * If this is not the first request, this method checks, before executing the command, if: * * <ul> * <li>The session ID of the request was stored * <li>The session life do not exceed the time out * <li>The action to execute is one of the available actions * </ul> * * @param requestData the packet to process. */ private void processAdHocCommand(AdHocCommandData requestData) { // Only process requests of type SET if (requestData.getType() != IQ.Type.SET) { return; } // Creates the response with the corresponding data AdHocCommandData response = new AdHocCommandData(); response.setTo(requestData.getFrom()); response.setPacketID(requestData.getPacketID()); response.setNode(requestData.getNode()); response.setId(requestData.getTo()); String sessionId = requestData.getSessionID(); String commandNode = requestData.getNode(); if (sessionId == null) { // A new execution request has been received. Check that the // command exists if (!commands.containsKey(commandNode)) { // Requested command does not exist so return // item_not_found error. respondError(response, XMPPError.Condition.item_not_found); return; } // Create new session ID sessionId = StringUtils.randomString(15); try { // Create a new instance of the command with the // corresponding sessioid LocalCommand command = newInstanceOfCmd(commandNode, sessionId); response.setType(IQ.Type.RESULT); command.setData(response); // Check that the requester has enough permission. // Answer forbidden error if requester permissions are not // enough to execute the requested command if (!command.hasPermission(requestData.getFrom())) { respondError(response, XMPPError.Condition.forbidden); return; } Action action = requestData.getAction(); // If the action is unknown then respond an error. if (action != null && action.equals(Action.unknown)) { respondError( response, XMPPError.Condition.bad_request, AdHocCommand.SpecificErrorCondition.malformedAction); return; } // If the action is not execute, then it is an invalid action. if (action != null && !action.equals(Action.execute)) { respondError( response, XMPPError.Condition.bad_request, AdHocCommand.SpecificErrorCondition.badAction); return; } // Increase the state number, so the command knows in witch // stage it is command.incrementStage(); // Executes the command command.execute(); if (command.isLastStage()) { // If there is only one stage then the command is completed response.setStatus(Status.completed); } else { // Else it is still executing, and is registered to be // available for the next call response.setStatus(Status.executing); executingCommands.put(sessionId, command); // See if the session reaping thread is started. If not, start it. if (!sessionsSweeper.isAlive()) { sessionsSweeper.start(); } } // Sends the response packet connection.sendPacket(response); } catch (XMPPException e) { // If there is an exception caused by the next, complete, // prev or cancel method, then that error is returned to the // requester. XMPPError error = e.getXMPPError(); // If the error type is cancel, then the execution is // canceled therefore the status must show that, and the // command be removed from the executing list. if (XMPPError.Type.CANCEL.equals(error.getType())) { response.setStatus(Status.canceled); executingCommands.remove(sessionId); } respondError(response, error); e.printStackTrace(); } } else { LocalCommand command = executingCommands.get(sessionId); // Check that a command exists for the specified sessionID // This also handles if the command was removed in the meanwhile // of getting the key and the value of the map. if (command == null) { respondError( response, XMPPError.Condition.bad_request, AdHocCommand.SpecificErrorCondition.badSessionid); return; } // Check if the Session data has expired (default is 10 minutes) long creationStamp = command.getCreationDate(); if (System.currentTimeMillis() - creationStamp > SESSION_TIMEOUT * 1000) { // Remove the expired session executingCommands.remove(sessionId); // Answer a not_allowed error (session-expired) respondError( response, XMPPError.Condition.not_allowed, AdHocCommand.SpecificErrorCondition.sessionExpired); return; } /* * Since the requester could send two requests for the same * executing command i.e. the same session id, all the execution of * the action must be synchronized to avoid inconsistencies. */ synchronized (command) { Action action = requestData.getAction(); // If the action is unknown the respond an error if (action != null && action.equals(Action.unknown)) { respondError( response, XMPPError.Condition.bad_request, AdHocCommand.SpecificErrorCondition.malformedAction); return; } // If the user didn't specify an action or specify the execute // action then follow the actual default execute action if (action == null || Action.execute.equals(action)) { action = command.getExecuteAction(); } // Check that the specified action was previously // offered if (!command.isValidAction(action)) { respondError( response, XMPPError.Condition.bad_request, AdHocCommand.SpecificErrorCondition.badAction); return; } try { // TODO: Check that all the requierd fields of the form are // TODO: filled, if not throw an exception. This will simplify the // TODO: construction of new commands // Since all errors were passed, the response is now a // result response.setType(IQ.Type.RESULT); // Set the new data to the command. command.setData(response); if (Action.next.equals(action)) { command.incrementStage(); command.next(new Form(requestData.getForm())); if (command.isLastStage()) { // If it is the last stage then the command is // completed response.setStatus(Status.completed); } else { // Otherwise it is still executing response.setStatus(Status.executing); } } else if (Action.complete.equals(action)) { command.incrementStage(); command.complete(new Form(requestData.getForm())); response.setStatus(Status.completed); // Remove the completed session executingCommands.remove(sessionId); } else if (Action.prev.equals(action)) { command.decrementStage(); command.prev(); } else if (Action.cancel.equals(action)) { command.cancel(); response.setStatus(Status.canceled); // Remove the canceled session executingCommands.remove(sessionId); } connection.sendPacket(response); } catch (XMPPException e) { // If there is an exception caused by the next, complete, // prev or cancel method, then that error is returned to the // requester. XMPPError error = e.getXMPPError(); // If the error type is cancel, then the execution is // canceled therefore the status must show that, and the // command be removed from the executing list. if (XMPPError.Type.CANCEL.equals(error.getType())) { response.setStatus(Status.canceled); executingCommands.remove(sessionId); } respondError(response, error); e.printStackTrace(); } } } }
/** * Reject a stream initiation request from a remote user. * * @param si The Stream Initiation request to reject. */ public void rejectStream(final StreamInitiation si) { final XMPPError error = new XMPPError(XMPPError.Condition.forbidden, "Offer Declined"); final IQ iqPacket = createIQ(si.getPacketID(), si.getFrom(), si.getTo(), IQ.Type.ERROR); iqPacket.setError(error); connection.sendPacket(iqPacket); }
/** * Responds an error with an specific error. * * @param response the response to send. * @param error the error to send. */ private void respondError(AdHocCommandData response, XMPPError error) { response.setType(IQ.Type.ERROR); response.setError(error); connection.sendPacket(response); }
/** * Parses an IQ packet. * * @param parser the XML parser, positioned at the start of an IQ packet. * @return an IQ object. * @throws Exception if an exception occurs while parsing the packet. */ public static IQ parseIQ(XmlPullParser parser, Connection connection) throws Exception { IQ iqPacket = null; String id = parser.getAttributeValue("", "id"); String to = parser.getAttributeValue("", "to"); String from = parser.getAttributeValue("", "from"); IQ.Type type = IQ.Type.fromString(parser.getAttributeValue("", "type")); XMPPError error = null; boolean done = false; while (!done) { int eventType = parser.next(); if (eventType == XmlPullParser.START_TAG) { String elementName = parser.getName(); String namespace = parser.getNamespace(); if (elementName.equals("error")) { error = PacketParserUtils.parseError(parser); } else if (elementName.equals("query") && namespace.equals("jabber:iq:auth")) { iqPacket = parseAuthentication(parser); } else if (elementName.equals("query") && namespace.equals("jabber:iq:roster")) { iqPacket = parseRoster(parser); } else if (elementName.equals("query") && namespace.equals("jabber:iq:register")) { iqPacket = parseRegistration(parser); } else if (elementName.equals("bind") && namespace.equals("urn:ietf:params:xml:ns:xmpp-bind")) { iqPacket = parseResourceBinding(parser); } // Otherwise, see if there is a registered provider for // this element name and namespace. else { Object provider = ProviderManager.getInstance().getIQProvider(elementName, namespace); if (provider != null) { if (provider instanceof IQProvider) { iqPacket = ((IQProvider) provider).parseIQ(parser); } else if (provider instanceof Class) { iqPacket = (IQ) PacketParserUtils.parseWithIntrospection( elementName, (Class<?>) provider, parser); } } // Only handle unknown IQs of type result. Types of 'get' and 'set' which are not // understood // have to be answered with an IQ error response. See the code a few lines below else if (IQ.Type.RESULT == type) { // No Provider found for the IQ stanza, parse it to an UnparsedIQ instance // so that the content of the IQ can be examined later on iqPacket = new UnparsedResultIQ(parseContent(parser)); } } } else if (eventType == XmlPullParser.END_TAG) { if (parser.getName().equals("iq")) { done = true; } } } // Decide what to do when an IQ packet was not understood if (iqPacket == null) { if (IQ.Type.GET == type || IQ.Type.SET == type) { // If the IQ stanza is of type "get" or "set" containing a child element // qualified by a namespace it does not understand, then answer an IQ of // type "error" with code 501 ("feature-not-implemented") iqPacket = new IQ() { @Override public String getChildElementXML() { return null; } }; iqPacket.setPacketID(id); iqPacket.setTo(from); iqPacket.setFrom(to); iqPacket.setType(IQ.Type.ERROR); iqPacket.setError(new XMPPError(XMPPError.Condition.feature_not_implemented)); connection.sendPacket(iqPacket); return null; } else { // If an IQ packet wasn't created above, create an empty IQ packet. iqPacket = new IQ() { @Override public String getChildElementXML() { return null; } }; } } // Set basic values on the iq packet. iqPacket.setPacketID(id); iqPacket.setTo(to); iqPacket.setFrom(from); iqPacket.setType(type); iqPacket.setError(error); return iqPacket; }
/** * Responses to the given IQ packet's sender with an XMPP error that an In-Band Bytestream open * request is rejected because its block size is greater than the maximum allowed block size. * * @param request IQ packet that should be answered with a resource-constraint error */ protected void replyResourceConstraintPacket(IQ request) { final XMPPError xmppError = new XMPPError(XMPPError.Condition.resource_constraint); final IQ error = IQ.createErrorResponse(request, xmppError); connection.sendPacket(error); }
/** * Responses to the given IQ packet's sender with an XMPP error that an In-Band Bytestream is not * accepted. * * @param request IQ packet that should be answered with a not-acceptable error */ protected void replyRejectPacket(IQ request) { final XMPPError xmppError = new XMPPError(XMPPError.Condition.no_acceptable); final IQ error = IQ.createErrorResponse(request, xmppError); connection.sendPacket(error); }
/** * Responses to the given IQ packet's sender with an XMPP error that an In-Band Bytestream session * could not be found. * * @param request IQ packet that should be answered with a item-not-found error */ protected void replyItemNotFoundPacket(IQ request) { final XMPPError xmppError = new XMPPError(XMPPError.Condition.item_not_found); final IQ error = IQ.createErrorResponse(request, xmppError); connection.sendPacket(error); }