/* * Copyright (C) 2013-2014 Sony Computer Science Laboratories, Inc. All Rights Reserved. * Copyright (C) 2014 Sony Corporation. All Rights Reserved. */ package com.sonycsl.wamp.role; import com.sonycsl.wamp.WampError; import com.sonycsl.wamp.WampPeer; import com.sonycsl.wamp.message.WampMessage; import com.sonycsl.wamp.message.WampMessageFactory; import com.sonycsl.wamp.message.WampMessageType; import com.sonycsl.wamp.message.WampPublishMessage; import com.sonycsl.wamp.message.WampSubscribeMessage; import com.sonycsl.wamp.message.WampUnsubscribeMessage; import org.json.JSONObject; import java.util.Map; import java.util.Map.Entry; import java.util.concurrent.ConcurrentHashMap; public class WampBroker extends WampRole { public interface PubSubMessageHandler { public void onSubscribe(String topic); public void onUnsubscribe(String topic); } private final Map<String, Map<WampPeer, Integer>> mSubscriberMaps = new ConcurrentHashMap<String, Map<WampPeer, Integer>>(); private int mPublicationId = 0; private int mSubscriptionId = 0; private final PubSubMessageHandler mPubSubMessageHandler; @Override public final String getRoleName() { return "broker"; } public WampBroker() { super(); mPubSubMessageHandler = null; } public WampBroker(PubSubMessageHandler handler) { super(); mPubSubMessageHandler = handler; } @Override protected final boolean resolveTxMessageImpl(WampPeer receiver, WampMessage msg) { return false; } @Override protected final boolean resolveRxMessageImpl(WampPeer transmitter, WampMessage msg, OnReplyListener listener) { if (msg.isSubscribeMessage()) { return resolveSubscribeMessage(transmitter, msg, listener); } if (msg.isUnsubscribeMessage()) { return resolveUnsubscribeMessage(transmitter, msg, listener); } if (msg.isPublishMessage()) { return resolvePublishMessage(transmitter, msg, listener); } return false; } private boolean resolveSubscribeMessage(WampPeer transmitter, WampMessage msg, OnReplyListener listener) { WampSubscribeMessage sub = msg.asSubscribeMessage(); String topic = sub.getTopic(); if (!mSubscriberMaps.containsKey(topic)) { mSubscriberMaps.put(topic, new ConcurrentHashMap<WampPeer, Integer>()); } Map<WampPeer, Integer> subMap = mSubscriberMaps.get(topic); int subscriptionId = ++mSubscriptionId; subMap.put(transmitter, subscriptionId); listener.onReply(transmitter, WampMessageFactory.createSubscribed(sub.getRequestId(), subscriptionId)); if (mPubSubMessageHandler != null) { mPubSubMessageHandler.onSubscribe(topic); } return true; } private boolean resolveUnsubscribeMessage(WampPeer transmitter, WampMessage msg, OnReplyListener listener) { /* * TODO improve performance */ WampUnsubscribeMessage unsub = msg.asUnsubscribeMessage(); int subId = unsub.getSubscriptionId(); for (Entry<String, Map<WampPeer, Integer>> topics : mSubscriberMaps.entrySet()) { Map<WampPeer, Integer> subMap = topics.getValue(); for (Entry<WampPeer, Integer> subIds : subMap.entrySet()) { WampPeer target = subIds.getKey(); if (target != transmitter) { continue; } if (subIds.getValue() == subId) { subMap.remove(target); listener.onReply(transmitter, WampMessageFactory.createUnsubscribed(unsub.getRequestId())); if (mPubSubMessageHandler != null) { mPubSubMessageHandler.onUnsubscribe(topics.getKey()); } return true; } } } listener.onReply(transmitter, WampMessageFactory.createError(WampMessageType.UNSUBSCRIBE, unsub.getRequestId(), new JSONObject(), WampError.NO_SUCH_SUBSCRIPTION)); return false; } private boolean resolvePublishMessage(WampPeer transmitter, WampMessage msg, OnReplyListener listener) { WampPublishMessage pub = msg.asPublishMessage(); int publicationId = ++mPublicationId; listener.onReply(transmitter, WampMessageFactory.createPublished(pub.getRequestId(), publicationId)); if (!mSubscriberMaps.containsKey(pub.getTopic())) { return true; } Map<WampPeer, Integer> subMap = mSubscriberMaps.get(pub.getTopic()); for (Entry<WampPeer, Integer> entry : subMap.entrySet()) { listener.onReply(entry.getKey(), createEventMessage(entry.getValue(), publicationId, msg.asPublishMessage())); } return true; } private WampMessage createEventMessage(int subscriptionId, int publicationId, WampPublishMessage msg) { if (msg.hasArgumentsKw()) { return WampMessageFactory.createEvent(subscriptionId, publicationId, new JSONObject(), msg.getArguments(), msg.getArgumentsKw()); } if (msg.hasArguments()) { return WampMessageFactory.createEvent(subscriptionId, publicationId, new JSONObject(), msg.getArguments()); } return WampMessageFactory.createEvent(subscriptionId, publicationId, new JSONObject()); } }