Fix keep-alive to filter correctly.
[iotivity.git] / cloud / stack / src / main / java / org / iotivity / cloud / base / ServerSystem.java
1 /*
2  * //******************************************************************
3  * //
4  * // Copyright 2016 Samsung Electronics All Rights Reserved.
5  * //
6  * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
7  * //
8  * // Licensed under the Apache License, Version 2.0 (the "License");
9  * // you may not use this file except in compliance with the License.
10  * // You may obtain a copy of the License at
11  * //
12  * //      http://www.apache.org/licenses/LICENSE-2.0
13  * //
14  * // Unless required by applicable law or agreed to in writing, software
15  * // distributed under the License is distributed on an "AS IS" BASIS,
16  * // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * // See the License for the specific language governing permissions and
18  * // limitations under the License.
19  * //
20  * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
21  */
22 package org.iotivity.cloud.base;
23
24 import java.util.ArrayList;
25 import java.util.List;
26
27 import org.iotivity.cloud.base.connector.CoapClient;
28 import org.iotivity.cloud.base.device.CoapDevice;
29 import org.iotivity.cloud.base.device.Device;
30 import org.iotivity.cloud.base.device.IRequestChannel;
31 import org.iotivity.cloud.base.exception.ClientException;
32 import org.iotivity.cloud.base.exception.ServerException;
33 import org.iotivity.cloud.base.exception.ServerException.InternalServerErrorException;
34 import org.iotivity.cloud.base.protocols.MessageBuilder;
35 import org.iotivity.cloud.base.protocols.coap.CoapMessage;
36 import org.iotivity.cloud.base.protocols.coap.CoapRequest;
37 import org.iotivity.cloud.base.protocols.coap.CoapResponse;
38 import org.iotivity.cloud.base.protocols.enums.ResponseStatus;
39 import org.iotivity.cloud.base.resource.ResourceManager;
40 import org.iotivity.cloud.base.server.CoapServer;
41 import org.iotivity.cloud.base.server.HttpServer;
42 import org.iotivity.cloud.base.server.Server;
43 import org.iotivity.cloud.util.Log;
44
45 import io.netty.channel.ChannelDuplexHandler;
46 import io.netty.channel.ChannelHandler.Sharable;
47 import io.netty.channel.ChannelHandlerContext;
48 import io.netty.channel.SimpleChannelInboundHandler;
49 import io.netty.util.AttributeKey;
50
51 public class ServerSystem extends ResourceManager {
52     private List<Server>                  mServerList = new ArrayList<>();
53     protected static AttributeKey<Device> keyDevice   = AttributeKey
54             .newInstance("device");
55
56     @Sharable
57     public class PersistentPacketReceiver
58             extends SimpleChannelInboundHandler<CoapMessage> {
59         @Override
60         public void channelActive(ChannelHandlerContext ctx) {
61
62             StringBuilder deviceId = new StringBuilder(
63                     ctx.channel().id().asLongText().substring(26));
64             deviceId.deleteCharAt(25);
65             deviceId.insert(13, '-');
66             deviceId.insert(18, '-');
67             deviceId.insert(23, '-');
68             CoapDevice device = new CoapDevice(ctx);
69             device.updateDevice(deviceId.toString(), null, null);
70             ctx.channel().attr(keyDevice).set(device);
71
72             device.onConnected();
73         }
74
75         @Override
76         protected void channelRead0(ChannelHandlerContext ctx,
77                 CoapMessage msg) {
78             try {
79                 // Find proper device and raise event.
80                 Device targetDevice = ctx.channel().attr(keyDevice).get();
81
82                 if (targetDevice == null) {
83                     throw new InternalServerErrorException(
84                             "Unable to find device");
85                 }
86
87                 if (msg instanceof CoapRequest) {
88                     onRequestReceived(targetDevice, (CoapRequest) msg);
89                 } else if (msg instanceof CoapResponse) {
90                     // TODO: Re-architecturing required
91                     IRequestChannel reqChannel = ((CoapDevice) targetDevice)
92                             .getRequestChannel();
93                     CoapClient coapClient = (CoapClient) reqChannel;
94                     coapClient.onResponseReceived(msg);
95                 }
96
97             } catch (ServerException e) {
98                 ctx.writeAndFlush(MessageBuilder.createResponse(msg,
99                         e.getErrorResponse()));
100                 Log.f(ctx.channel(), e);
101             } catch (ClientException e) {
102                 Log.f(ctx.channel(), e);
103             } catch (Throwable t) {
104                 Log.f(ctx.channel(), t);
105                 if (msg instanceof CoapRequest) {
106                     ctx.writeAndFlush(MessageBuilder.createResponse(msg,
107                             ResponseStatus.INTERNAL_SERVER_ERROR));
108                 }
109             }
110         }
111
112         @Override
113         public void channelInactive(ChannelHandlerContext ctx)
114                 throws Exception {
115             Device device = ctx.channel().attr(keyDevice).get();
116             device.onDisconnected();
117             ctx.channel().attr(keyDevice).remove();
118         }
119     }
120
121     @Sharable
122     public class NonPersistentPacketReceiver extends ChannelDuplexHandler {
123         @Override
124         public void channelActive(ChannelHandlerContext ctx) throws Exception {
125             // onDeviceConnected(ctx)
126         }
127
128         @Override
129         public void channelRead(ChannelHandlerContext ctx, Object msg)
130                 throws Exception {
131             // Find proper device and raise event.
132             // onRequestReceived(new Device(ctx), msg);
133         }
134     }
135
136     public void addServer(Server server) {
137         if (server instanceof CoapServer) {
138             server.addHandler(new PersistentPacketReceiver());
139         }
140
141         if (server instanceof HttpServer) {
142             server.addHandler(new NonPersistentPacketReceiver());
143         }
144         mServerList.add(server);
145     }
146
147     public void startSystem(boolean tlsMode) throws Exception {
148         for (Server server : mServerList) {
149             server.startServer(tlsMode);
150         }
151     }
152
153     public void stopSystem() throws Exception {
154         for (Server server : mServerList) {
155             server.stopServer();
156         }
157     }
158 }