@Test public void testPagingAfterItemWithInvalidAfterId() throws Exception { Element rsm = new BaseElement(new QName("set", new Namespace("", "http://jabber.org/protocol/rsm"))); rsm.addElement("after").setText("this is invalid"); element.addAttribute("node", "/user/[email protected]/posts"); Mockito.when(channelManager.nodeExists(anyString())).thenReturn(true); Mockito.when(channelManager.getNodeMembership(node, jid)) .thenReturn( new NodeMembershipImpl(node, jid, Subscriptions.subscribed, Affiliations.member, null)); Mockito.when( channelManager.getUserFeedItems( Mockito.any(JID.class), Mockito.any(Date.class), Mockito.anyInt(), Mockito.any(GlobalItemID.class), Mockito.eq(false))) .thenReturn(new ClosableIteratorImpl<NodeItem>(new ArrayList<NodeItem>().iterator())); Mockito.when( channelManager.getCountUserFeedItems( Mockito.any(JID.class), Mockito.any(Date.class), Mockito.eq(false))) .thenReturn(0); userItemsGet.process(element, jid, request, rsm); Packet p = queue.poll(100, TimeUnit.MILLISECONDS); assertEquals("Error expected", "error", p.getElement().attributeValue("type")); }
public void notifyQueueStatus(JID sender, JID receiver, UserRequest request, boolean isPolling) { Packet statusPacket; if (isPolling) { statusPacket = new IQ(); } else { statusPacket = new Message(); } statusPacket.setFrom(sender); statusPacket.setTo(receiver); // Add Queue Status Packet to IQ Element status = statusPacket .getElement() .addElement("queue-status", "http://jabber.org/protocol/workgroup"); // Add Time Element Element time = status.addElement("time"); time.setText(Integer.toString(request.getTimeStatus())); // Add Position Element Element position = status.addElement("position"); position.setText(Integer.toString(request.getPosition() + 1)); status.add(request.getSessionElement()); // Send the queue status request.getWorkgroup().send(statusPacket); }
protected IQ error(Packet packet, PacketError.Condition condition) { IQ reply; reply = new IQ(IQ.Type.error, packet.getID()); reply.setFrom(packet.getTo()); reply.setTo(packet.getFrom()); reply.setError(condition); return reply; }
@Test public void testNotProvidingNodeAttributeReturnsErrorStanza() throws Exception { BaseElement element = new BaseElement("subscriptions"); event.process(element, jid, request, null); Packet response = queue.poll(100, TimeUnit.MILLISECONDS); PacketError error = response.getError(); Assert.assertNotNull(error); Assert.assertEquals(PacketError.Type.modify, error.getType()); Assert.assertEquals("nodeid-required", error.getApplicationConditionName()); }
@Test public void testNodeStoreExceptionResultsInInternalServerErrorStanza() throws Exception { Mockito.when(dataStore.nodeExists(Mockito.anyString())).thenThrow(NodeStoreException.class); event.process(element, jid, request, null); Packet response = queue.poll(100, TimeUnit.MILLISECONDS); PacketError error = response.getError(); Assert.assertNotNull(error); Assert.assertEquals(PacketError.Type.wait, error.getType()); Assert.assertEquals(PacketError.Condition.internal_server_error, error.getCondition()); }
private void sendFederatedRequests(String originatingServer) throws ComponentException { String remoteServer = discoveredServers.get(originatingServer); List<Packet> packetsToSend = waitingStanzas.get(originatingServer); if (packetsToSend == null) { return; } for (Packet packet : packetsToSend) { packet.setTo(remoteServer); sendPacket(packet.createCopy()); } waitingStanzas.remove(originatingServer); }
@Test public void testInvalidSinceAttributesReturnsErrorStanza() throws Exception { request.getChildElement().element("user-items").addAttribute("since", "a week ago"); userItemsGet.process(element, jid, request, null); Packet response = queue.poll(); PacketError error = response.getError(); Assert.assertNotNull(error); Assert.assertEquals(PacketError.Type.modify, error.getType()); Assert.assertEquals("invalid-since-value-provided", error.getApplicationConditionName()); }
@Test public void testNotProvidingSubscriptionAttributeReturnsErrorStanza() throws Exception { IQ request = toIq( readStanzaAsString("/iq/pubsub/subscribe/authorizationPendingGrantReply.stanza") .replaceFirst("subscription='subscribed'", "")); event.process(element, jid, request, null); Packet response = queue.poll(100, TimeUnit.MILLISECONDS); PacketError error = response.getError(); Assert.assertNotNull(error); Assert.assertEquals(PacketError.Type.modify, error.getType()); Assert.assertEquals(PacketError.Condition.bad_request, error.getCondition()); }
@Test public void testNonExistantNodeRetunsErrorStanza() throws Exception { Mockito.when(dataStore.nodeExists(node)).thenReturn(false); event.setChannelManager(dataStore); event.process(element, jid, request, null); Packet response = queue.poll(100, TimeUnit.MILLISECONDS); PacketError error = response.getError(); Assert.assertNotNull(error); Assert.assertEquals(PacketError.Type.cancel, error.getType()); Assert.assertEquals(PacketError.Condition.item_not_found, error.getCondition()); }
@Test public void testNotProvidingJidAttributeReturnsErrorStanza() throws Exception { IQ request = toIq( readStanzaAsString("/iq/pubsub/affiliation/affiliationChange.stanza") .replaceFirst("jid='*****@*****.**'", "")); event.process(element, jid, request, null); Packet response = queue.poll(100, TimeUnit.MILLISECONDS); PacketError error = response.getError(); Assert.assertNotNull(error); Assert.assertEquals(PacketError.Type.modify, error.getType()); Assert.assertEquals(PacketError.Condition.bad_request, error.getCondition()); }
/** * Processes packets that were sent to this service. Currently only packets that were sent from * registered components are being processed. In the future, we may also process packet of trusted * clients. Trusted clients may be able to execute ad-hoc commands such as adding or removing * components. * * @param packet the packet to process. */ @Override public void process(Packet packet) throws PacketException { List<Component> components = getComponents(packet.getFrom()); // Only process packets that were sent by registered components if (!components.isEmpty()) { if (packet instanceof IQ && IQ.Type.result == ((IQ) packet).getType()) { IQ iq = (IQ) packet; Element childElement = iq.getChildElement(); if (childElement != null) { String namespace = childElement.getNamespaceURI(); if ("http://jabber.org/protocol/disco#info".equals(namespace)) { // Add a disco item to the server for the component that supports disco Element identity = childElement.element("identity"); if (identity == null) { // Do nothing since there are no identities in the disco#info packet return; } try { XMPPServer.getInstance() .getIQDiscoItemsHandler() .addComponentItem(packet.getFrom().toBareJID(), identity.attributeValue("name")); for (Component component : components) { if (component instanceof ComponentSession.ExternalComponent) { ComponentSession.ExternalComponent externalComponent = (ComponentSession.ExternalComponent) component; externalComponent.setName(identity.attributeValue("name")); externalComponent.setType(identity.attributeValue("type")); externalComponent.setCategory(identity.attributeValue("category")); } } } catch (Exception e) { Log.error( "Error processing disco packet of components: " + components + " - " + packet.toXML(), e); } // Store the IQ disco#info returned by the component addComponentInfo(iq); // Notify listeners that a component answered the disco#info request notifyComponentInfo(iq); // Alert other cluster nodes CacheFactory.doClusterTask(new NotifyComponentInfo(iq)); } } } } }
public void deliver(Packet packet) throws UnauthorizedException { if (isClosed()) { // OF-857: Do not allow the backup deliverer to recurse if (backupDeliverer == null) { Log.error("Failed to deliver packet: " + packet.toXML()); throw new IllegalStateException("Connection closed"); } // attempt to deliver via backup only once PacketDeliverer backup = backupDeliverer; backupDeliverer = null; backup.deliver(packet); } else { boolean errorDelivering = false; IoBuffer buffer = IoBuffer.allocate(4096); buffer.setAutoExpand(true); try { // OF-464: if the connection has been dropped, fail over to backupDeliverer (offline) if (!ioSession.isConnected()) { throw new IOException("Connection reset/closed by peer"); } XMLWriter xmlSerializer = new XMLWriter(new ByteBufferWriter(buffer, encoder.get()), new OutputFormat()); xmlSerializer.write(packet.getElement()); xmlSerializer.flush(); if (flashClient) { buffer.put((byte) '\0'); } buffer.flip(); ioSessionLock.lock(); try { ioSession.write(buffer); } finally { ioSessionLock.unlock(); } } catch (Exception e) { Log.debug("Error delivering packet:\n" + packet, e); errorDelivering = true; } if (errorDelivering) { close(); // Retry sending the packet again. Most probably if the packet is a // Message it will be stored offline backupDeliverer.deliver(packet); } else { session.incrementServerPacketCount(); } } }
@Override boolean canProcess(Packet packet) { String senderDomain = packet.getFrom().getDomain(); if (!getAuthenticatedDomains().contains(senderDomain)) { synchronized (senderDomain.intern()) { if (!getAuthenticatedDomains().contains(senderDomain) && !authenticateSubdomain(senderDomain, packet.getTo().getDomain())) { // Return error since sender domain was not validated by remote server LocalSession.returnErrorToSender(packet); return false; } } } return true; }
private void extractNodeDetails(Packet packet) { try { String packetXml = packet.toXML(); if (!packetXml.contains("node=")) { return; } nodeMap.put(packet.getID(), packetXml.split("node=\"")[1].split("\"")[0]); } catch (NullPointerException e) { logger.info("No node details found in federated packet"); logger.error(e); } catch (ArrayIndexOutOfBoundsException e) { logger.info("Error extracting node information from federated packet"); logger.error(e); } }
@Test public void testUserWithoutSubscriptionReturnsErrorStanza() throws Exception { Mockito.when(dataStore.nodeExists(node)).thenReturn(true); Mockito.when(dataStore.getUserSubscription(node, jid)).thenReturn(null); event.setChannelManager(dataStore); event.process(element, jid, request, null); Packet response = queue.poll(100, TimeUnit.MILLISECONDS); PacketError error = response.getError(); Assert.assertNotNull(error); Assert.assertEquals(PacketError.Type.auth, error.getType()); Assert.assertEquals(PacketError.Condition.not_authorized, error.getCondition()); }
public void deliver(Packet packet) throws UnauthorizedException, PacketException { if (isClosed()) { deliverer.deliver(packet); } else { try { // Invoke the interceptors before we send the packet InterceptorManager.getInstance().invokeInterceptors(packet, session, false, false); boolean errorDelivering = false; synchronized (writer) { try { xmlSerializer.write(packet.getElement()); if (flashClient) { writer.write('\0'); } xmlSerializer.flush(); } catch (IOException e) { Log.debug("Error delivering packet" + "\n" + this.toString(), e); errorDelivering = true; } } if (errorDelivering) { close(); // Retry sending the packet again. Most probably if the packet is a // Message it will be stored offline deliverer.deliver(packet); } else { // Invoke the interceptors after we have sent the packet InterceptorManager.getInstance().invokeInterceptors(packet, session, false, true); session.incrementServerPacketCount(); } } catch (PacketRejectedException e) { // An interceptor rejected the packet so do nothing } } }
/** * Delivers the packet to the packet recipient. * * @param packet the packet to deliver * @throws PacketException if the packet is null or the recipient was not found. */ public static void deliver(Packet packet) throws PacketException { if (packet == null) { throw new PacketException("Packet was null"); } try { JID recipient = packet.getTo(); if (recipient != null) { ClientSession clientSession = SessionManager.getInstance().getSession(recipient); if (clientSession != null) { clientSession.deliver(packet); } } } catch (Exception e) { log.error("Could not deliver packet: " + packet.toString(), e); } }
@Test public void testUserWhoIsntOwnerOrModeratorCantUpdateSubscription() throws Exception { NodeAffiliation subscriptionMock = Mockito.mock(NodeAffiliation.class); Mockito.when(subscriptionMock.getAffiliation()).thenReturn(Affiliations.member); Mockito.when(dataStore.nodeExists(node)).thenReturn(true); Mockito.when(dataStore.getUserAffiliation(node, jid)).thenReturn(subscriptionMock); event.setChannelManager(dataStore); event.process(element, jid, request, null); Packet response = queue.poll(100, TimeUnit.MILLISECONDS); PacketError error = response.getError(); Assert.assertNotNull(error); Assert.assertEquals(PacketError.Type.auth, error.getType()); Assert.assertEquals(PacketError.Condition.not_authorized, error.getCondition()); }
@Test public void testSubscribingUserMustHaveExistingSubscriptionToUpdate() throws Exception { NodeAffiliation subscriptionMockActor = Mockito.mock(NodeAffiliation.class); Mockito.when(subscriptionMockActor.getAffiliation()).thenReturn(Affiliations.owner); Mockito.when(dataStore.nodeExists(node)).thenReturn(true); Mockito.when(dataStore.getUserAffiliation(node, jid)).thenReturn(subscriptionMockActor); Mockito.when(dataStore.getUserSubscription(node, new JID(subscriber))).thenReturn(null); event.setChannelManager(dataStore); event.process(element, jid, request, null); Packet response = queue.poll(100, TimeUnit.MILLISECONDS); PacketError error = response.getError(); Assert.assertNotNull(error); Assert.assertEquals(PacketError.Type.modify, error.getType()); Assert.assertEquals(PacketError.Condition.unexpected_request, error.getCondition()); }
@Test public void testItIsNotPossibleToChangeTheAffiliationOfNodeOwner() throws Exception { NodeAffiliation affiliationSubscriber = Mockito.mock(NodeAffiliation.class); Mockito.when(affiliationSubscriber.getAffiliation()).thenReturn(Affiliations.owner); Mockito.when(channelManager.nodeExists(node)).thenReturn(true); Mockito.when(channelManager.getUserAffiliation(Mockito.anyString(), Mockito.any(JID.class))) .thenReturn(affiliationSubscriber); event.setChannelManager(channelManager); event.process(element, jid, request, null); Packet response = queue.poll(100, TimeUnit.MILLISECONDS); PacketError error = response.getError(); Assert.assertNotNull(error); Assert.assertEquals(PacketError.Type.modify, error.getType()); Assert.assertEquals(PacketError.Condition.not_acceptable, error.getCondition()); }
@Test public void testNodeStoreExceptionGeneratesAnErrorStanza() throws Exception { Mockito.when( channelManager.getUserFeedItems( Mockito.any(JID.class), Mockito.any(Date.class), Mockito.anyInt(), Mockito.any(GlobalItemID.class), Mockito.anyBoolean())) .thenThrow(new NodeStoreException()); userItemsGet.process(element, jid, request, null); Packet response = queue.poll(); PacketError error = response.getError(); Assert.assertNotNull(error); Assert.assertEquals(PacketError.Type.wait, error.getType()); Assert.assertEquals(PacketError.Condition.internal_server_error, error.getCondition()); }
@Test public void testUserMustHaveExistingAffiliationToUpdate() throws Exception { NodeAffiliation affiliationMock = Mockito.mock(NodeAffiliation.class); Mockito.when(affiliationMock.getAffiliation()).thenReturn(Affiliations.owner); Mockito.when(channelManager.nodeExists(node)).thenReturn(true); // actorHasPermission Mockito.when(channelManager.getUserAffiliation(node, jid)).thenReturn(affiliationMock); // subscriberHasCurrentAffiliation Mockito.when(channelManager.getUserAffiliation(node, new JID("*****@*****.**"))) .thenReturn(null); event.setChannelManager(channelManager); event.process(element, jid, request, null); Packet response = queue.poll(100, TimeUnit.MILLISECONDS); PacketError error = response.getError(); Assert.assertNotNull(error); Assert.assertEquals(PacketError.Type.modify, error.getType()); Assert.assertEquals(PacketError.Condition.unexpected_request, error.getCondition()); }
@Override public void sendPacket(Component component, Packet packet) { if (packet != null && packet.getFrom() == null) { throw new IllegalArgumentException( "Packet with no FROM address was received from component."); } PacketRouter router = XMPPServer.getInstance().getPacketRouter(); if (router != null) { router.route(packet); } }
@Test public void testPassingValidSubscriptionSendsOutExpectedNotifications() throws Exception { IQ request = toIq( readStanzaAsString("/iq/pubsub/subscribe/authorizationPendingGrantReply.stanza") .replaceFirst("subscription='subscribed'", "subscription='subscribed'")); NodeAffiliation subscriptionMockActor = Mockito.mock(NodeAffiliation.class); Mockito.when(subscriptionMockActor.getAffiliation()).thenReturn(Affiliations.owner); NodeSubscription subscriptionMockSubscriber = Mockito.mock(NodeSubscription.class); Mockito.when(subscriptionMockSubscriber.getSubscription()).thenReturn(Subscriptions.subscribed); Mockito.when(dataStore.nodeExists(node)).thenReturn(true); Mockito.when(dataStore.getUserAffiliation(node, jid)).thenReturn(subscriptionMockActor); Mockito.when(dataStore.getUserSubscription(node, new JID(subscriber))) .thenReturn(subscriptionMockSubscriber); event.setChannelManager(dataStore); ArrayList<NodeSubscription> subscribers = new ArrayList<NodeSubscription>(); subscribers.add(new NodeSubscriptionMock(new JID("*****@*****.**"))); subscribers.add(new NodeSubscriptionMock(new JID("*****@*****.**"))); Mockito.doReturn(new ResultSetImpl<NodeSubscription>(subscribers)) .when(dataStore) .getNodeSubscriptionListeners(Mockito.anyString()); event.setChannelManager(dataStore); event.process(element, jid, request, null); Assert.assertEquals(2, queue.size()); Packet notification = queue.poll(100, TimeUnit.MILLISECONDS); Assert.assertEquals("*****@*****.**", notification.getTo().toString()); notification = queue.poll(100, TimeUnit.MILLISECONDS); Assert.assertEquals("*****@*****.**", notification.getTo().toString()); Assert.assertEquals( node, notification.getElement().element("event").element("subscription").attributeValue("node")); Assert.assertTrue(notification.toXML().contains(JabberPubsub.NS_PUBSUB_EVENT)); Assert.assertEquals( "subscribed", notification .getElement() .element("event") .element("subscription") .attributeValue("subscription")); Assert.assertEquals( subscriber, notification.getElement().element("event").element("subscription").attributeValue("jid")); }
public void send(Packet packet) { if (packet == null) { return; } packet.setTo(user.getAddress()); if (session != null && session.getStatus() == Session.STATUS_AUTHENTICATED) { // Send the packet directly to the local user session session.process(packet); } else { router.route(packet); } }
/** * Make sure that the received packet has a TO and FROM values defined and that it was sent from a * previously validated domain. If the packet does not matches any of the above conditions then a * PacketRejectedException will be thrown. * * @param packet the received packet. * @throws PacketRejectedException if the packet does not include a TO or FROM or if the packet * was sent from a domain that was not previously validated. */ private void packetReceived(Packet packet) throws PacketRejectedException { if (packet.getTo() == null || packet.getFrom() == null) { Log.debug( "Closing IncomingServerSession due to packet with no TO or FROM: " + packet.toXML()); // Send a stream error saying that the packet includes no TO or FROM StreamError error = new StreamError(StreamError.Condition.improper_addressing); connection.deliverRawText(error.toXML()); // Close the underlying connection connection.close(); open = false; throw new PacketRejectedException("Packet with no TO or FROM attributes"); } else if (!((IncomingServerSession) session).isValidDomain(packet.getFrom().getDomain())) { Log.debug( "Closing IncomingServerSession due to packet with invalid domain: " + packet.toXML()); // Send a stream error saying that the packet includes an invalid FROM StreamError error = new StreamError(StreamError.Condition.invalid_from); connection.deliverRawText(error.toXML()); // Close the underlying connection connection.close(); open = false; throw new PacketRejectedException("Packet with no TO or FROM attributes"); } }
public void process(Packet packet) throws ComponentException { logger.debug("Packet payload " + packet.toXML() + " going to federation."); String to = packet.getTo().toString(); String uniqueId = generateUniqueId(packet); idMap.put(uniqueId, packet.getID()); packet.setID(uniqueId); sentRemotePackets.put(uniqueId, packet.getFrom()); try { extractNodeDetails(packet); // Do we have a map already? if (discoveredServers.containsKey(to)) { packet.setTo(new JID(discoveredServers.get(to))); sendPacket(packet.createCopy()); return; } // Are we already discovering a remote server? if (!remoteChannelDiscoveryStatus.containsKey(to)) { discoverRemoteChannelServer(to, packet.getID()); } else if (remoteChannelDiscoveryStatus.get(to).equals(NO_CHANNEL_SERVER)) { logger.error("No remote channel server for " + to); IQ reply = IQ.createResultIQ((IQ) packet); reply.setError( new PacketError( PacketError.Condition.remote_server_not_found, PacketError.Type.cancel)); component.sendPacket(reply); return; } // Add packet to list if (!waitingStanzas.containsKey(to)) { waitingStanzas.put(to, new ArrayList<Packet>()); } waitingStanzas.get(to).add(packet); logger.debug( "Adding packet to waiting stanza list for " + to + " (size " + waitingStanzas.get(to).size() + ")"); } catch (Exception e) { logger.error(e); } }
/* @see org.xmpp.component.Component#processPacket(org.xmpp.packet.Packet) */ public void processPacket(Packet packet) { try { debug("Service.processPacket: %s", packet.toXML()); List<Packet> replies = null; if (packet instanceof IQ) replies = processIQ((IQ) packet); else if (packet instanceof Presence) replies = processPresence((Presence) packet); else if (packet instanceof Message) replies = processMessage((Message) packet); else { debug("ignoring unknown packet: %s", packet); } if (replies != null) for (Packet p : replies) send(p); } catch (Exception e) { Log.error("Interop:" + getName() + " - exception in processPacket", e); } }
/** * Delivers the packet to the Connection Manager that in turn will forward it to the target user. * Connection Managers may have one or many connections to the server so just get any connection * to the Connection Manager (uses a random) and use it. * * <p>If the packet to send does not have a TO attribute then wrap the packet with a special IQ * packet. The wrapper IQ packet will be sent to the Connection Manager and the stream ID of this * Client Session will be used for identifying that the wrapped packet must be sent to the * connected user. Since some packets can be exchanged before the user has a binded JID we need to * use the stream ID as the unique identifier. * * @param packet the packet to send to the user. */ @Override public void deliver(Packet packet) { String streamID = session.getStreamID().getID(); ConnectionMultiplexerSession multiplexerSession = multiplexerManager.getMultiplexerSession(connectionManagerName, streamID); if (multiplexerSession != null) { // Wrap packet so that the connection manager can figure out the target session Route wrapper = new Route(streamID); wrapper.setFrom(serverName); wrapper.setTo(connectionManagerName); wrapper.setChildElement(packet.getElement().createCopy()); // Deliver wrapper multiplexerSession.process(wrapper); session.incrementServerPacketCount(); } }
/** * Returns true if the specified packet must be blocked based on this privacy list rules. Rules * are going to be analyzed based on their order (in ascending order). When a rule is matched then * communication will be blocked or allowed based on that rule. No more further analysis is going * to be made. * * @param packet the packet to analyze if it must be blocked. * @return true if the specified packet must be blocked based on this privacy list rules. */ public boolean shouldBlockPacket(Packet packet) { if (packet.getFrom() == null) { // Sender is the server so it's not denied return false; } // Iterate over the rules and check each rule condition Roster roster = getRoster(); for (PrivacyItem item : items) { if (item.matchesCondition(packet, roster, userJID)) { if (item.isAllow()) { return false; } if (Log.isDebugEnabled()) { Log.debug("PrivacyList: Packet was blocked: " + packet); } return true; } } // If no rule blocked the communication then allow the packet to flow return false; }