package org.kne.cloud.network.srv6; import java.io.IOException; import java.lang.ref.Cleaner; import java.net.InetSocketAddress; import java.net.SocketAddress; import java.util.ArrayList; import java.util.List; import java.util.UUID; import java.util.function.BiConsumer; import java.util.function.Consumer; import org.kne.cloud.network.MultiProtocolSocketAddress; import org.kne.cloud.network.congestion.NOCongestionAlgorithm; import org.kne.cloud.network.congestion.SendPacketSlidingWindow; import org.kne.opencl64.Releaser; public class KLALBRoutingProtocolAPIClient { private KLALBRoutingProtocol routingProtocol; private SendPacketSlidingWindow window = new SendPacketSlidingWindow( new NOCongestionAlgorithm(3000000000L), 1024 * 1024); private static final Cleaner clr = Cleaner.create(); private BiConsumer rec = (addr, data) -> { KLALBRoutingProtocolJsonData dataobj = data.getDecodedData(); InetSocketAddress addrs = (InetSocketAddress) addr; UUID ruid = dataobj.getUuid(); JsonDataPacket relate = null; //System.out.println(ruid + " " + window.getSendmap()); switch (dataobj.getType()) { case KLALBRoutingProtocolJsonData.NODE_INFO_FULL_RESP: case KLALBRoutingProtocolJsonData.NODE_INFO_TINY_RESP: if ((relate = window.ack(ruid)) != null) { List connects = (List) dataobj.getData(); List connectsm = new ArrayList( connects == null ? 0 : connects.size()); if (connects != null) { for (Object open : connects) { if (open instanceof MultiProtocolSocketAddress) { connectsm.add((MultiProtocolSocketAddress) open); } else { connectsm.add(new MultiProtocolSocketAddress((String) open)); } } } // 组装节点信息(线路 + 设备名称 + 设备描述,精简模式下线路与描述为 null) KLALBNodeInformation info = new KLALBNodeInformation(connectsm, dataobj.getDeviceName(), dataobj.getDeviceDescription()); ((Consumer) relate.getUserCallback()).accept(info); } break; } }; public KLALBRoutingProtocolAPIClient(KLALBRoutingProtocol routingProtocol) { this.routingProtocol = routingProtocol; routingProtocol.addReceiver(rec); this.releaser = new KLALBRoutingProtocolAPIClientReleaser(this.routingProtocol, rec, window); clr.register(this, releaser); } /** * 精简查询:仅获取对端设备名称(开销最小,适用于未查看节点详情的场景)。 */ public void requestNodeInfoTiny(SocketAddress addr, Consumer callback) throws IOException { sendNodeInfoRequest(KLALBRoutingProtocolJsonData.NODE_INFO_TINY_REQ, addr, callback); } /** * 完整查询:获取对端开放线路 + 设备名称 + 设备描述(查看节点信息时使用)。 */ public void requestNodeInfoFull(SocketAddress addr, Consumer callback) throws IOException { sendNodeInfoRequest(KLALBRoutingProtocolJsonData.NODE_INFO_FULL_REQ, addr, callback); } private void sendNodeInfoRequest(String type, SocketAddress addr, Consumer callback) throws IOException { UUID suid = UUID.randomUUID(); KLALBRoutingProtocolJsonData json = new KLALBRoutingProtocolJsonData(type, suid, null); JsonDataPacket packet = new JsonDataPacket(json); packet.setUserCallback(callback); window.put(suid, packet); routingProtocol.sendJsonPacketToAddress(packet, addr); } public KLALBRoutingProtocol getRoutingProtocol() { return routingProtocol; } private KLALBRoutingProtocolAPIClientReleaser releaser; public void close() { releaser.run(); } public boolean isClosed() { return releaser.isReleased(); } } class KLALBRoutingProtocolAPIClientReleaser extends Releaser> { private KLALBRoutingProtocol routingProtocol; private SendPacketSlidingWindow window; public KLALBRoutingProtocolAPIClientReleaser(KLALBRoutingProtocol routingProtocol, BiConsumer resource, SendPacketSlidingWindow window) { super(resource); this.routingProtocol = routingProtocol; this.window = window; } @Override protected void release(BiConsumer resource) { window.close(); routingProtocol.removeReceiver(resource); } }