You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mina.apache.org by jv...@apache.org on 2013/06/16 10:14:08 UTC

[1/3] git commit: clear buffer before reading NIO socket

Updated Branches:
  refs/heads/trunk a68de05cc -> 08d2ac72b


clear buffer before reading NIO socket


Project: http://git-wip-us.apache.org/repos/asf/mina/repo
Commit: http://git-wip-us.apache.org/repos/asf/mina/commit/03b72a19
Tree: http://git-wip-us.apache.org/repos/asf/mina/tree/03b72a19
Diff: http://git-wip-us.apache.org/repos/asf/mina/diff/03b72a19

Branch: refs/heads/trunk
Commit: 03b72a196fc54d41057b80459218ce5869b16dab
Parents: a68de05
Author: jvermillard <jv...@apache.org>
Authored: Sat Jun 15 21:42:25 2013 +0200
Committer: jvermillard <jv...@apache.org>
Committed: Sat Jun 15 21:42:25 2013 +0200

----------------------------------------------------------------------
 .../main/java/org/apache/mina/transport/nio/NioUdpSession.java    | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mina/blob/03b72a19/core/src/main/java/org/apache/mina/transport/nio/NioUdpSession.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/mina/transport/nio/NioUdpSession.java b/core/src/main/java/org/apache/mina/transport/nio/NioUdpSession.java
index 42a0285..9dc0884 100644
--- a/core/src/main/java/org/apache/mina/transport/nio/NioUdpSession.java
+++ b/core/src/main/java/org/apache/mina/transport/nio/NioUdpSession.java
@@ -263,7 +263,7 @@ public class NioUdpSession extends AbstractNioSession implements SelectorListene
     public void ready(boolean accept, boolean connect, boolean read, ByteBuffer readBuffer, boolean write) {
         if (IS_DEBUG) {
             LOG.debug("session {} ready for accept={}, connect={}, read={}, write={}", new Object[] { this, accept,
-                    connect, read, write });
+                                    connect, read, write });
         }
 
         if (read) {
@@ -273,6 +273,7 @@ public class NioUdpSession extends AbstractNioSession implements SelectorListene
 
             // Read everything we can up to the buffer size
             try {
+                readBuffer.clear();
                 ((DatagramChannel) channel).receive(readBuffer);
                 readBuffer.flip();
 


[2/3] git commit: avoid chain of exception if close fail

Posted by jv...@apache.org.
avoid chain of exception if close fail


Project: http://git-wip-us.apache.org/repos/asf/mina/repo
Commit: http://git-wip-us.apache.org/repos/asf/mina/commit/2014f771
Tree: http://git-wip-us.apache.org/repos/asf/mina/tree/2014f771
Diff: http://git-wip-us.apache.org/repos/asf/mina/diff/2014f771

Branch: refs/heads/trunk
Commit: 2014f771916350154c32c24bec05bd8a8083e9c2
Parents: 03b72a1
Author: jvermillard <jv...@apache.org>
Authored: Sat Jun 15 21:43:39 2013 +0200
Committer: jvermillard <jv...@apache.org>
Committed: Sat Jun 15 21:43:39 2013 +0200

----------------------------------------------------------------------
 core/src/main/java/org/apache/mina/session/AbstractIoSession.java | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mina/blob/2014f771/core/src/main/java/org/apache/mina/session/AbstractIoSession.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/mina/session/AbstractIoSession.java b/core/src/main/java/org/apache/mina/session/AbstractIoSession.java
index 3ea614a..a82a2fa 100644
--- a/core/src/main/java/org/apache/mina/session/AbstractIoSession.java
+++ b/core/src/main/java/org/apache/mina/session/AbstractIoSession.java
@@ -599,7 +599,7 @@ public abstract class AbstractIoSession implements IoSession, ReadFilterChainCon
                 }
             }
         } catch (RuntimeException e) {
-            processException(e);
+            LOG.error("Exception while closing the session : ", e);
         }
         service.getManagedSessions().remove(id);
     }


[3/3] git commit: added a registering CoAP client (WIP)

Posted by jv...@apache.org.
added a registering CoAP client (WIP)


