/**
   * Returns true if the specified notification is newer than the current one.
   *
   * @param response the notification
   * @return true if the notification is new
   */
  public synchronized boolean isNew(Response response) {

    if (!response.getOptions().hasObserve()) {
      // this is a final response, e.g., error or proactive cancellation
      return true;
    }

    // Multiple responses with different notification numbers might
    // arrive and be processed by different threads. We have to
    // ensure that only the most fresh one is being delivered.
    // We use the notation from the observe draft-08.
    long T1 = getTimestamp();
    long T2 = System.currentTimeMillis();
    int V1 = getCurrent();
    int V2 = response.getOptions().getObserve();
    int notifMaxAge =
        NetworkConfig.getStandard().getInt(NetworkConfigDefaults.NOTIFICATION_MAX_AGE);
    if (V1 < V2 && V2 - V1 < 1 << 23 || V1 > V2 && V1 - V2 > 1 << 23 || T2 > T1 + notifMaxAge) {

      setTimestamp(T2);
      number.set(V2);
      return true;
    } else {
      return false;
    }
  }
예제 #2
0
  @Test
  public void testNonConfirmable() throws Exception {
    // send request
    Request req2acc = new Request(Code.POST);
    req2acc.setConfirmable(false);
    req2acc.setURI("localhost:" + serverPort + "/" + ACC_RESOURCE);
    req2acc.setPayload("client says hi");
    req2acc.send();

    // receive response and check
    Response response = req2acc.waitForResponse(100);
    assertNotNull(response);
    assertEquals(response.getPayloadString(), SERVER_RESPONSE);
    assertEquals(response.getType(), Type.NON);

    Request req2noacc = new Request(Code.POST);
    req2noacc.setConfirmable(false);
    req2noacc.setURI("coap://localhost:" + serverPort + "/" + NO_ACC_RESOURCE);
    req2noacc.setPayload("client says hi");
    req2noacc.send();

    // receive response and check
    response = req2noacc.waitForResponse(100);
    assertNotNull(response);
    assertEquals(response.getPayloadString(), SERVER_RESPONSE);
    assertEquals(response.getType(), Type.NON);
  }
예제 #3
0
 @Override
 public void handleGET(CoapExchange exchange) {
   String payload =
       "Available commands:\n - GET: show statistics\n - POST write stats to file\n - DELETE: reset statistics\n\n";
   payload += getStatString();
   Response response = new Response(ResponseCode.CONTENT);
   response.setPayload(payload);
   response.getOptions().setContentFormat(MediaTypeRegistry.TEXT_PLAIN);
   exchange.respond(response);
 }
예제 #4
0
  protected boolean checkResponse(Request request, Response response) {
    boolean success = true;

    success &= checkType(Type.NON, response.getType());
    success &= checkInt(EXPECTED_RESPONSE_CODE.value, response.getCode().value, "code");
    success &= hasContentType(response);
    success &= hasNonEmptyPalyoad(response);

    return success;
  }
  @Override
  public void handlePOST(CoapExchange exchange) {
    String payload = exchange.getRequestText();
    String[] parts = payload.split("\\?");
    String[] path = parts[0].split("/");
    Resource resource = create(new LinkedList<String>(Arrays.asList(path)));

    Response response = new Response(ResponseCode.CREATED);
    response.getOptions().setLocationPath(resource.getURI());
    exchange.respond(response);
  }
