View Javadoc

1   /*
2    *  Licensed to the Apache Software Foundation (ASF) under one
3    *  or more contributor license agreements.  See the NOTICE file
4    *  distributed with this work for additional information
5    *  regarding copyright ownership.  The ASF licenses this file
6    *  to you under the Apache License, Version 2.0 (the
7    *  "License"); you may not use this file except in compliance
8    *  with the License.  You may obtain a copy of the License at
9    *
10   *    http://www.apache.org/licenses/LICENSE-2.0
11   *
12   *  Unless required by applicable law or agreed to in writing,
13   *  software distributed under the License is distributed on an
14   *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   *  KIND, either express or implied.  See the License for the
16   *  specific language governing permissions and limitations
17   *  under the License.
18   *
19   */
20  package org.apache.mina.examples.coap;
21  
22  import java.io.UnsupportedEncodingException;
23  import java.nio.ByteBuffer;
24  import java.util.Map;
25  import java.util.concurrent.ConcurrentHashMap;
26  
27  import org.apache.mina.api.AbstractIoFutureListener;
28  import org.apache.mina.api.AbstractIoHandler;
29  import org.apache.mina.api.IdleStatus;
30  import org.apache.mina.api.IoSession;
31  import org.apache.mina.coap.CoapCode;
32  import org.apache.mina.coap.CoapMessage;
33  import org.apache.mina.coap.CoapOption;
34  import org.apache.mina.coap.CoapOptionType;
35  import org.apache.mina.coap.codec.CoapDecoder;
36  import org.apache.mina.coap.codec.CoapEncoder;
37  import org.apache.mina.coap.resource.AbstractResourceHandler;
38  import org.apache.mina.coap.resource.CoapResponse;
39  import org.apache.mina.coap.resource.ResourceRegistry;
40  import org.apache.mina.filter.codec.ProtocolCodecFilter;
41  import org.apache.mina.filter.query.RequestFilter;
42  import org.apache.mina.transport.bio.BioUdpServer;
43  
44  /**
45   * A CoAP UDP server serving some resources.
46   * 
47   * @author <a href="http://mina.apache.org">Apache MINA Project</a>
48   */
49  public class CoapServer {
50  
51      public static void main(String[] args) {
52  
53          final Map<String, IoSession> registration = new ConcurrentHashMap<>();
54  
55          // create a CoAP resource registry
56          final ResourceRegistry reg = new ResourceRegistry();
57  
58          reg.register(new AbstractResourceHandler() {
59  
60              @Override
61              public String getPath() {
62                  return "demo";
63              }
64  
65              @Override
66              public CoapResponse handle(CoapMessage request, IoSession session) {
67                  return new CoapResponse(CoapCode.CONTENT.getCode(), "niah niah niah niah niah\n niah niah niah\n"
68                          .getBytes(), new CoapOption(CoapOptionType.CONTENT_FORMAT, new byte[] { 0 }));
69              }
70  
71              @Override
72              public String getTittle() {
73                  return "Some demo resource";
74              }
75  
76          });
77  
78          reg.register(new AbstractResourceHandler() {
79  
80              @Override
81              public CoapResponse handle(CoapMessage request, IoSession session) {
82                  String device = null;
83                  try {
84                      for (CoapOption o : request.getOptions()) {
85                          if (o.getType() == CoapOptionType.URI_QUERY) {
86                              String qr = new String(o.getData(), "UTF-8");
87                              if (qr.startsWith("id=")) {
88                                  device = qr.substring(2);
89                              }
90                          }
91                      }
92                      if (device != null) {
93                          registration.put(device, session);
94                          return new CoapResponse(CoapCode.CREATED.getCode(), null);
95                      } else {
96                          return new CoapResponse(CoapCode.BAD_REQUEST.getCode(), "no id=xxx parameter".getBytes("UTF-8"));
97                      }
98                  } catch (UnsupportedEncodingException e) {
99                      throw new IllegalStateException("no UTF-8 in the JVM", e);
100                 }
101             }
102 
103             @Override
104             public String getPath() {
105                 return "register";
106             }
107         });
108 
109         BioUdpServer server = new BioUdpServer();
110         final RequestFilter<CoapMessage, CoapMessage> rq = new RequestFilter<>();
111 
112         server.setFilters(new ProtocolCodecFilter<CoapMessage, ByteBuffer, Void, Void>(
113                 new CoapEncoder(), new CoapDecoder()), rq);
114         // idle in 10 minute
115         server.getSessionConfig().setIdleTimeInMillis(IdleStatus.READ_IDLE, 60 * 10_000);
116         server.setIoHandler(new AbstractIoHandler() {
117 
118             long start = System.currentTimeMillis();
119             int count = 0;
120 
121             @Override
122             public void messageReceived(IoSession session, Object message) {
123                 System.err.println("rcv : " + message);
124 
125                 CoapMessage resp = reg.respond((CoapMessage) message, session);
126                 System.err.println("resp : " + resp);
127                 session.write(resp);
128                 count++;
129                 if (count >= 100_000) {
130                     System.err.println("time for 100k msg : " + (System.currentTimeMillis() - start));
131                     count = 0;
132                     start = System.currentTimeMillis();
133                 }
134             }
135 
136             @Override
137             public void messageSent(IoSession session, Object message) {
138                 System.err.println("sent : " + message);
139             }
140 
141             @Override
142             public void sessionIdle(IoSession session, IdleStatus status) {
143                 System.err.println("idle closing");
144                 session.close(false);
145             }
146         });
147 
148         try {
149             server.bind(5683);
150             new Thread() {
151                 @Override
152                 public void run() {
153                     for (;;) {
154                         for (IoSession s : registration.values()) {
155                             rq.request(s, CoapMessage.get("st", true), 15_000).register(
156                                     new AbstractIoFutureListener<CoapMessage>() {
157                                         @Override
158                                         public void completed(CoapMessage result) {
159                                             System.err.println("status : " + result);
160                                         }
161                                     });
162                         }
163 
164                         try {
165                             // let's poll every 10 seconds
166                             Thread.sleep(10_000);
167                         } catch (InterruptedException e) {
168                             break;
169                         }
170                     }
171                 }
172             }.start();
173 
174             for (;;) {
175                 Thread.sleep(1_000);
176             }
177         } catch (InterruptedException e) {
178             e.printStackTrace();
179         }
180     }
181 }