Project: http://git-wip-us.apache.org/repos/asf/mina/repo
Commit: http://git-wip-us.apache.org/repos/asf/mina/commit/08d2ac72
Tree: http://git-wip-us.apache.org/repos/asf/mina/tree/08d2ac72
Diff: http://git-wip-us.apache.org/repos/asf/mina/diff/08d2ac72

Branch: refs/heads/trunk
Commit: 08d2ac72b7584aade8171480e00050d06b468bba
Parents: 2014f77
Author: jvermillard <jv...@apache.org>
Authored: Sat Jun 15 21:48:59 2013 +0200
Committer: jvermillard <jv...@apache.org>
Committed: Sun Jun 16 10:13:23 2013 +0200

----------------------------------------------------------------------
 .../java/org/apache/mina/coap/CoapMessage.java  |  21 ++-
 .../mina/coap/resource/ResourceHandler.java     |   4 +-
 .../mina/coap/resource/ResourceRegistry.java    |   5 +-
 .../coap/resource/ResourceRegistryTest.java     |   9 +-
 .../apache/mina/filter/query/RequestFilter.java |  42 +++--
 .../mina/filter/query/RequestFilterTest.java    |   4 +-
 .../apache/mina/examples/coap/CoapClient.java   | 148 +++++++++++++++
 .../mina/examples/coap/CoapGetServer.java       | 110 -----------
 .../apache/mina/examples/coap/CoapServer.java   | 181 +++++++++++++++++++
 9 files changed, 382 insertions(+), 142 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mina/blob/08d2ac72/coap/src/main/java/org/apache/mina/coap/CoapMessage.java
----------------------------------------------------------------------
diff --git a/coap/src/main/java/org/apache/mina/coap/CoapMessage.java b/coap/src/main/java/org/apache/mina/coap/CoapMessage.java
index 4bdafa1..7af3c87 100644
--- a/coap/src/main/java/org/apache/mina/coap/CoapMessage.java
+++ b/coap/src/main/java/org/apache/mina/coap/CoapMessage.java
@@ -46,8 +46,16 @@ public class CoapMessage implements Request, Response {
     }
 
     private static final CoapOption[] optionsForUrl(String url) {
-        String[] paths = url.split("/");
-        CoapOption[] opt = new CoapOption[paths.length];
+        String[] parts = url.split("\\?");
+
+        String[] paths = parts[0].split("\\/");
+
+        String[] params = new String[] {};
+
+        if (parts.length > 1) {
+            params = parts[1].split("\\,");
+        }
+        CoapOption[] opt = new CoapOption[paths.length + params.length];
         for (int i = 0; i < paths.length; i++) {
             try {
                 opt[i] = new CoapOption(CoapOptionType.URI_PATH, paths[i].getBytes("UTF-8"));
@@ -55,6 +63,15 @@ public class CoapMessage implements Request, Response {
                 throw new IllegalStateException(e);
             }
         }
+
+        for (int i = 0; i < params.length; i++) {
+            try {
+                opt[paths.length + i] = new CoapOption(CoapOptionType.URI_QUERY, params[i].getBytes("UTF-8"));
+            } catch (UnsupportedEncodingException e) {
+                throw new IllegalStateException(e);
+            }
+        }
+
         return opt;
     }
 

http://git-wip-us.apache.org/repos/asf/mina/blob/08d2ac72/coap/src/main/java/org/apache/mina/coap/resource/ResourceHandler.java
----------------------------------------------------------------------
diff --git a/coap/src/main/java/org/apache/mina/coap/resource/ResourceHandler.java b/coap/src/main/java/org/apache/mina/coap/resource/ResourceHandler.java
index a79f227..0db497c 100644
--- a/coap/src/main/java/org/apache/mina/coap/resource/ResourceHandler.java
+++ b/coap/src/main/java/org/apache/mina/coap/resource/ResourceHandler.java
@@ -19,6 +19,7 @@
  */
 package org.apache.mina.coap.resource;
 
+import org.apache.mina.api.IoSession;
 import org.apache.mina.coap.CoapMessage;
 
 /**
@@ -53,7 +54,8 @@ public interface ResourceHandler {
      * Generate the response for this request.
      * 
      * @param request the request to serve
+     * @param session the session which receive the request
      * @return the response
      */
-    public CoapResponse handle(CoapMessage request);
+    public CoapResponse handle(CoapMessage request, IoSession session);
 }