예제 #6
0
    @Override
    public void handlePOST(CoapExchange exchange) {
      // TODO include stopping the writing => make something for the whole
      // proxy
      // executor.shutdown();
      // request.respond(CodeRegistry.RESP_DELETED, "Stopped",
      // MediaTypeRegistry.TEXT_PLAIN);

      // starting to log the stats on a new file

      // create the new file
      String logName = System.nanoTime() + CACHE_LOG_NAME;
      final File cacheLog = new File(logName);
      try {
        cacheLog.createNewFile();

        // write the header
        com.google.common.io.Files.write(
            "hits%, avg. load, #evictions \n", cacheLog, Charset.defaultCharset());
      } catch (IOException e) {
      }

      executor.scheduleWithFixedDelay(
          new Runnable() {

            @Override
            public void run() {
              CacheStats cacheStats = cacheResource.getCacheStats().minus(relativeCacheStats);

              String csvStats =
                  String.format(
                      "%.3f, %.3f, %d %n",
                      cacheStats.hitRate(),
                      cacheStats.averageLoadPenalty(),
                      cacheStats.evictionCount());
              try {
                com.google.common.io.Files.append(csvStats, cacheLog, Charset.defaultCharset());
              } catch (IOException e) {
              }
            }
          },
          0,
          DEFAULT_LOGGING_DELAY,
          TimeUnit.SECONDS);

      Response response = new Response(ResponseCode.CREATED);
      response.setPayload("Creted log: " + logName);
      response.getOptions().setContentFormat(MediaTypeRegistry.TEXT_PLAIN);
      exchange.respond(response);
    }
  @Override
  public void handlePOST(CoapExchange exchange) {

    Response response = new Response(CoAP.ResponseCode.CONTENT);

    int contentType = exchange.getRequestOptions().getContentFormat();
    int acceptTypeVal = exchange.getRequestOptions().getAccept();
    String acceptType = "";
    switch (acceptTypeVal) {
      case MediaTypeRegistry.APPLICATION_EXI:
        break;
      case MediaTypeRegistry.APPLICATION_XML:
        acceptType = MediaType.APPLICATION_XML.getSubType();
        break;
      case MediaTypeRegistry.APPLICATION_JSON:
        acceptType = MediaType.APPLICATION_JSON.getSubType();
        break;
    }

    Resource02_Discovery rd = new Resource02_Discovery();
    byte[] message = exchange.getRequestPayload();
    InputStream isMsg = new ByteArrayInputStream(message);
    StringRepresentation sr = new StringRepresentation("");

    try {
      switch (contentType) {
        case MediaTypeRegistry.APPLICATION_EXI:
          //              decode first! TODO
          //                 sr = rc.registerXmlHandler(isMsg, acceptType);
          //                 byte[] exiMessage = codeSchemaLess(message);
          //                 response.setPayload(exiMessage);
          break;
        case MediaTypeRegistry.APPLICATION_JSON:
          sr = rd.discoveryJsonHandler(isMsg, acceptType);
          response.setPayload(sr.getText());
          break;
        default:
          response.setPayload(
              "accept types supported: application/exi; application/xml; application/json");
      }

    } catch (ResourceException ex) {
      Logger.getLogger(CoapR02_Discovery.class.getName()).log(Level.SEVERE, null, ex);
    }

    exchange.respond(response);
  }
  /**
   * When we receive a Confirmable response, we acknowledge it and it also counts as acknowledgment
   * for the request. If the response is a duplicate, we stop it here and do not forward it to the
   * upper layer.
   */
  @Override
  public void receiveResponse(Exchange exchange, Response response) {
    exchange.setFailedTransmissionCount(0);

    exchange.getCurrentRequest().setAcknowledged(true);
    LOGGER.finest("Cancel any retransmission");
    exchange.setRetransmissionHandle(null);

    if (response.getType() == Type.CON && !exchange.getRequest().isCanceled()) {
      LOGGER.finer("Response is confirmable, send ACK");
      EmptyMessage ack = EmptyMessage.newACK(response);
      sendEmptyMessage(exchange, ack);
    }

    if (response.isDuplicate()) {
      LOGGER.fine("Response is duplicate, ignore it");
    } else {
      super.receiveResponse(exchange, response);
    }
  }
  /**
   * Makes sure that the response type is correct. The response type for a NON can be NON or CON.
   * The response type for a CON should either be an ACK with a piggy-backed response or, if an
   * empty ACK has already be sent, a CON or NON with a separate response.
   */
  @Override
  public void sendResponse(final Exchange exchange, final Response response) {

    LOGGER.finer("Send response, failed transmissions: " + exchange.getFailedTransmissionCount());

    // If a response type is set, we do not mess around with it.
    // Only if none is set, we have to decide for one here.

    Type respType = response.getType();
    if (respType == null) {
      Type reqType = exchange.getCurrentRequest().getType();
      if (reqType == Type.CON) {
        if (exchange.getCurrentRequest().isAcknowledged()) {
          // send separate response
          response.setType(Type.CON);
        } else {
          exchange.getCurrentRequest().setAcknowledged(true);
          // send piggy-backed response
          response.setType(Type.ACK);
          response.setMID(exchange.getCurrentRequest().getMID());
        }
      } else {
        // send NON response
        response.setType(Type.NON);
      }

      LOGGER.finest(
          "Switched response message type from "
              + respType
              + " to "
              + response.getType()
              + " (request was "
              + reqType
              + ")");

    } else if (respType == Type.ACK || respType == Type.RST) {
      response.setMID(exchange.getCurrentRequest().getMID());
    }

    if (response.getType() == Type.CON) {
      LOGGER.finer("Scheduling retransmission for " + response);
      prepareRetransmission(
          exchange,
          new RetransmissionTask(exchange, response) {
            public void retransmit() {
              sendResponse(exchange, response);
            }
          });
    }
    super.sendResponse(exchange, response);
  }
