Example #1
0
  private Set<String> getMatchingSubscriptions(String partition, String topic) {

    Set<String> topicFilterKeys = new HashSet<>();

    ListIterator<String> pathIterator =
        Arrays.asList(topic.split(Constant.PATH_SEPARATOR)).listIterator();

    List<String> growingTitles = new ArrayList<>();

    while (pathIterator.hasNext()) {

      String name = pathIterator.next();

      List<String> slWildCardList = new ArrayList<>(growingTitles);

      if (pathIterator.hasNext()) {
        // We deal with wildcard.
        slWildCardList.add(Constant.SINGLE_LEVEL_WILDCARD);
        topicFilterKeys.add(quickCheckIdKey(partition, slWildCardList));

      } else {
        // we deal with full topic
        slWildCardList.add(name);
      }

      List<String> reverseSlWildCardList = new ArrayList<>(slWildCardList);

      growingTitles.add(name);

      int sizeOfTopic = slWildCardList.size();
      if (sizeOfTopic > 1) {
        sizeOfTopic -= 1;

        for (int i = 0; i < sizeOfTopic; i++) {

          if (i >= 0) {
            slWildCardList.set(i, Constant.MULTI_LEVEL_WILDCARD);
            reverseSlWildCardList.set(sizeOfTopic - i, Constant.MULTI_LEVEL_WILDCARD);

            topicFilterKeys.add(quickCheckIdKey(partition, slWildCardList));
            topicFilterKeys.add(quickCheckIdKey(partition, reverseSlWildCardList));
          }
        }
      }
    }

    topicFilterKeys.add(quickCheckIdKey(partition, growingTitles));

    return topicFilterKeys;
  }
Example #2
0
  /**
   * Provides the Observer with a new item to observe.
   *
   * <p>The {@link com.caricah.iotracah.core.modules.Server} may call this method 0 or more times.
   *
   * <p>The {@code Observable} will not call this method again after it calls either {@link
   * #onCompleted} or {@link #onError}.
   *
   * @param iotMessage the item emitted by the Observable
   */
  @Override
  public void onNext(IOTMessage iotMessage) {

    getExecutorService()
        .submit(
            () -> {
              log.info(" onNext : received {}", iotMessage);
              try {

                IOTMessage response = null;

                switch (iotMessage.getMessageType()) {
                  case ConnectMessage.MESSAGE_TYPE:
                    ConnectMessage connectMessage = (ConnectMessage) iotMessage;
                    response =
                        ConnectAcknowledgeMessage.from(
                            connectMessage.isDup(),
                            connectMessage.getQos(),
                            connectMessage.isRetain(),
                            connectMessage.getKeepAliveTime(),
                            MqttConnectReturnCode.CONNECTION_ACCEPTED);

                    break;
                  case SubscribeMessage.MESSAGE_TYPE:
                    SubscribeMessage subscribeMessage = (SubscribeMessage) iotMessage;

                    List<Integer> grantedQos = new ArrayList<>();
                    subscribeMessage
                        .getTopicFilterList()
                        .forEach(
                            topic -> {
                              String topicKey =
                                  quickCheckIdKey(
                                      "",
                                      Arrays.asList(topic.getKey().split(Constant.PATH_SEPARATOR)));

                              Set<String> channelIds = subscriptions.get(topicKey);

                              if (Objects.isNull(channelIds)) {
                                channelIds = new HashSet<>();
                              }

                              channelIds.add(subscribeMessage.getConnectionId());
                              subscriptions.put(topicKey, channelIds);

                              grantedQos.add(topic.getValue());
                            });

                    response =
                        SubscribeAcknowledgeMessage.from(
                            subscribeMessage.getMessageId(), grantedQos);

                    break;
                  case UnSubscribeMessage.MESSAGE_TYPE:
                    UnSubscribeMessage unSubscribeMessage = (UnSubscribeMessage) iotMessage;
                    response =
                        UnSubscribeAcknowledgeMessage.from(unSubscribeMessage.getMessageId());

                    break;
                  case Ping.MESSAGE_TYPE:
                    response = iotMessage;
                    break;
                  case PublishMessage.MESSAGE_TYPE:
                    PublishMessage publishMessage = (PublishMessage) iotMessage;

                    Set<String> matchingTopics =
                        getMatchingSubscriptions("", publishMessage.getTopic());

                    for (String match : matchingTopics) {
                      Set<String> channelIds = subscriptions.get(match);

                      if (Objects.nonNull(channelIds)) {

                        channelIds.forEach(
                            id -> {
                              PublishMessage clonePublishMessage = publishMessage.cloneMessage();
                              clonePublishMessage.copyTransmissionData(iotMessage);
                              clonePublishMessage.setConnectionId(id);
                              pushToServer(clonePublishMessage);
                            });
                      }
                    }

                    if (MqttQoS.AT_MOST_ONCE.value() == publishMessage.getQos()) {

                      break;

                    } else if (MqttQoS.AT_LEAST_ONCE.value() == publishMessage.getQos()) {

                      response = AcknowledgeMessage.from(publishMessage.getMessageId());
                      break;
                    }

                  case PublishReceivedMessage.MESSAGE_TYPE:
                  case ReleaseMessage.MESSAGE_TYPE:
                  case CompleteMessage.MESSAGE_TYPE:
                  case DisconnectMessage.MESSAGE_TYPE:
                  case AcknowledgeMessage.MESSAGE_TYPE:
                  default:
                    DisconnectMessage disconnectMessage = DisconnectMessage.from(true);
                    disconnectMessage.copyTransmissionData(iotMessage);

                    throw new ShutdownException(disconnectMessage);
                }

                if (Objects.nonNull(response)) {

                  response.copyTransmissionData(iotMessage);
                  pushToServer(response);
                }

              } catch (ShutdownException e) {

                IOTMessage response = e.getResponse();
                if (Objects.nonNull(response)) {
                  pushToServer(response);
                }

              } catch (Exception e) {
                log.error(" onNext : Serious error that requires attention ", e);
              }
            });
  }