增加客户端在线状态

master
fengfei 7 years ago
parent ece971fd01
commit f33cef6bb6
  1. 25
      proxy-server/src/main/java/org/fengfei/lanproxy/server/ProxyChannelManager.java
  2. 10
      proxy-server/src/main/java/org/fengfei/lanproxy/server/config/ProxyConfig.java
  3. 12
      proxy-server/src/main/java/org/fengfei/lanproxy/server/config/web/routes/RouteConfig.java
  4. 9
      proxy-server/src/main/java/org/fengfei/lanproxy/server/handlers/ServerChannelHandler.java
  5. 12
      proxy-server/src/test/resources/log4j.properties
  6. 3
      proxy-server/webpages/i18n/lang_en.properties
  7. 3
      proxy-server/webpages/i18n/lang_zh_CN.properties
  8. 145
      proxy-server/webpages/lanproxy-config/html/client/list.html

@ -39,9 +39,11 @@ public class ProxyChannelManager {
private static final AttributeKey<String> CHANNEL_CLIENT_KEY = AttributeKey.newInstance("channel_client_key"); private static final AttributeKey<String> CHANNEL_CLIENT_KEY = AttributeKey.newInstance("channel_client_key");
private static final AttributeKey<Boolean> PROXY_CHANNEL_WRITEABLE = AttributeKey.newInstance("proxy_channel_writeable"); private static final AttributeKey<Boolean> PROXY_CHANNEL_WRITEABLE = AttributeKey
.newInstance("proxy_channel_writeable");
private static final AttributeKey<Boolean> REAL_BACKEND_SERVER_CHANNEL_WRITEABLE = AttributeKey.newInstance("real_backend_server_channel_writeable"); private static final AttributeKey<Boolean> REAL_BACKEND_SERVER_CHANNEL_WRITEABLE = AttributeKey
.newInstance("real_backend_server_channel_writeable");
private static Map<Integer, Channel> portChannelMapping = new ConcurrentHashMap<Integer, Channel>(); private static Map<Integer, Channel> portChannelMapping = new ConcurrentHashMap<Integer, Channel>();
@ -68,7 +70,8 @@ public class ProxyChannelManager {
} }
if (proxyChannel.isActive()) { if (proxyChannel.isActive()) {
List<Integer> inetPorts = new ArrayList<Integer>(ProxyConfig.getInstance().getClientInetPorts(clientKey)); List<Integer> inetPorts = new ArrayList<Integer>(
ProxyConfig.getInstance().getClientInetPorts(clientKey));
Set<Integer> inetPortSet = new HashSet<Integer>(inetPorts); Set<Integer> inetPortSet = new HashSet<Integer>(inetPorts);
List<Integer> channelInetPorts = new ArrayList<Integer>(proxyChannel.attr(CHANNEL_PORT).get()); List<Integer> channelInetPorts = new ArrayList<Integer>(proxyChannel.attr(CHANNEL_PORT).get());
@ -111,7 +114,8 @@ public class ProxyChannelManager {
while (ite.hasNext()) { while (ite.hasNext()) {
Entry<String, Channel> entry = ite.next(); Entry<String, Channel> entry = ite.next();
Channel proxyChannel = entry.getValue(); Channel proxyChannel = entry.getValue();
logger.info("proxyChannel config, {}, {}, {} ,{}", entry.getKey(), proxyChannel, getUserChannels(proxyChannel).size(), proxyChannel.attr(CHANNEL_PORT).get()); logger.info("proxyChannel config, {}, {}, {} ,{}", entry.getKey(), proxyChannel,
getUserChannels(proxyChannel).size(), proxyChannel.attr(CHANNEL_PORT).get());
} }
} }
@ -218,6 +222,10 @@ public class ProxyChannelManager {
return portChannelMapping.get(port); return portChannelMapping.get(port);
} }
public static Channel getProxyChannel(String clientKey) {
return proxyChannels.get(clientKey);
}
/** /**
* 增加用户连接与代理客户端连接关系 * 增加用户连接与代理客户端连接关系
* *
@ -294,8 +302,10 @@ public class ProxyChannelManager {
* @param client * @param client
* @param proxy * @param proxy
*/ */
public static void setUserChannelReadability(Channel userChannel, Boolean realBackendServerChannelWriteability, Boolean proxyChannelWriteability) { public static void setUserChannelReadability(Channel userChannel, Boolean realBackendServerChannelWriteability,
logger.info("update user channel readability, {} {} {}", userChannel, realBackendServerChannelWriteability, proxyChannelWriteability); Boolean proxyChannelWriteability) {
logger.debug("update user channel readability, {} {} {}", userChannel, realBackendServerChannelWriteability,
proxyChannelWriteability);
synchronized (userChannel) { synchronized (userChannel) {
if (realBackendServerChannelWriteability != null) { if (realBackendServerChannelWriteability != null) {
userChannel.attr(REAL_BACKEND_SERVER_CHANNEL_WRITEABLE).set(realBackendServerChannelWriteability); userChannel.attr(REAL_BACKEND_SERVER_CHANNEL_WRITEABLE).set(realBackendServerChannelWriteability);
@ -305,7 +315,8 @@ public class ProxyChannelManager {
userChannel.attr(PROXY_CHANNEL_WRITEABLE).set(proxyChannelWriteability); userChannel.attr(PROXY_CHANNEL_WRITEABLE).set(proxyChannelWriteability);
} }
if (userChannel.attr(REAL_BACKEND_SERVER_CHANNEL_WRITEABLE).get() && userChannel.attr(PROXY_CHANNEL_WRITEABLE).get()) { if (userChannel.attr(REAL_BACKEND_SERVER_CHANNEL_WRITEABLE).get()
&& userChannel.attr(PROXY_CHANNEL_WRITEABLE).get()) {
// 代理客户端与后端服务器连接状态均为可写时,用户连接状态为可读 // 代理客户端与后端服务器连接状态均为可写时,用户连接状态为可读
userChannel.config().setOption(ChannelOption.AUTO_READ, true); userChannel.config().setOption(ChannelOption.AUTO_READ, true);

@ -320,6 +320,8 @@ public class ProxyConfig implements Serializable {
/** 代理客户端与其后面的真实服务器映射关系 */ /** 代理客户端与其后面的真实服务器映射关系 */
private List<ClientProxyMapping> proxyMappings; private List<ClientProxyMapping> proxyMappings;
private int status;
public String getClientKey() { public String getClientKey() {
return clientKey; return clientKey;
} }
@ -344,6 +346,14 @@ public class ProxyConfig implements Serializable {
this.name = name; this.name = name;
} }
public int getStatus() {
return status;
}
public void setStatus(int status) {
this.status = status;
}
} }
/** /**

@ -6,6 +6,7 @@ import java.util.Map;
import java.util.UUID; import java.util.UUID;
import org.fengfei.lanproxy.common.JsonUtil; import org.fengfei.lanproxy.common.JsonUtil;
import org.fengfei.lanproxy.server.ProxyChannelManager;
import org.fengfei.lanproxy.server.config.ProxyConfig; import org.fengfei.lanproxy.server.config.ProxyConfig;
import org.fengfei.lanproxy.server.config.ProxyConfig.Client; import org.fengfei.lanproxy.server.config.ProxyConfig.Client;
import org.fengfei.lanproxy.server.config.web.ApiRoute; import org.fengfei.lanproxy.server.config.web.ApiRoute;
@ -19,6 +20,7 @@ import org.slf4j.LoggerFactory;
import com.google.gson.reflect.TypeToken; import com.google.gson.reflect.TypeToken;
import io.netty.channel.Channel;
import io.netty.handler.codec.http.FullHttpRequest; import io.netty.handler.codec.http.FullHttpRequest;
import io.netty.handler.codec.http.HttpHeaders; import io.netty.handler.codec.http.HttpHeaders;
@ -79,7 +81,15 @@ public class RouteConfig {
@Override @Override
public ResponseInfo request(FullHttpRequest request) { public ResponseInfo request(FullHttpRequest request) {
List<Client> clients = ProxyConfig.getInstance().getClients();
for (Client client : clients) {
Channel channel = ProxyChannelManager.getProxyChannel(client.getClientKey());
if (channel != null) {
client.setStatus(1);// online
} else {
client.setStatus(0);// offline
}
}
return ResponseInfo.build(ProxyConfig.getInstance().getClients()); return ResponseInfo.build(ProxyConfig.getInstance().getClients());
} }
}); });

@ -108,7 +108,14 @@ public class ServerChannelHandler extends SimpleChannelInboundHandler<ProxyMessa
return; return;
} }
logger.info("set port => channel, {} {}", clientKey, ports); Channel channel = ProxyChannelManager.getProxyChannel(clientKey);
if (channel != null) {
logger.warn("exist channel for key {}, {}", clientKey, channel);
ctx.channel().close();
return;
}
logger.info("set port => channel, {}, {}, {}", clientKey, ports, ctx.channel());
ProxyChannelManager.addProxyChannel(ports, clientKey, ctx.channel()); ProxyChannelManager.addProxyChannel(ports, clientKey, ctx.channel());
} }

@ -1,7 +1,7 @@
log4j.rootLogger=warn,stdout log4j.rootLogger=info,stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - <%m>%n log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - <%m>%n
#log4j.logger.io.netty=warn #log4j.logger.io.netty=warn

@ -33,6 +33,9 @@ client.notice.inputname=Client name is required
client.notice.inputkey=Client key is required client.notice.inputkey=Client key is required
client.notice.addsuccess=New client has been added successfully client.notice.addsuccess=New client has been added successfully
client.edit=Edit client client.edit=Edit client
client.status=Status
client.status.online=Up
client.status.offline=Down
lan.proxyconfig=Proxy config lan.proxyconfig=Proxy config
lan.addnewconfig=New proxy config lan.addnewconfig=New proxy config

@ -32,6 +32,9 @@ client.notice.inputname=请输入客户端备注名称
client.notice.inputkey=请输入客户端通信密钥 client.notice.inputkey=请输入客户端通信密钥
client.notice.addsuccess=客户端添加成功 client.notice.addsuccess=客户端添加成功
client.edit=编辑客户端 client.edit=编辑客户端
client.status=状态
client.status.online=在线
client.status.offline=离线
lan.proxyconfig=代理配置 lan.proxyconfig=代理配置
lan.addnewconfig=添加配置 lan.addnewconfig=添加配置

@ -1,72 +1,75 @@
<div class="layui-tab layui-tab-brief"> <div class="layui-tab layui-tab-brief">
<ul class="layui-tab-title site-demo-title"> <ul class="layui-tab-title site-demo-title">
<li class="layui-this detail-page"></li> <li class="layui-this detail-page"></li>
</ul> </ul>
<div class="main-content"></div> <div class="main-content"></div>
</div> </div>
<script> <script>
$(".layui-this.detail-page").html($.i18n.prop('client.list')); $(".layui-this.detail-page").html($.i18n.prop('client.list'));
window.clientList = []; window.clientList = [];
api_invoke("/config/detail", {}, function(data) { api_invoke("/config/detail", {}, function(data) {
if (data.code == 20000) { if (data.code == 20000) {
clientList = data.data; clientList = data.data;
var html = template($("#client-tpl").html(), data); var html = template($("#client-tpl").html(), data);
$(".main-content").html(html); $(".main-content").html(html);
$(".mapping-config").click(function() { $(".mapping-config").click(function() {
window.clientIndex = $(this).attr("data-index"); window.clientIndex = $(this).attr("data-index");
load_page("html/lan/list.html"); load_page("html/lan/list.html");
}); });
$(".client-edit").click(function() { $(".client-edit").click(function() {
window.clientIndex = $(this).attr("data-index"); window.clientIndex = $(this).attr("data-index");
load_page("html/client/edit.html"); load_page("html/client/edit.html");
}); });
$(".client-delete").click(function() { $(".client-delete").click(function() {
window.clientIndex = $(this).attr("data-index"); window.clientIndex = $(this).attr("data-index");
layer.confirm($.i18n.prop('public.confirm.delete'), { layer.confirm($.i18n.prop('public.confirm.delete'), {
title: $.i18n.prop('public.tips'), title: $.i18n.prop('public.tips'),
btn : [ $.i18n.prop('public.ok'), $.i18n.prop('public.cancel') ] btn : [ $.i18n.prop('public.ok'), $.i18n.prop('public.cancel') ]
}, function(i) { }, function(i) {
layer.close(i); layer.close(i);
clientList.splice(clientIndex, 1); clientList.splice(clientIndex, 1);
api_invoke("/config/update", clientList, function(data) { api_invoke("/config/update", clientList, function(data) {
if (data.code != 20000) { if (data.code != 20000) {
layer.alert(data.message); layer.alert(data.message);
} else { } else {
location.reload(); location.reload();
} }
}) })
}); });
}); });
$(".th-client-name").html($.i18n.prop('client.name')); } else {
$(".th-client-key").html($.i18n.prop('client.key')); alert(data.message);
$(".th-options").html($.i18n.prop('public.options')); }
$(".client-edit").html($.i18n.prop('public.edit')); });
$(".client-delete").html($.i18n.prop('public.delete')); </script>
} else { <script id="client-tpl" type="text/html">
alert(data.message); <table class="layui-table" lay-skin="line">
} <thead>
}); <tr>
</script> <th class="th-client-name"><%:=$.i18n.prop('client.name')%></th>
<script id="client-tpl" type="text/html"> <th class="th-client-key"><%:=$.i18n.prop('client.key')%></th>
<table class="layui-table" lay-skin="line"> <th class="th-status"><%:=$.i18n.prop('client.status')%></th>
<thead> <th class="th-options"><%:=$.i18n.prop('public.options')%></th>
<tr> </tr>
<th class="th-client-name"></th> </thead>
<th class="th-client-key"></th> <tbody>
<th class="th-options"></th> <%for(var i = 0; i < data.length; i++) {%>
</tr> <tr>
</thead> <td><%:=data[i].name%></td>
<tbody> <td><%:=data[i].clientKey%></td>
<%for(var i = 0; i < data.length; i++) {%> <td>
<tr> <% if(data[i].status == 1){ %>
<td><%:=data[i].name%></td> <span class="layui-badge layui-bg-green"><%:=$.i18n.prop('client.status.online')%></span>
<td><%:=data[i].clientKey%></td> <% } else { %>
<td> <span class="layui-badge layui-bg-gray"><%:=$.i18n.prop('client.status.offline')%></span>
<a data-index="<%:=i%>" class="layui-btn layui-btn-mini client-edit"></a> <% }%>
<a data-index="<%:=i%>" class="layui-btn layui-btn-danger layui-btn-mini client-delete"></a> </td>
</td> <td>
</tr> <a data-index="<%:=i%>" class="layui-btn layui-btn-mini client-edit"><%:=$.i18n.prop('public.edit')%></a>
<%}%> <a data-index="<%:=i%>" class="layui-btn layui-btn-danger layui-btn-mini client-delete"><%:=$.i18n.prop('public.delete')%></a>
</tbody> </td>
</table> </tr>
<%}%>
</tbody>
</table>
</script> </script>
Loading…
Cancel
Save