예제 #10
0
    @Override
    public void sendResponse(Exchange exchange, Response response) {

      if (response.getDestination() == null)
        throw new NullPointerException("Response has no destination address");
      if (response.getDestinationPort() == 0)
        throw new NullPointerException("Response has no destination port");

      matcher.sendResponse(exchange, response);

      /*
       * Logging here causes significant performance loss.
       * If necessary, add an interceptor that logs the messages,
       * e.g., the MessageTracer.
       */

      for (MessageInterceptor interceptor : interceptors) interceptor.sendResponse(response);

      // MessageInterceptor might have canceled
      if (!response.isCanceled()) connector.send(serializer.serialize(response));
    }
예제 #11
0
  /**
   * This method is used to apply resource-specific knowledge on the exchange. If the request was
   * successful, it sets the Observe option for the response. It is important to use the
   * notificationOrderer of the resource here. Further down the layer, race conditions could cause
   * local reordering of notifications. If the response has an error code, no observe relation can
   * be established and if there was one previously it is canceled. When this resource allows to be
   * observed by clients and the request is a GET request with an observe option, the {@link
   * ServerMessageDeliverer} already created the relation, as it manages the observing endpoints
   * globally.
   *
   * @param exchange the exchange
   * @param response the response
   */
  public void checkObserveRelation(Exchange exchange, Response response) {
    /*
     * If the request for the specified exchange tries to establish an observer
     * relation, then the ServerMessageDeliverer must have created such a relation
     * and added to the exchange. Otherwise, there is no such relation.
     * Remember that different paths might lead to this resource.
     */

    ObserveRelation relation = exchange.getRelation();
    if (relation == null) return; // because request did not try to establish a relation

    if (CoAP.ResponseCode.isSuccess(response.getCode())) {
      response.getOptions().setObserve(notificationOrderer.getCurrent());

      if (!relation.isEstablished()) {
        relation.setEstablished(true);
        addObserveRelation(relation);
      } else if (observeType != null) {
        // The resource can control the message type of the notification
        response.setType(observeType);
      }
    } // ObserveLayer takes care of the else case
  }
예제 #12
0
    /*
     * The endpoint's executor executes this method to convert the raw bytes
     * into a message, look for an associated exchange and forward it to
     * the stack of layers.
     */
    private void receiveMessage(RawData raw) {
      DataParser parser = new DataParser(raw.getBytes());

      if (parser.isRequest()) {
        // This is a request
        Request request;
        try {
          request = parser.parseRequest();
        } catch (IllegalStateException e) {
          StringBuffer log =
              new StringBuffer("message format error caused by ")
                  .append(raw.getInetSocketAddress());
          if (!parser.isReply()) {
            // manually build RST from raw information
            EmptyMessage rst = new EmptyMessage(Type.RST);
            rst.setDestination(raw.getAddress());
            rst.setDestinationPort(raw.getPort());
            rst.setMID(parser.getMID());
            for (MessageInterceptor interceptor : interceptors) interceptor.sendEmptyMessage(rst);
            connector.send(serializer.serialize(rst));
            log.append(" and reset");
          }
          if (LOGGER.isLoggable(Level.INFO)) {
            LOGGER.info(log.toString());
          }
          return;
        }
        request.setSource(raw.getAddress());
        request.setSourcePort(raw.getPort());
        request.setSenderIdentity(raw.getSenderIdentity());

        /*
         * Logging here causes significant performance loss.
         * If necessary, add an interceptor that logs the messages,
         * e.g., the MessageTracer.
         */

        for (MessageInterceptor interceptor : interceptors) interceptor.receiveRequest(request);

        // MessageInterceptor might have canceled
        if (!request.isCanceled()) {
          Exchange exchange = matcher.receiveRequest(request);
          if (exchange != null) {
            exchange.setEndpoint(CoAPEndpoint.this);
            coapstack.receiveRequest(exchange, request);
          }
        }

      } else if (parser.isResponse()) {
        // This is a response
        Response response = parser.parseResponse();
        response.setSource(raw.getAddress());
        response.setSourcePort(raw.getPort());

        /*
         * Logging here causes significant performance loss.
         * If necessary, add an interceptor that logs the messages,
         * e.g., the MessageTracer.
         */

        for (MessageInterceptor interceptor : interceptors) interceptor.receiveResponse(response);

        // MessageInterceptor might have canceled
        if (!response.isCanceled()) {
          Exchange exchange = matcher.receiveResponse(response);
          if (exchange != null) {
            exchange.setEndpoint(CoAPEndpoint.this);
            response.setRTT(System.currentTimeMillis() - exchange.getTimestamp());
            coapstack.receiveResponse(exchange, response);
          } else if (response.getType() != Type.ACK) {
            LOGGER.fine("Rejecting unmatchable response from " + raw.getInetSocketAddress());
            reject(response);
          }
        }

      } else if (parser.isEmpty()) {
        // This is an empty message
        EmptyMessage message = parser.parseEmptyMessage();
        message.setSource(raw.getAddress());
        message.setSourcePort(raw.getPort());

        /*
         * Logging here causes significant performance loss.
         * If necessary, add an interceptor that logs the messages,
         * e.g., the MessageTracer.
         */

        for (MessageInterceptor interceptor : interceptors)
          interceptor.receiveEmptyMessage(message);

        // MessageInterceptor might have canceled
        if (!message.isCanceled()) {
          // CoAP Ping
          if (message.getType() == Type.CON || message.getType() == Type.NON) {
            LOGGER.info("Responding to ping by " + raw.getInetSocketAddress());
            reject(message);
          } else {
            Exchange exchange = matcher.receiveEmptyMessage(message);
            if (exchange != null) {
              exchange.setEndpoint(CoAPEndpoint.this);
              coapstack.receiveEmptyMessage(exchange, message);
            }
          }
        }
      } else {
        LOGGER.finest("Silently ignoring non-CoAP message from " + raw.getInetSocketAddress());
      }
    }
 /**
  * Checks if the response code is a successful code.
  *
  * @return true, if is success
  */
 public boolean isSuccess() {
   return CoAP.ResponseCode.isSuccess(response.getCode());
 }
