Coverage Summary for Class: PeerServerImpl (org.ethereum.net.server)
Class |
Class, %
|
Method, %
|
Line, %
|
PeerServerImpl |
0%
(0/1)
|
0%
(0/9)
|
0%
(0/40)
|
1 /*
2 * This file is part of RskJ
3 * Copyright (C) 2017 RSK Labs Ltd.
4 * (derived from ethereumJ library, Copyright (c) 2016 <ether.camp>)
5 *
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU Lesser General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 package org.ethereum.net.server;
21
22 import io.netty.bootstrap.ServerBootstrap;
23 import io.netty.channel.ChannelFuture;
24 import io.netty.channel.ChannelOption;
25 import io.netty.channel.DefaultMessageSizeEstimator;
26 import io.netty.channel.EventLoopGroup;
27 import io.netty.channel.nio.NioEventLoopGroup;
28 import io.netty.channel.socket.nio.NioServerSocketChannel;
29 import io.netty.handler.logging.LoggingHandler;
30 import org.ethereum.config.SystemProperties;
31 import org.ethereum.listener.EthereumListener;
32 import org.ethereum.net.EthereumChannelInitializerFactory;
33 import org.ethereum.util.ByteUtil;
34 import org.slf4j.Logger;
35 import org.slf4j.LoggerFactory;
36
37 import java.net.InetAddress;
38 import java.util.concurrent.ExecutorService;
39 import java.util.concurrent.Executors;
40
41 /**
42 * This class establishes a listener for incoming connections.
43 * See <a href="http://netty.io">http://netty.io</a>.
44 */
45 public class PeerServerImpl implements PeerServer {
46
47 private static final Logger logger = LoggerFactory.getLogger("net");
48
49 private final SystemProperties config;
50 private final EthereumListener ethereumListener;
51 private final EthereumChannelInitializerFactory ethereumChannelInitializerFactory;
52
53 // TODO review this variable use
54 private boolean listening;
55 private ExecutorService peerServiceExecutor;
56
57 public PeerServerImpl(SystemProperties config, EthereumListener ethereumListener, EthereumChannelInitializerFactory ethereumChannelInitializerFactory) {
58 this.config = config;
59 this.ethereumListener = ethereumListener;
60 this.ethereumChannelInitializerFactory = ethereumChannelInitializerFactory;
61 }
62
63 @Override
64 public void start() {
65 if (config.getPeerPort() > 0) {
66 peerServiceExecutor = Executors.newSingleThreadExecutor(runnable -> {
67 Thread thread = new Thread(runnable, "Peer Server");
68 thread.setUncaughtExceptionHandler(
69 (exceptionThread, exception) -> logger.error("Unable to start peer server", exception)
70 );
71 return thread;
72 });
73 peerServiceExecutor.execute(() -> start(config.getBindAddress(), config.getPeerPort()));
74 }
75
76 logger.info("RskJ node started: enode://{}@{}:{}" , ByteUtil.toHexString(config.nodeId()), config.getPublicIp(), config.getPeerPort());
77 }
78
79 @Override
80 public void stop() {
81 if (peerServiceExecutor != null) {
82 peerServiceExecutor.shutdown();
83 }
84 }
85
86 private void start(InetAddress host, int port) {
87 // TODO review listening use
88 listening = true;
89
90 EventLoopGroup bossGroup = new NioEventLoopGroup(1);
91 EventLoopGroup workerGroup = new NioEventLoopGroup();
92
93 EthereumChannelInitializer ethereumChannelInitializer = ethereumChannelInitializerFactory.newInstance("");
94
95 ethereumListener.trace("Listening on port " + port);
96
97
98 try {
99 ServerBootstrap b = new ServerBootstrap();
100
101 b.group(bossGroup, workerGroup);
102 b.channel(NioServerSocketChannel.class);
103
104 b.option(ChannelOption.SO_KEEPALIVE, true);
105 b.option(ChannelOption.MESSAGE_SIZE_ESTIMATOR, DefaultMessageSizeEstimator.DEFAULT);
106 b.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, config.peerConnectionTimeout());
107
108 b.handler(new LoggingHandler());
109 b.childHandler(ethereumChannelInitializer);
110
111 // Start the client.
112 logger.info("Listening for incoming connections, host: {}, port: [{}] ", host, port);
113 logger.info("NodeId: [{}] ", ByteUtil.toHexString(config.nodeId()));
114
115 ChannelFuture f = b.bind(host, port).sync();
116
117 // Wait until the connection is closed.
118 f.channel().closeFuture().sync();
119 logger.debug("Connection is closed");
120
121 // TODO review listening use
122 listening = false;
123 } catch (Exception e) {
124 logger.debug("Exception: {} ({})", e.getMessage(), e.getClass().getName());
125 throw new Error("Server Disconnected");
126 } finally {
127 workerGroup.shutdownGracefully();
128
129 }
130 }
131
132 public boolean isListening() {
133 return listening;
134 }
135 }