bba5344b8a29ed6b48dc90dbab7b0789a4f56c95
[iotivity.git] / cloud / stack / src / main / java / org / iotivity / cloud / base / connector / CoapConnector.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.connector;
23
24 import java.io.File;
25 import java.net.InetSocketAddress;
26 import java.util.ArrayList;
27 import java.util.HashMap;
28 import java.util.List;
29
30 import javax.net.ssl.SSLException;
31
32 import org.iotivity.cloud.base.OCFConstants;
33 import org.iotivity.cloud.base.protocols.coap.CoapDecoder;
34 import org.iotivity.cloud.base.protocols.coap.CoapEncoder;
35 import org.iotivity.cloud.base.protocols.coap.CoapLogHandler;
36 import org.iotivity.cloud.base.protocols.coap.CoapResponse;
37
38 import io.netty.bootstrap.Bootstrap;
39 import io.netty.channel.Channel;
40 import io.netty.channel.ChannelFuture;
41 import io.netty.channel.ChannelHandler;
42 import io.netty.channel.ChannelHandler.Sharable;
43 import io.netty.channel.ChannelHandlerContext;
44 import io.netty.channel.ChannelInitializer;
45 import io.netty.channel.ChannelOption;
46 import io.netty.channel.ChannelPipeline;
47 import io.netty.channel.EventLoopGroup;
48 import io.netty.channel.SimpleChannelInboundHandler;
49 import io.netty.channel.nio.NioEventLoopGroup;
50 import io.netty.channel.socket.SocketChannel;
51 import io.netty.channel.socket.nio.NioSocketChannel;
52 import io.netty.handler.ssl.SslContext;
53 import io.netty.handler.ssl.SslContextBuilder;
54 import io.netty.handler.ssl.SslProvider;
55
56 public class CoapConnector {
57
58     public CoapConnector() {
59
60         mBootstrap.group(mConnectorGroup);
61         mBootstrap.channel(NioSocketChannel.class);
62         mBootstrap.option(ChannelOption.TCP_NODELAY, true);
63         mBootstrap.option(ChannelOption.SO_KEEPALIVE, true);
64         mBootstrap.option(ChannelOption.SO_REUSEADDR, true);
65     }
66
67     @Sharable
68     private class CoapPacketHandler
69             extends SimpleChannelInboundHandler<CoapResponse> {
70
71         @Override
72         protected void channelRead0(ChannelHandlerContext ctx, CoapResponse msg)
73                 throws Exception {
74             mChannelMap.get(ctx.channel()).onResponseReceived(msg);
75         }
76     }
77
78     public static class CoapConnectorInitializer
79             extends ChannelInitializer<SocketChannel> {
80
81         private List<ChannelHandler> additionalHandlers = new ArrayList<>();
82
83         private Boolean              mTlsMode           = false;
84         InetSocketAddress            mInetSocketAddress = null;
85         String                       mRootCertFiePath   = null;
86
87         public void setTlsMode(Boolean tlsMode) {
88             this.mTlsMode = tlsMode;
89         }
90
91         public void setInetSocketAddress(InetSocketAddress address) {
92             this.mInetSocketAddress = address;
93         }
94
95         public void setRootCertFilePath(String path) {
96             this.mRootCertFiePath = path;
97         }
98
99         public void addHandler(ChannelHandler handler) {
100             additionalHandlers.add(handler);
101         }
102
103         @Override
104         public void initChannel(SocketChannel ch) {
105             ChannelPipeline p = ch.pipeline();
106
107             SslContext sslContext = null;
108
109             if (mTlsMode.equals(true)) {
110
111                 File rootCert = new File(mRootCertFiePath);
112
113                 try {
114                     sslContext = SslContextBuilder.forClient()
115                             .sslProvider(SslProvider.JDK).trustManager(rootCert)
116                             .build();
117                 } catch (SSLException e) {
118                     e.printStackTrace();
119                 }
120
121                 final SslContext sslCtx = sslContext;
122                 p.addLast(sslCtx.newHandler(ch.alloc(),
123                         mInetSocketAddress.getHostString(),
124                         mInetSocketAddress.getPort()));
125             }
126
127             p.addLast(new CoapDecoder());
128             p.addLast(new CoapEncoder());
129             p.addLast(new CoapLogHandler());
130             for (ChannelHandler handler : additionalHandlers) {
131                 p.addLast(handler);
132             }
133         }
134     }
135
136     HashMap<Channel, CoapClient> mChannelMap     = new HashMap<>();
137
138     Bootstrap                    mBootstrap      = new Bootstrap();
139     EventLoopGroup               mConnectorGroup = new NioEventLoopGroup();
140
141     public CoapClient connect(final InetSocketAddress inetSocketAddress,
142             boolean tlsMode) throws InterruptedException {
143
144         CoapConnectorInitializer initializer = new CoapConnectorInitializer();
145
146         if (tlsMode == true) {
147             initializer.setTlsMode(true);
148             initializer.setInetSocketAddress(inetSocketAddress);
149             initializer.setRootCertFilePath(OCFConstants.ROOT_CERT_FILE);
150         }
151
152         initializer.addHandler(new CoapPacketHandler());
153         mBootstrap.handler(initializer);
154
155         ChannelFuture channelFuture = null;
156         channelFuture = mBootstrap.connect(inetSocketAddress).sync();
157
158         CoapClient coapClient = null;
159         coapClient = new CoapClient(channelFuture.channel());
160         mChannelMap.put(channelFuture.channel(), coapClient);
161
162         return coapClient;
163     }
164
165     public void disconenct() throws Exception {
166         mConnectorGroup.shutdownGracefully().await();
167     }
168 }