예제 #14
0
  @Override
  protected synchronized void executeRequest(
      Request request, String serverURI, String resourceUri) {

    // defensive check for slash
    if (!serverURI.endsWith("/") && !resourceUri.startsWith("/")) {
      resourceUri = "/" + resourceUri;
    }

    URI uri = null;
    try {
      uri = new URI(serverURI + resourceUri);
    } catch (URISyntaxException use) {
      throw new IllegalArgumentException("Invalid URI: " + use.getMessage());
    }

    request.setURI(uri);

    // for observing
    int observeLoop = 2;

    // print request info
    if (verbose) {
      System.out.println("Request for test " + this.testName + " sent");
      Utils.prettyPrint(request);
    }

    // execute the request
    try {
      Response response = null;
      boolean success = true;
      long time = 5000;

      request.send();

      System.out.println();
      System.out.println("**** TEST: " + testName + " ****");
      System.out.println("**** BEGIN CHECK ****");

      response = request.waitForResponse(time);
      if (response != null) {
        success &= checkType(Type.ACK, response.getType());
        success &= checkInt(EXPECTED_RESPONSE_CODE.value, response.getCode().value, "code");
        success &= checkToken(request.getToken(), response.getToken());
        success &= hasContentType(response);
        success &= hasNonEmptyPalyoad(response);
        success &= hasObserve(response);

        if (success) {

          time = response.getOptions().getMaxAge() * 1000;
          System.out.println("+++++ Max-Age: " + time + " +++++");
          if (time == 0) time = 5000;

          for (int l = 0; success && (l < observeLoop); ++l) {

            response = request.waitForResponse(time + 1000);

            // checking the response
            if (response != null) {
              System.out.println("Received notification " + l);

              // print response info
              if (verbose) {
                System.out.println("Response received");
                System.out.println("Time elapsed (ms): " + response.getRTT());
                Utils.prettyPrint(response);
              }

              success &= checkResponse(request, response);

            } else {
              System.out.println("FAIL: Notifications stopped");
              success = false;
              break;
            } // response != null
          } // observeLoop

          if (response != null) {

            System.out.println("+++++++ Canceling +++++++");
            request.cancel(); // stack should send RST

            Thread.sleep(time + time / 2);

          } else {
            System.out.println("FAIL: Notifications stopped");
            success = false;
          }
        }
      } else {
        System.out.println("FAIL: No notification after registration");
        success = false;
      }

      if (success) {
        System.out.println("**** TEST PASSED ****");
        addSummaryEntry(testName + ": PASSED (conditionally)");
      } else {
        System.out.println("**** TEST FAILED ****");
        addSummaryEntry(testName + ": --FAILED--");
      }

      tickOffTest();

    } catch (InterruptedException e) {
      System.err.println("Interupted during receive: " + e.getMessage());
      System.exit(-1);
    }
  }
 /**
  * Gets the response code code.
  *
  * @return the response code
  */
 public ResponseCode getCode() {
   return response.getCode();
 }
 /**
  * Gets the payload of this response as string.
  *
  * @return the response text
  */
 public String getResponseText() {
   return response.getPayloadString();
 }
 /**
  * Gets the set of options of this response.
  *
  * @return the options
  */
 public OptionSet getOptions() {
   return response.getOptions();
 }
 /**
  * Gets the payload of this response as byte array.
  *
  * @return the payload
  */
 public byte[] getPayload() {
   return response.getPayload();
 }