http://git-wip-us.apache.org/repos/asf/mina/blob/08d2ac72/coap/src/main/java/org/apache/mina/coap/resource/ResourceRegistry.java
----------------------------------------------------------------------
diff --git a/coap/src/main/java/org/apache/mina/coap/resource/ResourceRegistry.java b/coap/src/main/java/org/apache/mina/coap/resource/ResourceRegistry.java
index dd14e09..e14b34f 100644
--- a/coap/src/main/java/org/apache/mina/coap/resource/ResourceRegistry.java
+++ b/coap/src/main/java/org/apache/mina/coap/resource/ResourceRegistry.java
@@ -23,6 +23,7 @@ import java.io.UnsupportedEncodingException;
 import java.util.HashMap;
 import java.util.Map;
 
+import org.apache.mina.api.IoSession;
 import org.apache.mina.coap.CoapCode;
 import org.apache.mina.coap.CoapMessage;
 import org.apache.mina.coap.CoapOption;
@@ -59,7 +60,7 @@ public class ResourceRegistry {
      * @param request the request ot serve
      * @return the response
      */
-    public CoapMessage respond(CoapMessage request) {
+    public CoapMessage respond(CoapMessage request, IoSession session) {
         // find the URI
         StringBuilder urlBuilder = new StringBuilder("");
         for (CoapOption opt : request.getOptions()) {
@@ -93,7 +94,7 @@ public class ResourceRegistry {
                         request.getToken(), new CoapOption[] { new CoapOption(CoapOptionType.CONTENT_FORMAT,
                                 new byte[] { 0 }) }, "not found !".getBytes());
             } else {
-                CoapResponse response = handler.handle(request);
+                CoapResponse response = handler.handle(request, session);
                 return new CoapMessage(1, request.getType() == MessageType.CONFIRMABLE ? MessageType.ACK
                         : MessageType.NON_CONFIRMABLE, response.getCode(), request.getId(), request.getToken(),
                         response.getOptions(), response.getContent());

http://git-wip-us.apache.org/repos/asf/mina/blob/08d2ac72/coap/src/test/java/org/apache/mina/coap/resource/ResourceRegistryTest.java
----------------------------------------------------------------------
diff --git a/coap/src/test/java/org/apache/mina/coap/resource/ResourceRegistryTest.java b/coap/src/test/java/org/apache/mina/coap/resource/ResourceRegistryTest.java
index 767811a..11eefda 100644
--- a/coap/src/test/java/org/apache/mina/coap/resource/ResourceRegistryTest.java
+++ b/coap/src/test/java/org/apache/mina/coap/resource/ResourceRegistryTest.java
@@ -21,6 +21,7 @@ package org.apache.mina.coap.resource;
 
 import static org.junit.Assert.*;
 
+import org.apache.mina.api.IoSession;
 import org.apache.mina.coap.CoapCode;
 import org.apache.mina.coap.CoapMessage;
 import org.apache.mina.coap.CoapOption;
@@ -39,7 +40,7 @@ public class ResourceRegistryTest {
         ResourceRegistry reg = new ResourceRegistry();
         CoapMessage msg = new CoapMessage(1, MessageType.CONFIRMABLE, CoapCode.GET.getCode(), 123, null,
                 new CoapOption[] { new CoapOption(CoapOptionType.URI_PATH, "test".getBytes()) }, new byte[] {});
-        CoapMessage resp = reg.respond(msg);
+        CoapMessage resp = reg.respond(msg, null);
         assertEquals(1, resp.getVersion());
         assertEquals(CoapCode.NOT_FOUND.getCode(), resp.getCode());
         assertArrayEquals(new CoapOption[] { new CoapOption(CoapOptionType.CONTENT_FORMAT, new byte[] { 0 }) },
@@ -53,7 +54,7 @@ public class ResourceRegistryTest {
         ResourceHandler handler = new AbstractResourceHandler() {
 
             @Override
-            public CoapResponse handle(CoapMessage request) {
+            public CoapResponse handle(CoapMessage request, IoSession session) {
                 return new CoapResponse(12345, "bla bla".getBytes(), new CoapOption[] {});
             }
 
@@ -67,14 +68,14 @@ public class ResourceRegistryTest {
         // 4.04 on bad path
         CoapMessage msg = new CoapMessage(1, MessageType.CONFIRMABLE, CoapCode.GET.getCode(), 123, null,
                 new CoapOption[] { new CoapOption(CoapOptionType.URI_PATH, "meh".getBytes()) }, new byte[] {});
-        CoapMessage resp = reg.respond(msg);
+        CoapMessage resp = reg.respond(msg, null);
         assertEquals(CoapCode.NOT_FOUND.getCode(), resp.getCode());
 
         // on correct path the 2.02 with the response
         msg = new CoapMessage(1, MessageType.CONFIRMABLE, CoapCode.GET.getCode(), 123, null, new CoapOption[] {
                                 new CoapOption(CoapOptionType.URI_PATH, "myTest".getBytes()),
                                 new CoapOption(CoapOptionType.URI_PATH, "Path".getBytes()) }, new byte[] {});
-        resp = reg.respond(msg);
+        resp = reg.respond(msg, null);
         assertEquals(1, resp.getVersion());
         assertEquals(12345, resp.getCode());
         assertArrayEquals(new CoapOption[] {}, resp.getOptions());

http://git-wip-us.apache.org/repos/asf/mina/blob/08d2ac72/core/src/main/java/org/apache/mina/filter/query/RequestFilter.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/mina/filter/query/RequestFilter.java b/core/src/main/java/org/apache/mina/filter/query/RequestFilter.java
index 963bea1..5539b89 100644
--- a/core/src/main/java/org/apache/mina/filter/query/RequestFilter.java
+++ b/core/src/main/java/org/apache/mina/filter/query/RequestFilter.java
@@ -57,10 +57,12 @@ import org.apache.mina.session.AttributeKey;
 public class RequestFilter<REQUEST extends Request, RESPONSE extends Response> extends AbstractIoFilter {
 
     /**
+     * Send a request message and provide a {@link IoFuture} for handling the response. WARNING : for now timeout
+     * doesn't work (WIP).
      * 
-     * @param session
-     * @param request
-     * @param timeoutInMs
+     * @param session the session where to write the request
+     * @param request the request to be issued
+     * @param timeoutInMs the timeout in milli-seconds (doesn't work Work-in-progress).
      * @return
      */
     @SuppressWarnings({ "rawtypes", "unchecked" })
@@ -102,15 +104,15 @@ public class RequestFilter<REQUEST extends Request, RESPONSE extends Response> e
             }
         }
 
-        // check for timeout
-        long now = System.currentTimeMillis();
-        if (lastTimeoutCheck + 1000 < now) {
-            lastTimeoutCheck = now;
-            Map<?, ?> inFlight = session.getAttribute(IN_FLIGHT_REQUESTS);
-            for (Object v : inFlight.values()) {
-                ((RequestFuture<?, ?>) v).timeoutIfNeeded(now);
-            }
-        }
+        // // check for timeout
+        // long now = System.currentTimeMillis();
+        // if (lastTimeoutCheck + 1000 < now) {
+        // lastTimeoutCheck = now;
+        // Map<?, ?> inFlight = session.getAttribute(IN_FLIGHT_REQUESTS);
+        // for (Object v : inFlight.values()) {
+        // ((RequestFuture<?, ?>) v).timeoutIfNeeded(now);
+        // }
+        // }
         // trigger the next filter
         super.messageReceived(session, message, controller);
     }
@@ -118,14 +120,14 @@ public class RequestFilter<REQUEST extends Request, RESPONSE extends Response> e
     @Override
     public void messageSent(IoSession session, Object message) {
         // check for timeout
-        long now = System.currentTimeMillis();
-        if (lastTimeoutCheck + 1000 < now) {
-            lastTimeoutCheck = now;
-            Map<?, ?> inFlight = session.getAttribute(IN_FLIGHT_REQUESTS);
-            for (Object v : inFlight.values()) {
-                ((RequestFuture<?, ?>) v).timeoutIfNeeded(now);
-            }
-        }
+        // long now = System.currentTimeMillis();
+        // if (lastTimeoutCheck + 1000 < now) {
+        // lastTimeoutCheck = now;
+        // Map<?, ?> inFlight = session.getAttribute(IN_FLIGHT_REQUESTS);
+        // for (Object v : inFlight.values()) {
+        // ((RequestFuture<?, ?>) v).timeoutIfNeeded(now);
+        // }
+        // }
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/mina/blob/08d2ac72/core/src/test/java/org/apache/mina/filter/query/RequestFilterTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/mina/filter/query/RequestFilterTest.java b/core/src/test/java/org/apache/mina/filter/query/RequestFilterTest.java
index 588e021..50e0dd3 100644
--- a/core/src/test/java/org/apache/mina/filter/query/RequestFilterTest.java
+++ b/core/src/test/java/org/apache/mina/filter/query/RequestFilterTest.java
@@ -101,13 +101,11 @@ public class RequestFilterTest {
         rq.messageReceived(session, r, ctl);
 
         // verify
-        verify(session, times(2)).getAttribute(RequestFilter.IN_FLIGHT_REQUESTS);
+        verify(session).getAttribute(RequestFilter.IN_FLIGHT_REQUESTS);
         verify(m).remove("ID");
         verify(r).requestId();
         verify(f).complete(r);
 
-        verify(m).values();
-
         verify(ctl).callReadNextFilter(r);
         verifyNoMoreInteractions(r, m, session, f, ctl);
     }

http://git-wip-us.apache.org/repos/asf/mina/blob/08d2ac72/examples/src/main/java/org/apache/mina/examples/coap/CoapClient.java
----------------------------------------------------------------------
diff --git a/examples/src/main/java/org/apache/mina/examples/coap/CoapClient.java b/examples/src/main/java/org/apache/mina/examples/coap/CoapClient.java
new file mode 100644
index 0000000..4a5cfe0
--- /dev/null
+++ b/examples/src/main/java/org/apache/mina/examples/coap/CoapClient.java
@@ -0,0 +1,148 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ *
+ */
+package org.apache.mina.examples.coap;
+
+import java.net.InetSocketAddress;
+import java.nio.ByteBuffer;
+
+import org.apache.mina.api.AbstractIoFutureListener;
+import org.apache.mina.api.AbstractIoHandler;
+import org.apache.mina.api.IoFuture;
+import org.apache.mina.api.IoSession;
+import org.apache.mina.coap.CoapCode;
+import org.apache.mina.coap.CoapMessage;
+import org.apache.mina.coap.codec.CoapDecoder;
+import org.apache.mina.coap.codec.CoapEncoder;
+import org.apache.mina.coap.resource.AbstractResourceHandler;
+import org.apache.mina.coap.resource.CoapResponse;
+import org.apache.mina.coap.resource.ResourceRegistry;
+import org.apache.mina.filter.codec.ProtocolCodecFilter;
+import org.apache.mina.filter.query.RequestFilter;
+import org.apache.mina.transport.nio.NioUdpClient;
+
+/**
+ * 
+ * A CoAP client, accepting "piggy-backed" request and behaving like a server too.
+ */
+public class CoapClient {
+
+    static final ResourceRegistry reg = new ResourceRegistry();
+
+    public static void main(String[] args) {
+
+        final String status = "status message";
+        System.err.println(status.length());
+
+        final RequestFilter<CoapMessage, CoapMessage> rq = new RequestFilter<CoapMessage, CoapMessage>();
+
+        NioUdpClient client = new NioUdpClient();
+        client.setFilters( //
+                new ProtocolCodecFilter<CoapMessage, ByteBuffer, Void, Void>( //
+                        new CoapEncoder(), new CoapDecoder() //
+                ), rq);
+
+        client.setIoHandler(new Handler());
+
+        reg.register(new AbstractResourceHandler() {
+
+            @Override
+            public CoapResponse handle(CoapMessage request, IoSession session) {
+                if (request.getCode() == CoapCode.GET.getCode()) {
+                    return new CoapResponse(CoapCode.CONTENT.getCode(), status.getBytes());
+                } else {
+                    return new CoapResponse(CoapCode.METHOD_NOT_ALLOWED.getCode(), null);
+                }
+            }
+
+            @Override
+            public String getTittle() {
+                return "Status report";
+            }
+
+            @Override
+            public String getPath() {
+                return "st";
+            }
+
+        });
+
+        IoFuture<IoSession> cf = client.connect(new InetSocketAddress(args[0], Integer.parseInt(args[1])));
+
+        // register on connection
+        cf.register(new AbstractIoFutureListener<IoSession>() {
+
+            @Override
+            public void completed(IoSession session) {
+                IoFuture<CoapMessage> response = rq.request(session,
+                        CoapMessage.post("register?id=1234567890ABCDEF", true, "true".getBytes()), 10000);
+                response.register(new AbstractIoFutureListener<CoapMessage>() {
+                    @Override
+                    public void completed(CoapMessage result) {
+                        if (result.getCode() == CoapCode.CREATED.getCode()) {
+                            System.err.println("registered !" + result);
+                        } else {
+                            System.err.println("registration error : " + result.getCode());
+                        }
+                    }
+                });
+            }
+        });
+
+        try {
+            Thread.sleep(50000);
+        } catch (InterruptedException e) {
+            e.printStackTrace();
+        }
+
+    }
+
+    private static class Handler extends AbstractIoHandler {
+
+        @Override
+        public void messageReceived(IoSession session, Object message) {
+
+            System.err.println("rcvd : " + message);
+            CoapMessage msg = (CoapMessage) message;
+            if (msg.getCode() == CoapCode.GET.getCode() || msg.getCode() == CoapCode.POST.getCode()
+                    || msg.getCode() == CoapCode.PUT.getCode() || msg.getCode() == CoapCode.DELETE.getCode()) {
+                CoapMessage resp = reg.respond(msg, session);
+                session.write(resp);
+            }
+        }
+
+        @Override
+        public void messageSent(IoSession session, Object message) {
+            System.err.println("sent : " + message);
+        }
+
+        @Override
+        public void exceptionCaught(IoSession session, Exception cause) {
+            System.err.println("exception !");
+            cause.printStackTrace();
+
+            try {
+                Thread.sleep(200);
+            } catch (InterruptedException e) {
+                e.printStackTrace();
+            }
+            session.close(true);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/mina/blob/08d2ac72/examples/src/main/java/org/apache/mina/examples/coap/CoapGetServer.java
----------------------------------------------------------------------
diff --git a/examples/src/main/java/org/apache/mina/examples/coap/CoapGetServer.java b/examples/src/main/java/org/apache/mina/examples/coap/CoapGetServer.java
deleted file mode 100644
index 286c927..0000000
--- a/examples/src/main/java/org/apache/mina/examples/coap/CoapGetServer.java
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- *
- */
-package org.apache.mina.examples.coap;
-
-import java.nio.ByteBuffer;
-
-import org.apache.mina.api.AbstractIoHandler;
-import org.apache.mina.api.IdleStatus;
-import org.apache.mina.api.IoSession;
-import org.apache.mina.coap.CoapCode;
-import org.apache.mina.coap.CoapMessage;
-import org.apache.mina.coap.CoapOption;
-import org.apache.mina.coap.CoapOptionType;
-import org.apache.mina.coap.codec.CoapDecoder;
-import org.apache.mina.coap.codec.CoapEncoder;
-import org.apache.mina.coap.resource.AbstractResourceHandler;
-import org.apache.mina.coap.resource.CoapResponse;
-import org.apache.mina.coap.resource.ResourceRegistry;
-import org.apache.mina.filter.codec.ProtocolCodecFilter;
-import org.apache.mina.transport.bio.BioUdpServer;
-
-/**
- * A CoAP UDP server serving some resources.
- * 
- * @author <a href="http://mina.apache.org">Apache MINA Project</a>
- */
-public class CoapGetServer {
-
-    public static void main(String[] args) {
-
-        // create a CoAP resource registry
-        final ResourceRegistry reg = new ResourceRegistry();
-
-        reg.register(new AbstractResourceHandler() {
-
-            @Override
-            public String getPath() {
-                return "demo";
-            }
-
-            @Override
-            public CoapResponse handle(CoapMessage request) {
-                return new CoapResponse(CoapCode.CONTENT.getCode(), "niah niah niah niah niah\n niah niah niah\n"
-                        .getBytes(), new CoapOption(CoapOptionType.CONTENT_FORMAT, new byte[] { 0 }));
-            }
-
-            @Override
-            public String getTittle() {
-                return "Some demo resource";
-            }
-
-        });
-        BioUdpServer server = new BioUdpServer();
-        server.setFilters(/* new LoggingFilter(), */new ProtocolCodecFilter<CoapMessage, ByteBuffer, Void, Void>(
-                new CoapEncoder(), new CoapDecoder()));
-        server.getSessionConfig().setIdleTimeInMillis(IdleStatus.READ_IDLE, 20000);
-        server.setIoHandler(new AbstractIoHandler() {
-
-            long start = System.currentTimeMillis();
-            int count = 0;
-
-            @Override
-            public void messageReceived(IoSession session, Object message) {
-                // System.err.println("rcv : " + message);
-
-                CoapMessage resp = reg.respond((CoapMessage) message);
-                // System.err.println("resp : " + resp);
-                session.write(resp);
-                count++;
-                if (count >= 100000) {
-                    System.err.println("time for 100k msg : " + (System.currentTimeMillis() - start));
-                    count = 0;
-                    start = System.currentTimeMillis();
-                }
-            }
-
-            @Override
-            public void sessionIdle(IoSession session, IdleStatus status) {
-                System.err.println("idle closing");
-                session.close(false);
-            }
-        });
-
-        try {
-            server.bind(5683);
-            for (;;) {
-                Thread.sleep(1000);
-            }
-        } catch (InterruptedException e) {
-            e.printStackTrace();
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/mina/blob/08d2ac72/examples/src/main/java/org/apache/mina/examples/coap/CoapServer.java
----------------------------------------------------------------------
diff --git a/examples/src/main/java/org/apache/mina/examples/coap/CoapServer.java b/examples/src/main/java/org/apache/mina/examples/coap/CoapServer.java
new file mode 100644
index 0000000..24da802
--- /dev/null
+++ b/examples/src/main/java/org/apache/mina/examples/coap/CoapServer.java
@@ -0,0 +1,181 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ *
+ */
+package org.apache.mina.examples.coap;
+
+import java.io.UnsupportedEncodingException;
+import java.nio.ByteBuffer;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.apache.mina.api.AbstractIoFutureListener;
+import org.apache.mina.api.AbstractIoHandler;
+import org.apache.mina.api.IdleStatus;
+import org.apache.mina.api.IoSession;
+import org.apache.mina.coap.CoapCode;
+import org.apache.mina.coap.CoapMessage;
+import org.apache.mina.coap.CoapOption;
+import org.apache.mina.coap.CoapOptionType;
+import org.apache.mina.coap.codec.CoapDecoder;
+import org.apache.mina.coap.codec.CoapEncoder;
+import org.apache.mina.coap.resource.AbstractResourceHandler;
+import org.apache.mina.coap.resource.CoapResponse;
+import org.apache.mina.coap.resource.ResourceRegistry;
+import org.apache.mina.filter.codec.ProtocolCodecFilter;
+import org.apache.mina.filter.query.RequestFilter;
+import org.apache.mina.transport.bio.BioUdpServer;
+
+/**
+ * A CoAP UDP server serving some resources.
+ * 
+ * @author <a href="http://mina.apache.org">Apache MINA Project</a>
+ */
+public class CoapServer {
+
+    public static void main(String[] args) {
+
+        final Map<String, IoSession> registration = new ConcurrentHashMap<String, IoSession>();
+
+        // create a CoAP resource registry
+        final ResourceRegistry reg = new ResourceRegistry();
+
+        reg.register(new AbstractResourceHandler() {
+
+            @Override
+            public String getPath() {
+                return "demo";
+            }
+
+            @Override
+            public CoapResponse handle(CoapMessage request, IoSession session) {
+                return new CoapResponse(CoapCode.CONTENT.getCode(), "niah niah niah niah niah\n niah niah niah\n"
+                        .getBytes(), new CoapOption(CoapOptionType.CONTENT_FORMAT, new byte[] { 0 }));
+            }
+
+            @Override
+            public String getTittle() {
+                return "Some demo resource";
+            }
+
+        });
+
+        reg.register(new AbstractResourceHandler() {
+
+            @Override
+            public CoapResponse handle(CoapMessage request, IoSession session) {
+                String device = null;
+                try {
+                    for (CoapOption o : request.getOptions()) {
+                        if (o.getType() == CoapOptionType.URI_QUERY) {
+                            String qr = new String(o.getData(), "UTF-8");
+                            if (qr.startsWith("id=")) {
+                                device = qr.substring(2);
+                            }
+                        }
+                    }
+                    if (device != null) {
+                        registration.put(device, session);
+                        return new CoapResponse(CoapCode.CREATED.getCode(), null);
+                    } else {
+                        return new CoapResponse(CoapCode.BAD_REQUEST.getCode(), "no id=xxx parameter".getBytes("UTF-8"));
+                    }
+                } catch (UnsupportedEncodingException e) {
+                    throw new IllegalStateException("no UTF-8 in the JVM", e);
+                }
+            }
+
+            @Override
+            public String getPath() {
+                return "register";
+            }
+        });
+
+        BioUdpServer server = new BioUdpServer();
+        final RequestFilter<CoapMessage, CoapMessage> rq = new RequestFilter<CoapMessage, CoapMessage>();
+
+        server.setFilters(/* new LoggingFilter(), */new ProtocolCodecFilter<CoapMessage, ByteBuffer, Void, Void>(
+                new CoapEncoder(), new CoapDecoder()), rq);
+        // idle in 10 minute
+        server.getSessionConfig().setIdleTimeInMillis(IdleStatus.READ_IDLE, 10 * 60 * 1000);
+        server.setIoHandler(new AbstractIoHandler() {
+
+            long start = System.currentTimeMillis();
+            int count = 0;
+
+            @Override
+            public void messageReceived(IoSession session, Object message) {
+                System.err.println("rcv : " + message);
+
+                CoapMessage resp = reg.respond((CoapMessage) message, session);
+                System.err.println("resp : " + resp);
+                session.write(resp);
+                count++;
+                if (count >= 100000) {
+                    System.err.println("time for 100k msg : " + (System.currentTimeMillis() - start));
+                    count = 0;
+                    start = System.currentTimeMillis();
+                }
+            }
+
+            @Override
+            public void messageSent(IoSession session, Object message) {
+                System.err.println("sent : " + message);
+            }
+
+            @Override
+            public void sessionIdle(IoSession session, IdleStatus status) {
+                System.err.println("idle closing");
+                session.close(false);
+            }
+        });
+
+        try {
+            server.bind(5683);
+            new Thread() {
+                @Override
+                public void run() {
+                    for (;;) {
+                        for (IoSession s : registration.values()) {
+                            rq.request(s, CoapMessage.get("st", true), 15000).register(
+                                    new AbstractIoFutureListener<CoapMessage>() {
+                                        @Override
+                                        public void completed(CoapMessage result) {
+                                            System.err.println("status : " + result);
+                                        }
+                                    });
+                        }
+
+                        try {
+                            // let's poll every 10 seconds
+                            Thread.sleep(10000);
+                        } catch (InterruptedException e) {
+                            break;
+                        }
+                    }
+                }
+            }.start();
+
+            for (;;) {
+                Thread.sleep(1000);
+            }
+        } catch (InterruptedException e) {
+            e.printStackTrace();
+        }
+    }
+}