diff --git a/src/com/wentch/redkale/boot/Application.java b/src/com/wentch/redkale/boot/Application.java index 55d4889d9..1677e0d50 100644 --- a/src/com/wentch/redkale/boot/Application.java +++ b/src/com/wentch/redkale/boot/Application.java @@ -408,11 +408,11 @@ public final class Application { try { //Thread ctd = Thread.currentThread(); //ctd.setContextClassLoader(new URLClassLoader(new URL[0], ctd.getContextClassLoader())); - final String protocol = serconf.getValue("protocol", "").replaceFirst("\\..+", ""); + final String protocol = serconf.getValue("protocol", "").replaceFirst("\\..+", "").toUpperCase(); NodeServer server = null; - if ("SNCP".equalsIgnoreCase(protocol)) { + if ("SNCP".equals(protocol)) { server = new NodeSncpServer(Application.this, serconf); - } else if ("HTTP".equalsIgnoreCase(protocol) || "HTTPS".equalsIgnoreCase(protocol)) { + } else if ("HTTP".equals(protocol) || "HTTPS".equals(protocol)) { server = new NodeHttpServer(Application.this, serconf); } else { if (!inited.get()) { @@ -426,7 +426,8 @@ public final class Application { final Class type = entry.getType(); NodeProtocol pros = type.getAnnotation(NodeProtocol.class); for (String p : pros.value()) { - if (p.equalsIgnoreCase("SNCP") || p.equalsIgnoreCase("HTTP") || p.equalsIgnoreCase("HTTPS")) continue; + p = p.toUpperCase(); + if ("SNCP".equals(p) || "HTTP".equals(p) || "HTTPS".equals(p)) continue; final Class old = nodeClasses.get(p); if (old != null && old != type) throw new RuntimeException("Protocol(" + p + ") had NodeServer-Class(" + old.getName() + ") but repeat NodeServer-Class(" + type.getName() + ")"); nodeClasses.put(p, type); diff --git a/src/com/wentch/redkale/net/icep/IcepRequest.java b/src/com/wentch/redkale/net/icep/IcepRequest.java index 6026a7682..c69711e90 100644 --- a/src/com/wentch/redkale/net/icep/IcepRequest.java +++ b/src/com/wentch/redkale/net/icep/IcepRequest.java @@ -32,7 +32,7 @@ public class IcepRequest extends Request { if (buffer.remaining() < 20) return -1; this.requestid = buffer.getShort(); char bodysize = buffer.getChar(); - byte[] bytes = new byte[16]; + byte[] bytes = new byte[16]; buffer.get(bytes); StunHeader header = new StunHeader(this.requestid, bytes); this.stunPacket = new StunPacket(header); @@ -49,12 +49,13 @@ public class IcepRequest extends Request { @Override protected void prepare() { - } @Override protected void recycle() { - + this.requestid = 0; + this.stunPacket = null; + super.recycle(); } public short getRequestid() { diff --git a/src/com/wentch/redkale/net/icep/IcepServer.java b/src/com/wentch/redkale/net/icep/IcepServer.java index 4b69fb0fc..de99f5556 100644 --- a/src/com/wentch/redkale/net/icep/IcepServer.java +++ b/src/com/wentch/redkale/net/icep/IcepServer.java @@ -40,7 +40,7 @@ public final class IcepServer extends Server { final int port = this.address.getPort(); AtomicLong createBufferCounter = watch == null ? new AtomicLong() : watch.createWatchNumber("ICEP_" + port + ".Buffer.creatCounter"); AtomicLong cycleBufferCounter = watch == null ? new AtomicLong() : watch.createWatchNumber("ICEP_" + port + ".Buffer.cycleCounter"); - int rcapacity = Math.max(this.capacity, 16 * 1024 + 8); //兼容 HTTP 2.0 + int rcapacity = Math.max(this.capacity, 8 * 1024); ObjectPool bufferPool = new ObjectPool<>(createBufferCounter, cycleBufferCounter, this.bufferPoolSize, (Object... params) -> ByteBuffer.allocateDirect(rcapacity), null, (e) -> { if (e == null || e.isReadOnly() || e.capacity() != rcapacity) return false; @@ -50,9 +50,9 @@ public final class IcepServer extends Server { AtomicLong createResponseCounter = watch == null ? new AtomicLong() : watch.createWatchNumber("ICEP_" + port + ".Response.creatCounter"); AtomicLong cycleResponseCounter = watch == null ? new AtomicLong() : watch.createWatchNumber("ICEP_" + port + ".Response.cycleCounter"); ObjectPool responsePool = IcepResponse.createPool(createResponseCounter, cycleResponseCounter, this.responsePoolSize, null); - IcepContext icepcontext = new IcepContext(this.serverStartTime, this.logger, executor, bufferPool, responsePool, + IcepContext localcontext = new IcepContext(this.serverStartTime, this.logger, executor, bufferPool, responsePool, this.maxbody, this.charset, this.address, this.prepare, this.watch, this.readTimeoutSecond, this.writeTimeoutSecond); - responsePool.setCreator((Object... params) -> new IcepResponse(icepcontext, new IcepRequest(icepcontext))); - return icepcontext; + responsePool.setCreator((Object... params) -> new IcepResponse(localcontext, new IcepRequest(localcontext))); + return localcontext; } } diff --git a/src/com/wentch/redkale/net/icep/IcepServlet.java b/src/com/wentch/redkale/net/icep/IcepServlet.java index 5b16f3279..34a2c879d 100644 --- a/src/com/wentch/redkale/net/icep/IcepServlet.java +++ b/src/com/wentch/redkale/net/icep/IcepServlet.java @@ -14,7 +14,7 @@ import com.wentch.redkale.util.*; */ public abstract class IcepServlet implements Servlet { - AnyValue conf; //当前HttpServlet的配置 + AnyValue conf; //当前Servlet的配置 public abstract short getRequestid(); diff --git a/src/com/wentch/redkale/net/socks/NodeSocksServer.java b/src/com/wentch/redkale/net/socks/NodeSocksServer.java new file mode 100644 index 000000000..6a98b0a3d --- /dev/null +++ b/src/com/wentch/redkale/net/socks/NodeSocksServer.java @@ -0,0 +1,73 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package com.wentch.redkale.net.socks; + +import com.wentch.redkale.boot.ClassFilter.FilterEntry; +import com.wentch.redkale.boot.*; +import static com.wentch.redkale.boot.NodeServer.LINE_SEPARATOR; +import com.wentch.redkale.net.*; +import com.wentch.redkale.util.*; +import com.wentch.redkale.util.AnyValue.DefaultAnyValue; +import java.lang.reflect.*; +import java.net.*; +import java.util.logging.*; + +/** + * + * @author zhangjx + */ +@NodeProtocol({"SOCKS"}) +public class NodeSocksServer extends NodeServer { + + private final SocksServer socksServer; + + public NodeSocksServer(Application application, AnyValue serconf) { + super(application, application.getResourceFactory().createChild(), createServer(application, serconf)); + this.socksServer = (SocksServer) server; + } + + private static Server createServer(Application application, AnyValue serconf) { + return new SocksServer(application.getStartTime(), application.getWatchFactory()); + } + + @Override + public InetSocketAddress getSocketAddress() { + return socksServer == null ? null : socksServer.getSocketAddress(); + } + + @Override + protected ClassFilter createServletClassFilter() { + return createClassFilter(null, null, SocksServlet.class, null, "servlets", "servlet"); + } + + @Override + protected void loadServlet(ClassFilter servletFilter) throws Exception { + if (socksServer != null) loadSocksServlet(this.nodeConf.getAnyValue("servlets"), servletFilter); + } + + protected void loadSocksServlet(final AnyValue conf, ClassFilter filter) throws Exception { + final StringBuilder sb = logger.isLoggable(Level.FINE) ? new StringBuilder() : null; + final String threadName = "[" + Thread.currentThread().getName() + "] "; + for (FilterEntry en : filter.getFilterEntrys()) { + Class clazz = (Class) en.getType(); + if (Modifier.isAbstract(clazz.getModifiers())) continue; + final SocksServlet servlet = clazz.newInstance(); + factory.inject(servlet); + DefaultAnyValue servletConf = (DefaultAnyValue) en.getProperty(); + this.socksServer.addSocksServlet(servlet, servletConf); + if (sb != null) sb.append(threadName).append(" Loaded ").append(clazz.getName()).append(" --> ").append(format(servlet.getRequestid())).append(LINE_SEPARATOR); + } + if (sb != null && sb.length() > 0) logger.log(Level.FINE, sb.toString()); + } + + private static String format(short value) { + String str = Integer.toHexString(value); + if (str.length() == 1) return "0x000" + str; + if (str.length() == 2) return "0x00" + str; + if (str.length() == 3) return "0x0" + str; + return "0x" + str; + } +} diff --git a/src/com/wentch/redkale/net/socks/SocksContext.java b/src/com/wentch/redkale/net/socks/SocksContext.java new file mode 100644 index 000000000..b86ea94a1 --- /dev/null +++ b/src/com/wentch/redkale/net/socks/SocksContext.java @@ -0,0 +1,29 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package com.wentch.redkale.net.socks; + +import com.wentch.redkale.net.*; +import com.wentch.redkale.util.*; +import com.wentch.redkale.watch.*; +import java.net.*; +import java.nio.*; +import java.nio.charset.*; +import java.util.concurrent.*; +import java.util.logging.*; + +/** + * + * @author zhangjx + */ +public class SocksContext extends Context { + + public SocksContext(long serverStartTime, Logger logger, ExecutorService executor, ObjectPool bufferPool, + ObjectPool responsePool, int maxbody, Charset charset, InetSocketAddress address, PrepareServlet prepare, + WatchFactory watch, int readTimeoutSecond, int writeTimeoutSecond) { + super(serverStartTime, logger, executor, bufferPool, responsePool, maxbody, charset, + address, prepare, watch, readTimeoutSecond, writeTimeoutSecond); + } +} diff --git a/src/com/wentch/redkale/net/socks/SocksPrepareServlet.java b/src/com/wentch/redkale/net/socks/SocksPrepareServlet.java new file mode 100644 index 000000000..ce2a4b9fb --- /dev/null +++ b/src/com/wentch/redkale/net/socks/SocksPrepareServlet.java @@ -0,0 +1,45 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package com.wentch.redkale.net.socks; + +import com.wentch.redkale.net.*; +import com.wentch.redkale.util.*; +import java.io.*; +import java.util.*; + +/** + * + * @author zhangjx + */ +public class SocksPrepareServlet extends PrepareServlet { + + private final HashMap servletmaps = new HashMap<>(); + + public SocksPrepareServlet() { + } + + @Override + public void init(Context context, AnyValue config) { + } + + public void addSocksServlet(SocksServlet servlet, AnyValue conf) { + servlet.conf = conf; + this.servletmaps.put(servlet.getRequestid(), servlet); + } + + // 28.[00,03,00,08, 21,12,a4,42,45,6f,4e,77,4e,47,71,55,32,37,77,39, 00,19,00,04,11,00,00,00] + @Override + public void execute(SocksRequest request, SocksResponse response) throws IOException { + SocksServlet servlet = servletmaps.get(request.getRequestid()); + if (servlet != null) { + servlet.execute(request, response); + } else { + response.finish(); + } + } + +} + diff --git a/src/com/wentch/redkale/net/socks/SocksRequest.java b/src/com/wentch/redkale/net/socks/SocksRequest.java new file mode 100644 index 000000000..82f0c01a0 --- /dev/null +++ b/src/com/wentch/redkale/net/socks/SocksRequest.java @@ -0,0 +1,50 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package com.wentch.redkale.net.socks; + +import com.wentch.redkale.net.*; +import java.nio.*; + +/** + * + * @author zhangjx + */ +public class SocksRequest extends Request { + + private short requestid; + + protected SocksRequest(SocksContext context) { + super(context); + } + + @Override + protected int readHeader(ByteBuffer buffer) { + throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. + } + + @Override + protected void readBody(ByteBuffer buffer) { + throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. + } + + @Override + protected void prepare() { + } + + @Override + protected void recycle() { + super.recycle(); + } + + public short getRequestid() { + return requestid; + } + + public void setRequestid(short requestid) { + this.requestid = requestid; + } + +} diff --git a/src/com/wentch/redkale/net/socks/SocksResponse.java b/src/com/wentch/redkale/net/socks/SocksResponse.java new file mode 100644 index 000000000..0744baf51 --- /dev/null +++ b/src/com/wentch/redkale/net/socks/SocksResponse.java @@ -0,0 +1,26 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package com.wentch.redkale.net.socks; + +import com.wentch.redkale.net.*; +import com.wentch.redkale.util.*; +import java.util.concurrent.atomic.*; + +/** + * + * @author zhangjx + */ +public class SocksResponse extends Response { + + protected SocksResponse(Context context, SocksRequest request) { + super(context, request); + } + + public static ObjectPool createPool(AtomicLong creatCounter, AtomicLong cycleCounter, int max, Creator creator) { + return new ObjectPool<>(creatCounter, cycleCounter, max, creator, (x) -> ((SocksResponse) x).prepare(), (x) -> ((SocksResponse) x).recycle()); + } +} + diff --git a/src/com/wentch/redkale/net/socks/SocksServer.java b/src/com/wentch/redkale/net/socks/SocksServer.java new file mode 100644 index 000000000..739d79fc2 --- /dev/null +++ b/src/com/wentch/redkale/net/socks/SocksServer.java @@ -0,0 +1,58 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package com.wentch.redkale.net.socks; + +import com.wentch.redkale.net.*; +import com.wentch.redkale.util.*; +import com.wentch.redkale.watch.*; +import java.nio.*; +import java.util.concurrent.atomic.*; + +/** + * + * @author zhangjx + */ +public final class SocksServer extends Server { + + public SocksServer() { + this(System.currentTimeMillis(), null); + } + + public SocksServer(long serverStartTime, final WatchFactory watch) { + super(serverStartTime, "TCP", new SocksPrepareServlet(), watch); + } + + @Override + public void init(AnyValue config) throws Exception { + super.init(config); + } + + public void addSocksServlet(SocksServlet servlet, AnyValue conf) { + ((SocksPrepareServlet) this.prepare).addSocksServlet(servlet, conf); + } + + @Override + @SuppressWarnings("unchecked") + protected Context createContext() { + final int port = this.address.getPort(); + AtomicLong createBufferCounter = watch == null ? new AtomicLong() : watch.createWatchNumber("SOCKS_" + port + ".Buffer.creatCounter"); + AtomicLong cycleBufferCounter = watch == null ? new AtomicLong() : watch.createWatchNumber("SOCKS_" + port + ".Buffer.cycleCounter"); + int rcapacity = Math.max(this.capacity, 8 * 1024); + ObjectPool bufferPool = new ObjectPool<>(createBufferCounter, cycleBufferCounter, this.bufferPoolSize, + (Object... params) -> ByteBuffer.allocateDirect(rcapacity), null, (e) -> { + if (e == null || e.isReadOnly() || e.capacity() != rcapacity) return false; + e.clear(); + return true; + }); + AtomicLong createResponseCounter = watch == null ? new AtomicLong() : watch.createWatchNumber("SOCKS_" + port + ".Response.creatCounter"); + AtomicLong cycleResponseCounter = watch == null ? new AtomicLong() : watch.createWatchNumber("SOCKS_" + port + ".Response.cycleCounter"); + ObjectPool responsePool = SocksResponse.createPool(createResponseCounter, cycleResponseCounter, this.responsePoolSize, null); + SocksContext localcontext = new SocksContext(this.serverStartTime, this.logger, executor, bufferPool, responsePool, + this.maxbody, this.charset, this.address, this.prepare, this.watch, this.readTimeoutSecond, this.writeTimeoutSecond); + responsePool.setCreator((Object... params) -> new SocksResponse(localcontext, new SocksRequest(localcontext))); + return localcontext; + } +} diff --git a/src/com/wentch/redkale/net/socks/SocksServlet.java b/src/com/wentch/redkale/net/socks/SocksServlet.java new file mode 100644 index 000000000..67a82c13e --- /dev/null +++ b/src/com/wentch/redkale/net/socks/SocksServlet.java @@ -0,0 +1,30 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package com.wentch.redkale.net.socks; + +import com.wentch.redkale.net.*; +import com.wentch.redkale.util.*; + +/** + * + * @author zhangjx + */ +public abstract class SocksServlet implements Servlet { + + AnyValue conf; //当前Servlet的配置 + + public abstract short getRequestid(); + + @Override + public final boolean equals(Object obj) { + return obj != null && obj.getClass() == this.getClass(); + } + + @Override + public final int hashCode() { + return this.getClass().hashCode(); + } +}