├── ipseccmd.exe ├── lib ├── jna.jar ├── pcap4j-core.jar ├── fastjson-1.1.6.jar ├── slf4j-api-1.6.6.jar ├── slf4j-nop-1.6.1.jar ├── commons-cli-1.3.1.jar └── pcap4j-packetfactory-static.jar ├── img └── offline.png ├── src ├── META-INF │ └── MANIFEST.MF └── net │ └── fs │ ├── cap │ ├── SendRecord.java │ ├── TunData.java │ ├── CapServer.java │ ├── IPacket.java │ ├── TunManager.java │ ├── VDatagramSocket.java │ ├── CustomTcpSackOption.java │ ├── TCPTun.java │ ├── PacketUtils.java │ └── CapEnv.java │ ├── utils │ ├── LogListener.java │ ├── MessageCheck.java │ ├── MLog.java │ ├── ByteIntConvert.java │ ├── ByteShortConvert.java │ ├── LogOutputStream.java │ ├── NetStatus.java │ └── Tools.java │ ├── rudp │ ├── PipeListener.java │ ├── ClientProcessorInterface.java │ ├── ConnectionProcessor.java │ ├── Trafficlistener.java │ ├── MessageInterface.java │ ├── Constant.java │ ├── ConnectException.java │ ├── ReceivePingException.java │ ├── RUDPConfig.java │ ├── CopiedIterator.java │ ├── UDPOutputStream.java │ ├── ConnInfo.java │ ├── ResendItem.java │ ├── UDPInputStream.java │ ├── message │ │ ├── Message.java │ │ ├── CloseMessage_Conn.java │ │ ├── PingMessage2.java │ │ ├── CloseMessage_Stream.java │ │ ├── PingMessage.java │ │ ├── DataMessage.java │ │ ├── MessageType.java │ │ └── AckListMessage.java │ ├── TrafficEvent.java │ ├── AckListManage.java │ ├── AckListTask.java │ ├── ResendManage.java │ ├── SendRecord.java │ ├── ClientManager.java │ ├── ConnectionUDP.java │ ├── MapSocketPorcessor.java │ ├── StreamPipe.java │ ├── Receiver.java │ ├── Sender.java │ ├── ClientControl.java │ └── Route.java │ ├── client │ ├── ClientUII.java │ ├── MapRule.java │ ├── FSClient.java │ ├── ClientConfig.java │ ├── Pipe.java │ ├── PortMapProcess.java │ ├── PortMapManager.java │ └── MapClient.java │ └── server │ ├── MapTunnelProcessor.java │ └── FSServer.java ├── .gitignore ├── classes └── artifacts │ └── finalspeed_jar │ └── finalspeed.jar ├── .project ├── .classpath └── README.md /ipseccmd.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fly9i/finalspeed/HEAD/ipseccmd.exe -------------------------------------------------------------------------------- /lib/jna.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fly9i/finalspeed/HEAD/lib/jna.jar -------------------------------------------------------------------------------- /img/offline.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fly9i/finalspeed/HEAD/img/offline.png -------------------------------------------------------------------------------- /lib/pcap4j-core.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fly9i/finalspeed/HEAD/lib/pcap4j-core.jar -------------------------------------------------------------------------------- /lib/fastjson-1.1.6.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fly9i/finalspeed/HEAD/lib/fastjson-1.1.6.jar -------------------------------------------------------------------------------- /lib/slf4j-api-1.6.6.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fly9i/finalspeed/HEAD/lib/slf4j-api-1.6.6.jar -------------------------------------------------------------------------------- /lib/slf4j-nop-1.6.1.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fly9i/finalspeed/HEAD/lib/slf4j-nop-1.6.1.jar -------------------------------------------------------------------------------- /src/META-INF/MANIFEST.MF: -------------------------------------------------------------------------------- 1 | Manifest-Version: 1.0 2 | Main-Class: net.fs.client.FSClient 3 | 4 | -------------------------------------------------------------------------------- /lib/commons-cli-1.3.1.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fly9i/finalspeed/HEAD/lib/commons-cli-1.3.1.jar -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /bin/ 2 | /client_config.json 3 | /port_map.json 4 | /*.iml 5 | /.idea/ 6 | /out/ 7 | /*.sh 8 | /fortest/ 9 | -------------------------------------------------------------------------------- /lib/pcap4j-packetfactory-static.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fly9i/finalspeed/HEAD/lib/pcap4j-packetfactory-static.jar -------------------------------------------------------------------------------- /classes/artifacts/finalspeed_jar/finalspeed.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fly9i/finalspeed/HEAD/classes/artifacts/finalspeed_jar/finalspeed.jar -------------------------------------------------------------------------------- /src/net/fs/cap/SendRecord.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 D1SM.net 2 | 3 | package net.fs.cap; 4 | 5 | public class SendRecord { 6 | 7 | int sendCount; 8 | 9 | } 10 | -------------------------------------------------------------------------------- /src/net/fs/utils/LogListener.java: -------------------------------------------------------------------------------- 1 | package net.fs.utils; 2 | 3 | public interface LogListener { 4 | 5 | public void onAppendContent(LogOutputStream los,String text); 6 | 7 | } 8 | -------------------------------------------------------------------------------- /src/net/fs/rudp/PipeListener.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 D1SM.net 2 | 3 | package net.fs.rudp; 4 | 5 | public interface PipeListener { 6 | 7 | void pipeClose(); 8 | 9 | } 10 | -------------------------------------------------------------------------------- /src/net/fs/cap/TunData.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 D1SM.net 2 | 3 | package net.fs.cap; 4 | 5 | 6 | public class TunData { 7 | 8 | TCPTun tun; 9 | 10 | byte[] data; 11 | 12 | } 13 | -------------------------------------------------------------------------------- /src/net/fs/rudp/ClientProcessorInterface.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 D1SM.net 2 | 3 | package net.fs.rudp; 4 | 5 | public interface ClientProcessorInterface { 6 | 7 | public void onMapClientClose(); 8 | 9 | } 10 | -------------------------------------------------------------------------------- /src/net/fs/rudp/ConnectionProcessor.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 D1SM.net 2 | 3 | package net.fs.rudp; 4 | 5 | 6 | 7 | public interface ConnectionProcessor { 8 | abstract void process(final ConnectionUDP conn); 9 | } 10 | -------------------------------------------------------------------------------- /src/net/fs/rudp/Trafficlistener.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 D1SM.net 2 | 3 | package net.fs.rudp; 4 | 5 | public interface Trafficlistener { 6 | 7 | public void trafficDownload(TrafficEvent event); 8 | 9 | 10 | public void trafficUpload(TrafficEvent event); 11 | 12 | } 13 | -------------------------------------------------------------------------------- /src/net/fs/rudp/MessageInterface.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 D1SM.net 2 | 3 | package net.fs.rudp; 4 | 5 | import java.net.DatagramPacket; 6 | 7 | public interface MessageInterface { 8 | public int getVer(); 9 | public int getSType(); 10 | public DatagramPacket getDatagramPacket(); 11 | } 12 | 13 | -------------------------------------------------------------------------------- /src/net/fs/client/ClientUII.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 D1SM.net 2 | 3 | package net.fs.client; 4 | 5 | public interface ClientUII { 6 | 7 | 8 | 9 | 10 | boolean login(); 11 | 12 | boolean updateNode(boolean testSpeed); 13 | 14 | boolean isOsx_fw_pf(); 15 | 16 | boolean isOsx_fw_ipfw(); 17 | 18 | } 19 | -------------------------------------------------------------------------------- /src/net/fs/cap/CapServer.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 D1SM.net 2 | 3 | package net.fs.cap; 4 | 5 | 6 | public class CapServer { 7 | 8 | CapServer(){ 9 | CapEnv capEnv=null; 10 | try { 11 | capEnv=new CapEnv(false,true); 12 | capEnv.init(); 13 | } catch (Exception e) { 14 | e.printStackTrace(); 15 | } 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /src/net/fs/cap/IPacket.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 D1SM.net 2 | 3 | package net.fs.cap; 4 | 5 | import org.pcap4j.packet.Packet; 6 | 7 | public class IPacket { 8 | 9 | int index; 10 | 11 | int sequence; 12 | 13 | int legth; 14 | 15 | Packet packet; 16 | 17 | long firstSendTime; 18 | 19 | long sendTime; 20 | 21 | long reSendCount; 22 | 23 | } 24 | -------------------------------------------------------------------------------- /src/net/fs/rudp/Constant.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 D1SM.net 2 | 3 | package net.fs.rudp; 4 | 5 | public class Constant { 6 | 7 | 8 | public static int code_success=1; 9 | 10 | public static int code_failed=0; 11 | 12 | public static int code_no_port=41; 13 | 14 | public static int code_password_error=42; 15 | 16 | static int protocal_portmap=5755682; 17 | 18 | public static int protocal_socks5proxy=544643; 19 | 20 | } 21 | -------------------------------------------------------------------------------- /.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | finalspeed 4 | 5 | 6 | 7 | 8 | 9 | org.eclipse.jdt.core.javabuilder 10 | 11 | 12 | 13 | 14 | 15 | org.eclipse.jdt.core.javanature 16 | 17 | 18 | -------------------------------------------------------------------------------- /src/net/fs/utils/MessageCheck.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 D1SM.net 2 | 3 | package net.fs.utils; 4 | 5 | import java.net.DatagramPacket; 6 | 7 | 8 | 9 | public class MessageCheck{ 10 | public static int checkVer(DatagramPacket dp){ 11 | int ver=ByteShortConvert.toShort(dp.getData(), 0); 12 | return ver; 13 | } 14 | public static int checkSType(DatagramPacket dp){ 15 | int sType=ByteShortConvert.toShort(dp.getData(), 2); 16 | return sType; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/net/fs/rudp/ConnectException.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 D1SM.net 2 | 3 | package net.fs.rudp; 4 | 5 | import net.fs.utils.MLog; 6 | 7 | public class ConnectException extends Exception{ 8 | 9 | private static final long serialVersionUID = 8735513900170495107L; 10 | String message; 11 | ConnectException(String message){ 12 | this.message=message; 13 | } 14 | @Override 15 | public void printStackTrace(){ 16 | //#MLog.println("连接异常 "+message); 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /src/net/fs/rudp/ReceivePingException.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 D1SM.net 2 | 3 | package net.fs.rudp; 4 | 5 | import net.fs.utils.MLog; 6 | 7 | public class ReceivePingException extends Exception{ 8 | /** 9 | * 10 | */ 11 | private static final long serialVersionUID = -5199731243611486228L; 12 | String message; 13 | ReceivePingException(String message){ 14 | this.message=message; 15 | } 16 | @Override 17 | public void printStackTrace(){ 18 | //#MLog.println("Ping寮傚父 "+message); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/net/fs/utils/MLog.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 D1SM.net 2 | 3 | package net.fs.utils; 4 | 5 | 6 | public class MLog { 7 | 8 | public static void info(Object str){ 9 | System.out.println(str); 10 | } 11 | 12 | // public static void println(Object str){ 13 | // System.out.println(str); 14 | // } 15 | 16 | public static void println(String str){ 17 | System.out.println(str); 18 | } 19 | 20 | // public static void println(){ 21 | // System.out.println(); 22 | // } 23 | // 24 | // public static void print(String str){ 25 | // System.out.print(str); 26 | // } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /src/net/fs/rudp/RUDPConfig.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 D1SM.net 2 | 3 | package net.fs.rudp; 4 | 5 | public class RUDPConfig { 6 | 7 | public static short protocal_ver=0; 8 | 9 | public static int packageSize=1000; 10 | 11 | public static boolean twice_udp=false; 12 | 13 | public static boolean twice_tcp=false; 14 | 15 | public static int maxWin = 5*1024; 16 | 17 | public static int ackListDelay = 5; 18 | public static int ackListSum = 300; 19 | 20 | public static boolean double_send_start = true; 21 | 22 | public static int reSendDelay_min = 100; 23 | public static float reSendDelay = 0.37f; 24 | public static int reSendTryTimes = 10; 25 | 26 | } 27 | -------------------------------------------------------------------------------- /src/net/fs/utils/ByteIntConvert.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 D1SM.net 2 | 3 | package net.fs.utils; 4 | 5 | 6 | public class ByteIntConvert { 7 | 8 | public static int toInt(byte[] b,int offset) { 9 | return b[offset + 3] & 0xff | (b[offset + 2] & 0xff) << 8 10 | | (b[offset + 1] & 0xff) << 16 | (b[offset] & 0xff) << 24; 11 | } 12 | 13 | public static void toByteArray(int n,byte[] buf,int offset) { 14 | buf[offset] = (byte) (n >> 24); 15 | buf[offset + 1] = (byte) (n >> 16); 16 | buf[offset + 2] = (byte) (n >> 8); 17 | buf[offset + 3] = (byte) n; 18 | } 19 | 20 | } 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /src/net/fs/rudp/CopiedIterator.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 D1SM.net 2 | 3 | package net.fs.rudp; 4 | 5 | import java.util.Iterator; 6 | import java.util.LinkedList; 7 | 8 | public class CopiedIterator implements Iterator { 9 | private Iterator iterator = null; 10 | public CopiedIterator(Iterator itr) { 11 | LinkedList list = new LinkedList( ); 12 | while(itr.hasNext( )) { 13 | list.add(itr.next( )); 14 | } 15 | this.iterator = list.iterator( ); 16 | } 17 | public boolean hasNext( ) { 18 | return this.iterator.hasNext( ); 19 | } 20 | public void remove( ) { 21 | throw new UnsupportedOperationException("This is a read-only iterator."); 22 | } 23 | public Object next( ) { 24 | return this.iterator.next( ); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/net/fs/rudp/UDPOutputStream.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 D1SM.net 2 | 3 | package net.fs.rudp; 4 | 5 | import java.net.InetAddress; 6 | 7 | public class UDPOutputStream { 8 | public ConnectionUDP conn; 9 | InetAddress dstIp; 10 | int dstPort; 11 | Sender sender; 12 | 13 | boolean streamClosed=false; 14 | 15 | UDPOutputStream (ConnectionUDP conn){ 16 | this.conn=conn; 17 | this.dstIp=conn.dstIp; 18 | this.dstPort=conn.dstPort; 19 | this.sender=conn.sender; 20 | } 21 | 22 | public void write(byte[] data,int offset,int length) throws ConnectException, InterruptedException { 23 | sender.sendData(data, offset,length); 24 | } 25 | 26 | public void closeStream_Local(){ 27 | sender.closeStream_Local(); 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /.classpath: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /src/net/fs/utils/ByteShortConvert.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 D1SM.net 2 | 3 | package net.fs.utils; 4 | 5 | public final class ByteShortConvert { 6 | 7 | public static byte[] toByteArray(short i,byte[] b,int offset) { 8 | b[offset] = (byte) (i >> 8); 9 | b[offset + 1] = (byte) (i >> 0); 10 | return b; 11 | } 12 | 13 | 14 | 15 | public static short toShort(byte[] b,int offset) { 16 | return (short) (((b[offset] << 8) | b[offset + 1] & 0xff)); 17 | } 18 | 19 | //无符号 20 | public static byte[] toByteArrayUnsigned(int s,byte[] b,int offset) { 21 | b[offset] = (byte) (s >> 8); 22 | b[offset+1] = (byte) (s >> 0); 23 | return b; 24 | } 25 | 26 | //无符号 27 | public static int toShortUnsigned(byte[] b,int offset) { 28 | int i = 0; 29 | i |= b[offset+0] & 0xFF; 30 | i <<= 8; 31 | i |= b[offset+1] & 0xFF; 32 | return i; 33 | } 34 | 35 | 36 | } 37 | -------------------------------------------------------------------------------- /src/net/fs/client/MapRule.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 D1SM.net 2 | 3 | package net.fs.client; 4 | 5 | import java.io.Serializable; 6 | import java.net.ServerSocket; 7 | 8 | public class MapRule implements Serializable{ 9 | 10 | /** 11 | * 12 | */ 13 | private static final long serialVersionUID = -3504577683070928480L; 14 | 15 | int listen_port; 16 | 17 | int dst_port; 18 | 19 | String name; 20 | 21 | boolean using=false; 22 | 23 | ServerSocket serverSocket; 24 | 25 | public int getListen_port() { 26 | return listen_port; 27 | } 28 | 29 | public void setListen_port(int listen_port) { 30 | this.listen_port = listen_port; 31 | } 32 | 33 | public int getDst_port() { 34 | return dst_port; 35 | } 36 | 37 | public void setDst_port(int dst_port) { 38 | this.dst_port = dst_port; 39 | } 40 | 41 | public String getName() { 42 | return name; 43 | } 44 | 45 | public void setName(String name) { 46 | this.name = name; 47 | } 48 | 49 | } 50 | -------------------------------------------------------------------------------- /src/net/fs/client/FSClient.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 D1SM.net 2 | 3 | package net.fs.client; 4 | 5 | import org.apache.commons.cli.*; 6 | 7 | public class FSClient { 8 | 9 | public static void main(String[] args) { 10 | CommandLineParser parser = new DefaultParser(); 11 | Options options = new Options(); 12 | options.addOption("b", "back", false, "有此参数则运行CLI版本"); 13 | options.addOption("min", "minimize",false, "启动窗口最小化"); 14 | CommandLine commandLine = null; 15 | try { 16 | commandLine = parser.parse(options, args); 17 | } catch (ParseException e) { 18 | HelpFormatter helpFormatter = new HelpFormatter(); 19 | helpFormatter.printHelp("java -jar finalspeed.jar [-b/--back]", options); 20 | System.exit(0); 21 | } 22 | 23 | boolean visible=!commandLine.hasOption("b"); 24 | boolean min=commandLine.hasOption("min"); 25 | 26 | new ClientUI(visible,min); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/net/fs/rudp/ConnInfo.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 D1SM.net 2 | 3 | package net.fs.rudp; 4 | 5 | import net.fs.rudp.StreamPipe.HttpHost; 6 | 7 | public class ConnInfo { 8 | 9 | 10 | String requestHost=null; 11 | 12 | String requestPath=null; 13 | 14 | boolean http=false; 15 | 16 | HttpHost host=null; 17 | 18 | public String getRequestHost() { 19 | return requestHost; 20 | } 21 | 22 | public void setRequestHost(String requestHost) { 23 | this.requestHost = requestHost; 24 | } 25 | 26 | public String getRequestPath() { 27 | return requestPath; 28 | } 29 | 30 | public void setRequestPath(String requestPath) { 31 | this.requestPath = requestPath; 32 | } 33 | 34 | public boolean isHttp() { 35 | return http; 36 | } 37 | 38 | public void setHttp(boolean http) { 39 | this.http = http; 40 | } 41 | 42 | public HttpHost getHost() { 43 | return host; 44 | } 45 | 46 | public void setHost(HttpHost host) { 47 | this.host = host; 48 | } 49 | 50 | } 51 | -------------------------------------------------------------------------------- /src/net/fs/rudp/ResendItem.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 D1SM.net 2 | 3 | package net.fs.rudp; 4 | 5 | public class ResendItem { 6 | 7 | int count; 8 | 9 | ConnectionUDP conn; 10 | 11 | int sequence; 12 | 13 | long resendTime; 14 | 15 | ResendItem(ConnectionUDP conn,int sequence){ 16 | this.conn=conn; 17 | this.sequence=sequence; 18 | } 19 | 20 | void addCount(){ 21 | count++; 22 | } 23 | 24 | public int getCount() { 25 | return count; 26 | } 27 | 28 | public void setCount(int count) { 29 | this.count = count; 30 | } 31 | 32 | public ConnectionUDP getConn() { 33 | return conn; 34 | } 35 | 36 | public void setConn(ConnectionUDP conn) { 37 | this.conn = conn; 38 | } 39 | 40 | public int getSequence() { 41 | return sequence; 42 | } 43 | 44 | public void setSequence(int sequence) { 45 | this.sequence = sequence; 46 | } 47 | 48 | public long getResendTime() { 49 | return resendTime; 50 | } 51 | 52 | public void setResendTime(long resendTime) { 53 | this.resendTime = resendTime; 54 | } 55 | 56 | } 57 | -------------------------------------------------------------------------------- /src/net/fs/rudp/UDPInputStream.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 D1SM.net 2 | 3 | package net.fs.rudp; 4 | 5 | import java.net.DatagramSocket; 6 | import java.net.InetAddress; 7 | 8 | public class UDPInputStream { 9 | 10 | DatagramSocket ds; 11 | InetAddress dstIp; 12 | int dstPort; 13 | Receiver receiver; 14 | 15 | boolean streamClosed=false; 16 | 17 | ConnectionUDP conn; 18 | 19 | UDPInputStream(ConnectionUDP conn){ 20 | this.conn=conn; 21 | receiver=conn.receiver; 22 | } 23 | 24 | public int read(byte[] b, int off, int len) throws ConnectException, InterruptedException { 25 | byte[] b2=null; 26 | b2 = read2(); 27 | if(len listeners=new HashSet(); 10 | 11 | StringBuffer buffer=new StringBuffer(); 12 | 13 | public LogOutputStream(OutputStream out) { 14 | super(out); 15 | } 16 | 17 | @Override 18 | public void write(byte[] buf, int off, int len) { 19 | super.write(buf, off, len); 20 | fireEvent(new String(buf, off, len)); 21 | } 22 | 23 | private void fireEvent(String text){ 24 | if(buffer!=null&&buffer.length()<10000){ 25 | buffer.append(text); 26 | } 27 | for(LogListener listener:listeners){ 28 | listener.onAppendContent(this,text); 29 | } 30 | } 31 | 32 | public void addListener(LogListener listener){ 33 | listeners.add(listener); 34 | } 35 | 36 | public void remvoeListener(LogListener listener){ 37 | listeners.remove(listener); 38 | } 39 | 40 | public StringBuffer getBuffer() { 41 | return buffer; 42 | } 43 | 44 | public void setBuffer(StringBuffer buffer) { 45 | this.buffer = buffer; 46 | } 47 | 48 | 49 | } 50 | -------------------------------------------------------------------------------- /src/net/fs/rudp/TrafficEvent.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 D1SM.net 2 | 3 | package net.fs.rudp; 4 | 5 | public class TrafficEvent { 6 | 7 | long eventId; 8 | 9 | int traffic; 10 | 11 | public static int type_downloadTraffic=10; 12 | 13 | public static int type_uploadTraffic=11; 14 | 15 | int type=type_downloadTraffic; 16 | 17 | String userId; 18 | 19 | TrafficEvent(long eventId,int traffic,int type){ 20 | this(null,eventId,traffic,type); 21 | } 22 | 23 | public TrafficEvent(String userId,long eventId,int traffic,int type){ 24 | this.userId=userId; 25 | this.eventId=eventId; 26 | this.traffic=traffic; 27 | this.type=type; 28 | } 29 | 30 | public String getUserId() { 31 | return userId; 32 | } 33 | 34 | public void setUserId(String userId) { 35 | this.userId = userId; 36 | } 37 | 38 | public int getType() { 39 | return type; 40 | } 41 | 42 | public long getEventId() { 43 | return eventId; 44 | } 45 | 46 | public void setEventId(long eventId) { 47 | this.eventId = eventId; 48 | } 49 | 50 | public int getTraffic() { 51 | return traffic; 52 | } 53 | 54 | public void setTraffic(int traffic) { 55 | this.traffic = traffic; 56 | } 57 | 58 | 59 | 60 | } 61 | -------------------------------------------------------------------------------- /src/net/fs/rudp/message/PingMessage2.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 D1SM.net 2 | 3 | package net.fs.rudp.message; 4 | 5 | import java.net.DatagramPacket; 6 | 7 | import net.fs.utils.ByteIntConvert; 8 | import net.fs.utils.ByteShortConvert; 9 | 10 | 11 | 12 | public class PingMessage2 extends Message{ 13 | 14 | public short sType=net.fs.rudp.message.MessageType.sType_PingMessage2; 15 | 16 | byte[] dpData=new byte[16]; 17 | 18 | int pingId; 19 | 20 | public PingMessage2(int connectId,int clientId,int pingId){ 21 | ByteShortConvert.toByteArray(ver, dpData, 0); //add: ver 22 | ByteShortConvert.toByteArray(sType, dpData, 2); //add: service type 23 | ByteIntConvert.toByteArray(connectId, dpData, 4); //add: sequence 24 | ByteIntConvert.toByteArray(clientId, dpData, 8); //add: sequence 25 | ByteIntConvert.toByteArray(pingId, dpData, 12); //add: sequence 26 | dp=new DatagramPacket(dpData,dpData.length); 27 | } 28 | 29 | public PingMessage2(DatagramPacket dp){ 30 | this.dp=dp; 31 | dpData=dp.getData(); 32 | ver=ByteShortConvert.toShort(dpData, 0); 33 | sType=ByteShortConvert.toShort(dpData, 2); 34 | connectId=ByteIntConvert.toInt(dpData, 4); 35 | clientId=ByteIntConvert.toInt(dpData, 8); 36 | pingId=ByteIntConvert.toInt(dpData, 12); 37 | } 38 | 39 | public int getPingId() { 40 | return pingId; 41 | } 42 | 43 | public void setPingId(int pingId) { 44 | this.pingId = pingId; 45 | } 46 | 47 | } 48 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | __删除finalspeed对awt/swing的依赖,使之可以在没有x11的环境下,在命令行中直接运行__ 2 | 3 | 下载去除依赖后的 finalspeed点击下载最新版本 [finalspeed下载](https://github.com/fly9i/finalspeed/releases) 4 | 5 | 具体方法: 6 | 7 | java -jar finalspeed.jar -b 8 | # FinalSpeed 9 | 10 | FinalSpeed是高速双边加速软件,可加速所有基于tcp协议的网络服务,在高丢包和高延迟环境下,仍可达到90%的物理带宽利用率,即使高峰时段也能轻松跑满带宽. 11 | 12 | ### 安装教程 13 | [客户端安装说明](http://www.d1sm.net/thread-7-1-1.html) 14 |
15 | [服务端安装说明](http://www.d1sm.net/thread-8-1-1.html) 16 | 17 | ### 使用帮助 18 | ``` 19 | 需要管理员权限 20 | java -jar finalspeed.jar -b 运行CLI版 21 | java -jar finalspeed.jar 运行GUI版 22 | ``` 23 | 24 | CLI版本需要手动配置, 且配置文件与finalspeed必须处在同一目录下. 25 | clien_config.json 26 | ``` 27 | { 28 | // 下载速度,单位是 B,字节。这里换算起来就是 11MB。请把这里改成本机的下载速度 29 | "download_speed": 11200698, 30 | // 协议:tcp 或 udp。注意:服务端如果是 OpenVZ 架构的话,则只支持 udp。 31 | "protocal": "udp", 32 | // 服务器地址 33 | "server_address": "1.2.3.4", 34 | // 一般不需要更改,保持默认即可。 35 | "server_port": 150, 36 | // 不需要更改,保持默认即可。 37 | "socks5_port": 1083, 38 | // 上传速度,单位是 B,字节。 39 | "upload_speed": 357469 40 | } 41 | ``` 42 | port_map.json 43 | ``` 44 | { 45 | "map_list": [ 46 | { 47 | // 要加速的服务器端口 48 | "dst_port": 12345, 49 | // 本地端口 50 | "listen_port": 1099, 51 | // 备注信息 52 | "name": "ss" 53 | }, 54 | { 55 | "dst_port": 23456, 56 | "listen_port": 2200, 57 | "name": "ssh" 58 | } 59 | ] 60 | } 61 | ``` 62 | 63 | 论坛 http://www.d1sm.net/forum-44-1.html 64 | -------------------------------------------------------------------------------- /src/net/fs/rudp/AckListManage.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 D1SM.net 2 | 3 | package net.fs.rudp; 4 | 5 | import java.util.HashMap; 6 | import java.util.Iterator; 7 | 8 | public class AckListManage implements Runnable{ 9 | Thread mainThread; 10 | HashMap taskTable; 11 | public AckListManage(){ 12 | taskTable=new HashMap(); 13 | mainThread=new Thread(this); 14 | mainThread.start(); 15 | } 16 | 17 | synchronized void addAck(ConnectionUDP conn,int sequence){ 18 | if(!taskTable.containsKey(conn.connectId)){ 19 | AckListTask at=new AckListTask(conn); 20 | taskTable.put(conn.connectId, at); 21 | } 22 | AckListTask at=taskTable.get(conn.connectId); 23 | at.addAck(sequence); 24 | } 25 | 26 | synchronized void addLastRead(ConnectionUDP conn){ 27 | if(!taskTable.containsKey(conn.connectId)){ 28 | AckListTask at=new AckListTask(conn); 29 | taskTable.put(conn.connectId, at); 30 | } 31 | } 32 | 33 | public void run(){ 34 | while(true){ 35 | synchronized (this){ 36 | Iterator it=taskTable.keySet().iterator(); 37 | while(it.hasNext()){ 38 | int id=it.next(); 39 | AckListTask at=taskTable.get(id); 40 | at.run(); 41 | } 42 | taskTable.clear(); 43 | taskTable=null; 44 | taskTable=new HashMap(); 45 | } 46 | 47 | try { 48 | Thread.sleep(RUDPConfig.ackListDelay); 49 | } catch (InterruptedException e) { 50 | e.printStackTrace(); 51 | } 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/net/fs/rudp/message/CloseMessage_Stream.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 D1SM.net 2 | 3 | package net.fs.rudp.message; 4 | 5 | 6 | import java.net.DatagramPacket; 7 | 8 | import net.fs.utils.ByteIntConvert; 9 | import net.fs.utils.ByteShortConvert; 10 | 11 | 12 | 13 | 14 | 15 | 16 | public class CloseMessage_Stream extends Message{ 17 | 18 | public short sType=net.fs.rudp.message.MessageType.sType_CloseMessage_Stream; 19 | 20 | byte [] data; 21 | byte [] dpData; 22 | 23 | int closeOffset; 24 | 25 | public CloseMessage_Stream(int connectId,int clientId,int closeOffset){ 26 | byte[] dpData=new byte[16]; 27 | this.clientId=clientId; 28 | this.connectId=connectId; 29 | ByteShortConvert.toByteArray(ver, dpData, 0); //add: ver 30 | ByteShortConvert.toByteArray(sType, dpData, 2); //add: service type 31 | ByteIntConvert.toByteArray(connectId, dpData, 4); //add: sequence 32 | ByteIntConvert.toByteArray(clientId, dpData, 8); //add: sequence 33 | ByteIntConvert.toByteArray(closeOffset, dpData, 12); //add: sequence 34 | dp=new DatagramPacket(dpData,dpData.length); 35 | ////#MLog.println("vCloseMessageaaa"+clientId+"v"); 36 | } 37 | 38 | public CloseMessage_Stream(DatagramPacket dp){ 39 | this.dp=dp; 40 | dpData=dp.getData(); 41 | ver=ByteShortConvert.toShort(dpData, 0); 42 | sType=ByteShortConvert.toShort(dpData, 2); 43 | 44 | connectId=ByteIntConvert.toInt(dpData, 4); 45 | clientId=ByteIntConvert.toInt(dpData, 8); 46 | closeOffset=ByteIntConvert.toInt(dpData, 12); 47 | ////#MLog.println("vCloseMessagebbb"+clientId+"v"); 48 | } 49 | 50 | public int getCloseOffset(){ 51 | return closeOffset; 52 | } 53 | 54 | } 55 | -------------------------------------------------------------------------------- /src/net/fs/rudp/AckListTask.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 D1SM.net 2 | 3 | package net.fs.rudp; 4 | 5 | import java.util.ArrayList; 6 | import java.util.HashSet; 7 | 8 | import net.fs.rudp.message.AckListMessage; 9 | 10 | 11 | 12 | public class AckListTask { 13 | ConnectionUDP conn; 14 | AckListMessage alm; 15 | int lastRead=0; 16 | ArrayList ackList; 17 | @SuppressWarnings("unchecked") 18 | HashSet set; 19 | AckListTask(ConnectionUDP conn){ 20 | this.conn=conn; 21 | ackList=new ArrayList(); 22 | set=new HashSet(); 23 | } 24 | 25 | synchronized void addAck(int sequence){ 26 | ////#MLog.println("sendACK "+sequence); 27 | if(!set.contains(sequence)){ 28 | ackList.add(sequence); 29 | set.add(sequence); 30 | } 31 | } 32 | 33 | synchronized void run(){ 34 | int offset=0; 35 | int packetLength=RUDPConfig.ackListSum; 36 | int length=ackList.size(); 37 | ////#MLog.println("ffffffffaaaaaaaaa "+length); 38 | int sum=(length/packetLength); 39 | if(length%packetLength!=0){ 40 | sum+=1; 41 | } 42 | if(sum==0){ 43 | sum=1; 44 | } 45 | int len=packetLength; 46 | if(length<=len){ 47 | conn.sender.sendALMessage(ackList); 48 | conn.sender.sendALMessage(ackList); 49 | }else{ 50 | for(int i=0;i nl=copy(offset,len,ackList); 52 | conn.sender.sendALMessage(nl); 53 | conn.sender.sendALMessage(nl); 54 | // conn.sender.sendALMessage(nl); 55 | // conn.sender.sendALMessage(nl); 56 | // conn.sender.sendALMessage(nl); 57 | offset+=packetLength; 58 | ////#MLog.println("fffffffffa "+nl.size()); 59 | if(offset+len>length){ 60 | len=length-(sum-1)*packetLength; 61 | } 62 | } 63 | } 64 | } 65 | 66 | ArrayList copy(int offset,int length,ArrayList ackList){ 67 | ArrayList nl= new ArrayList(); 68 | for(int i=0;i taskList=new LinkedBlockingQueue(); 19 | 20 | public ResendManage(){ 21 | Route.es.execute(this); 22 | } 23 | 24 | public void addTask(final ConnectionUDP conn,final int sequence){ 25 | ResendItem ri=new ResendItem(conn, sequence); 26 | ri.setResendTime(getNewResendTime(conn)); 27 | taskList.add(ri); 28 | } 29 | 30 | long getNewResendTime(ConnectionUDP conn){ 31 | int delayAdd=conn.clientControl.pingDelay+(int) ((float)conn.clientControl.pingDelay*RUDPConfig.reSendDelay); 32 | if(delayAdd0){ 46 | Thread.sleep(sleepTime); 47 | } 48 | ri.addCount(); 49 | 50 | if(ri.conn.sender.getDataMessage(ri.sequence)!=null){ 51 | 52 | if(!ri.conn.stopnow){ 53 | //多线程重发容易内存溢出 54 | // Route.es.execute(new Runnable() { 55 | // 56 | // @Override 57 | // public void run() { 58 | // ri.conn.sender.reSend(ri.sequence,ri.getCount()); 59 | // } 60 | // 61 | // }); 62 | ri.conn.sender.reSend(ri.sequence,ri.getCount()); 63 | } 64 | 65 | } 66 | if(ri.getCount()0){ 32 | dropRate=(float)droped/getSendSize(); 33 | } 34 | return dropRate; 35 | } 36 | 37 | float getResendRate(){ 38 | float resendRate=0; 39 | if(getSendSize_First()>0){ 40 | resendRate=(float)getResended()/getSendSize_First(); 41 | } 42 | return resendRate; 43 | } 44 | 45 | void addResended(int size){ 46 | resended+=size; 47 | } 48 | 49 | void addSended(int size){ 50 | sendCount++; 51 | sendSize+=size; 52 | } 53 | 54 | void addSended_First(int size){ 55 | sendSize_First+=size; 56 | } 57 | 58 | public int getSendSize() { 59 | return sendSize; 60 | } 61 | 62 | public int getSendCount() { 63 | return sendCount; 64 | } 65 | 66 | public int getAckedSize() { 67 | return ackedSize; 68 | } 69 | 70 | //接收到的数据大小 71 | public void setAckedSize(int ackedSize) { 72 | if(ackedSize>this.ackedSize){ 73 | this.ackedSize = ackedSize; 74 | } 75 | } 76 | 77 | public int getTimeId() { 78 | return timeId; 79 | } 80 | 81 | public void setTimeId(int timeId) { 82 | this.timeId = timeId; 83 | } 84 | 85 | public int getSpeed() { 86 | return speed; 87 | } 88 | 89 | public void setSpeed(int speed) { 90 | this.speed = speed; 91 | speedRecored=true; 92 | } 93 | 94 | public boolean isSpeedRecored(){ 95 | return speedRecored; 96 | } 97 | 98 | public int getResended() { 99 | return resended; 100 | } 101 | 102 | public void setResended(int resended) { 103 | this.resended = resended; 104 | } 105 | 106 | public int getSendSize_First() { 107 | return sendSize_First; 108 | } 109 | 110 | public void setSendSize_First(int sendSize_First) { 111 | this.sendSize_First = sendSize_First; 112 | } 113 | 114 | } 115 | -------------------------------------------------------------------------------- /src/net/fs/client/ClientConfig.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 D1SM.net 2 | 3 | package net.fs.client; 4 | 5 | public class ClientConfig { 6 | 7 | String serverAddress=""; 8 | 9 | int serverPort; 10 | 11 | int remotePort; 12 | 13 | int downloadSpeed,uploadSpeed; 14 | 15 | boolean direct_cn=true; 16 | 17 | int socks5Port=1083; 18 | 19 | String remoteAddress; 20 | 21 | String protocal="tcp"; 22 | 23 | boolean autoStart=false; 24 | 25 | public String getServerAddress() { 26 | return serverAddress; 27 | } 28 | 29 | public void setServerAddress(String serverAddress) { 30 | this.serverAddress = serverAddress; 31 | } 32 | 33 | public int getServerPort() { 34 | return serverPort; 35 | } 36 | 37 | public void setServerPort(int serverPort) { 38 | this.serverPort = serverPort; 39 | } 40 | 41 | public int getRemotePort() { 42 | return remotePort; 43 | } 44 | 45 | public void setRemotePort(int remotePort) { 46 | this.remotePort = remotePort; 47 | } 48 | 49 | public boolean isDirect_cn() { 50 | return direct_cn; 51 | } 52 | 53 | public void setDirect_cn(boolean direct_cn) { 54 | this.direct_cn = direct_cn; 55 | } 56 | 57 | public int getDownloadSpeed() { 58 | return downloadSpeed; 59 | } 60 | 61 | public void setDownloadSpeed(int downloadSpeed) { 62 | this.downloadSpeed = downloadSpeed; 63 | } 64 | 65 | public int getUploadSpeed() { 66 | return uploadSpeed; 67 | } 68 | 69 | public void setUploadSpeed(int uploadSpeed) { 70 | this.uploadSpeed = uploadSpeed; 71 | } 72 | 73 | public int getSocks5Port() { 74 | return socks5Port; 75 | } 76 | 77 | public void setSocks5Port(int socks5Port) { 78 | this.socks5Port = socks5Port; 79 | } 80 | 81 | public String getRemoteAddress() { 82 | return remoteAddress; 83 | } 84 | 85 | public void setRemoteAddress(String remoteAddress) { 86 | this.remoteAddress = remoteAddress; 87 | } 88 | 89 | public String getProtocal() { 90 | return protocal; 91 | } 92 | 93 | public void setProtocal(String protocal) { 94 | this.protocal = protocal; 95 | } 96 | 97 | public boolean isAutoStart() { 98 | return autoStart; 99 | } 100 | 101 | public void setAutoStart(boolean autoStart) { 102 | this.autoStart = autoStart; 103 | } 104 | 105 | } 106 | -------------------------------------------------------------------------------- /src/net/fs/rudp/ClientManager.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 D1SM.net 2 | 3 | package net.fs.rudp; 4 | 5 | import java.net.InetAddress; 6 | import java.util.Date; 7 | import java.util.HashMap; 8 | import java.util.Iterator; 9 | 10 | import net.fs.utils.MLog; 11 | 12 | 13 | public class ClientManager { 14 | 15 | HashMap clientTable=new HashMap(); 16 | 17 | Thread mainThread; 18 | 19 | Route route; 20 | 21 | int receivePingTimeout=8*1000; 22 | 23 | int sendPingInterval=1*1000; 24 | 25 | Object syn_clientTable=new Object(); 26 | 27 | ClientManager(Route route){ 28 | this.route=route; 29 | mainThread=new Thread(){ 30 | @Override 31 | public void run(){ 32 | while(true){ 33 | try { 34 | Thread.sleep(1000); 35 | } catch (InterruptedException e) { 36 | e.printStackTrace(); 37 | } 38 | scanClientControl(); 39 | } 40 | } 41 | }; 42 | mainThread.start(); 43 | } 44 | 45 | void scanClientControl(){ 46 | Iterator it=getClientTableIterator(); 47 | long current=System.currentTimeMillis(); 48 | //MLog.println("ffffffffffff "+clientTable.size()); 49 | while(it.hasNext()){ 50 | ClientControl cc=clientTable.get(it.next()); 51 | if(cc!=null){ 52 | if(current-cc.getLastReceivePingTime()sendPingInterval){ 54 | cc.sendPingMessage(); 55 | } 56 | }else { 57 | //超时关闭client 58 | MLog.println("超时关闭client "+cc.dstIp.getHostAddress()+":"+cc.dstPort+" "+new Date()); 59 | // System.exit(0); 60 | synchronized (syn_clientTable) { 61 | cc.close(); 62 | } 63 | } 64 | } 65 | } 66 | } 67 | 68 | void removeClient(int clientId){ 69 | clientTable.remove(clientId); 70 | } 71 | 72 | Iterator getClientTableIterator(){ 73 | Iterator it=null; 74 | synchronized (syn_clientTable) { 75 | it=new CopiedIterator(clientTable.keySet().iterator()); 76 | } 77 | return it; 78 | } 79 | 80 | ClientControl getClientControl(int clientId,InetAddress dstIp,int dstPort){ 81 | ClientControl c=clientTable.get(clientId); 82 | if(c==null){ 83 | c=new ClientControl(route,clientId,dstIp,dstPort); 84 | synchronized (syn_clientTable) { 85 | clientTable.put(clientId, c); 86 | } 87 | } 88 | return c; 89 | } 90 | 91 | } 92 | -------------------------------------------------------------------------------- /src/net/fs/client/Pipe.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 D1SM.net 2 | 3 | package net.fs.client; 4 | 5 | import java.io.InputStream; 6 | import java.io.OutputStream; 7 | import java.util.HashMap; 8 | import java.util.concurrent.ExecutorService; 9 | import java.util.concurrent.SynchronousQueue; 10 | import java.util.concurrent.ThreadPoolExecutor; 11 | import java.util.concurrent.TimeUnit; 12 | 13 | import net.fs.rudp.ConnectionUDP; 14 | import net.fs.rudp.UDPInputStream; 15 | import net.fs.rudp.UDPOutputStream; 16 | import net.fs.utils.MLog; 17 | 18 | public class Pipe { 19 | 20 | 21 | int lastTime=-1; 22 | 23 | 24 | boolean readed=false; 25 | 26 | public Pipe p2; 27 | 28 | byte[] pv; 29 | 30 | int pvl; 31 | 32 | int readedLength; 33 | 34 | String successMessage; 35 | 36 | int dstPort=-1; 37 | 38 | public void pipe(InputStream is,UDPOutputStream tos,int initSpeed,final Pipe p2) throws Exception{ 39 | 40 | int len=0; 41 | byte[] buf=new byte[100*1024]; 42 | boolean sendeda=false; 43 | while((len=is.read(buf))>0){ 44 | readed=true; 45 | if(!sendeda){ 46 | sendeda=true; 47 | } 48 | tos.write(buf, 0, len); 49 | } 50 | } 51 | 52 | 53 | 54 | void sendSleep(long startTime,int speed,int length){ 55 | long needTime=(long) (1000f*length/speed); 56 | long usedTime=System.currentTimeMillis()-startTime; 57 | if(usedTime0){ 75 | readedLength+=len; 76 | if(!sendedb){ 77 | pv=buf; 78 | pvl=len; 79 | sendedb=true; 80 | } 81 | if(dstPort>0){ 82 | if(ClientUI.ui!=null){ 83 | if(!msged){ 84 | msged=true; 85 | String msg="端口"+dstPort+"连接成功"; 86 | MLog.println(msg); 87 | } 88 | 89 | } 90 | } 91 | os.write(buf, 0, len); 92 | if(!sended){ 93 | sended=true; 94 | } 95 | } 96 | } 97 | 98 | 99 | 100 | public int getReadedLength() { 101 | return readedLength; 102 | } 103 | 104 | 105 | 106 | public void setDstPort(int dstPort) { 107 | this.dstPort = dstPort; 108 | } 109 | 110 | } 111 | -------------------------------------------------------------------------------- /src/net/fs/utils/NetStatus.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 D1SM.net 2 | 3 | package net.fs.utils; 4 | 5 | import java.util.Vector; 6 | 7 | 8 | public class NetStatus { 9 | 10 | public long uploadSum; 11 | public long downloadSum; 12 | 13 | Thread mainThread; 14 | 15 | int averageTime; 16 | 17 | Vector speedList; 18 | SpeedUnit currentUnit; 19 | 20 | public int upSpeed=0; 21 | public int downSpeed=0; 22 | 23 | public NetStatus(){ 24 | this(2); 25 | } 26 | 27 | public NetStatus(int averageTime){ 28 | this.averageTime=averageTime; 29 | speedList=new Vector(); 30 | for(int i=0;i1000){ 43 | ////#MLog.println("yyyyyyyyyyy "); 44 | lastTime=System.currentTimeMillis(); 45 | calcuSpeed(); 46 | } 47 | try { 48 | Thread.sleep(100); 49 | } catch (InterruptedException e) { 50 | // e.printStackTrace(); 51 | break; 52 | } 53 | } 54 | } 55 | }; 56 | mainThread.start(); 57 | } 58 | 59 | public void stop(){ 60 | mainThread.interrupt(); 61 | } 62 | 63 | 64 | public int getUpSpeed() { 65 | return upSpeed; 66 | } 67 | 68 | public void setUpSpeed(int upSpeed) { 69 | this.upSpeed = upSpeed; 70 | } 71 | 72 | public int getDownSpeed() { 73 | return downSpeed; 74 | } 75 | 76 | public void setDownSpeed(int downSpeed) { 77 | this.downSpeed = downSpeed; 78 | } 79 | 80 | 81 | void calcuSpeed(){ 82 | int ds = 0,us=0; 83 | for(SpeedUnit unit:speedList){ 84 | ds+=unit.downSum; 85 | us+=unit.upSum; 86 | } 87 | upSpeed=(int) ((float)us/speedList.size()); 88 | downSpeed=(int)(float)ds/speedList.size(); 89 | 90 | speedList.remove(0); 91 | SpeedUnit unit=new SpeedUnit(); 92 | currentUnit=unit; 93 | speedList.add(unit); 94 | } 95 | 96 | public void addDownload(int sum){ 97 | downloadSum+=sum; 98 | currentUnit.addDown(sum); 99 | } 100 | 101 | public void addUpload(int sum){ 102 | uploadSum+=sum; 103 | currentUnit.addUp(sum); 104 | } 105 | 106 | public void sendAvail(){ 107 | 108 | } 109 | 110 | public void receiveAvail(){ 111 | 112 | } 113 | 114 | public void setUpLimite(int speed){ 115 | 116 | } 117 | 118 | public void setDownLimite(int speed){ 119 | 120 | } 121 | } 122 | 123 | 124 | class SpeedUnit{ 125 | int downSum; 126 | int upSum; 127 | SpeedUnit(){ 128 | 129 | } 130 | 131 | void addUp(int n){ 132 | upSum+=n; 133 | } 134 | 135 | void addDown(int n){ 136 | downSum+=n; 137 | } 138 | } 139 | 140 | -------------------------------------------------------------------------------- /src/net/fs/utils/Tools.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 D1SM.net 2 | 3 | package net.fs.utils; 4 | 5 | import java.net.HttpURLConnection; 6 | import java.net.URL; 7 | 8 | import javax.net.ssl.HostnameVerifier; 9 | import javax.net.ssl.HttpsURLConnection; 10 | import javax.net.ssl.SSLSession; 11 | 12 | 13 | public class Tools { 14 | 15 | public static HttpURLConnection getConnection(String urlString) throws Exception{ 16 | URL url = new URL(urlString); 17 | HttpURLConnection conn = null; 18 | if(urlString.startsWith("http://")){ 19 | conn = (HttpURLConnection) url.openConnection(); 20 | }else if(urlString.startsWith("https://")){ 21 | HttpsURLConnection conns=(HttpsURLConnection)url.openConnection(); 22 | conns.setHostnameVerifier(new HostnameVerifier() { 23 | public boolean verify(String hostname, SSLSession session) { 24 | return true; 25 | } 26 | }); 27 | conn=conns; 28 | } 29 | if(conn!=null){ 30 | conn.setConnectTimeout(10*1000); 31 | conn.setReadTimeout(10*1000); 32 | conn.setRequestMethod("POST"); 33 | conn.setDoInput(true); 34 | conn.setDoOutput(true); 35 | conn.setUseCaches(false); 36 | } 37 | return conn; 38 | } 39 | 40 | public static String getMD5(String str) { 41 | byte[] source=str.getBytes(); 42 | return getMD5(source); 43 | } 44 | 45 | public static String getMD5(byte[] source) { 46 | String s = null; 47 | char hexDigits[] = { 48 | '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; 49 | try 50 | { 51 | java.security.MessageDigest md = java.security.MessageDigest.getInstance( "MD5" ); 52 | md.update( source ); 53 | byte tmp[] = md.digest(); 54 | char str[] = new char[16 * 2]; 55 | int k = 0; 56 | for (int i = 0; i < 16; i++) { 57 | byte byte0 = tmp[i]; 58 | str[k++] = hexDigits[byte0 >>> 4 & 0xf]; 59 | str[k++] = hexDigits[byte0 & 0xf]; 60 | } 61 | s = new String(str); 62 | 63 | }catch( Exception e ) 64 | { 65 | e.printStackTrace(); 66 | } 67 | return s; 68 | } 69 | 70 | 71 | public static String getSizeStringKB(long size){ 72 | int gb=(int) (size/(1024*1024*1024)); 73 | int gbl=(int) (size%(1024*1024*1024)); 74 | int mb=gbl/(1024*1024); 75 | int mbl=gbl%(1024*1024); 76 | int kb=mbl/(1024); 77 | String ls=""; 78 | if(gb>0){ 79 | ls+=gb+","; 80 | } 81 | if(mb>0){ 82 | String mbs=""; 83 | if(gb>0){ 84 | if(mb<10){ 85 | mbs+="00"; 86 | }else if(mb<100){ 87 | mbs+="0"; 88 | } 89 | } 90 | mbs+=mb; 91 | ls+=mbs+","; 92 | }else{ 93 | if(gb>0){ 94 | ls+="000,"; 95 | } 96 | } 97 | 98 | if(kb>0){ 99 | String kbs=""; 100 | if(gb>0|mb>0){ 101 | if(kb<10){ 102 | kbs+="00"; 103 | }else if(kb<100){ 104 | kbs+="0"; 105 | } 106 | } 107 | kbs+=kb; 108 | ls+=kbs+" KB"; 109 | }else{ 110 | if(mb>0|gb>0){ 111 | ls+="000 KB"; 112 | } 113 | } 114 | if(size==0){ 115 | ls+=0+" KB"; 116 | } 117 | if(size<1024){ 118 | //ls=size+" b"; 119 | ls=0+" KB"; 120 | } 121 | return ls; 122 | } 123 | 124 | } 125 | -------------------------------------------------------------------------------- /src/net/fs/cap/TunManager.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 D1SM.net 2 | 3 | package net.fs.cap; 4 | 5 | import java.util.HashMap; 6 | import java.util.Iterator; 7 | 8 | import net.fs.rudp.CopiedIterator; 9 | import net.fs.utils.MLog; 10 | 11 | public class TunManager { 12 | 13 | HashMap connTable=new HashMap(); 14 | 15 | static TunManager tunManager; 16 | 17 | { 18 | tunManager=this; 19 | } 20 | 21 | TCPTun defaultTcpTun; 22 | 23 | Thread scanThread; 24 | 25 | Object syn_scan=new Object(); 26 | 27 | CapEnv capEnv; 28 | 29 | { 30 | scanThread=new Thread(){ 31 | public void run(){ 32 | while(true){ 33 | try { 34 | Thread.sleep(1000); 35 | } catch (InterruptedException e) { 36 | e.printStackTrace(); 37 | } 38 | scan(); 39 | } 40 | } 41 | }; 42 | scanThread.start(); 43 | } 44 | 45 | TunManager(CapEnv capEnv){ 46 | this.capEnv=capEnv; 47 | } 48 | 49 | void scan(){ 50 | Iterator it=getConnTableIterator(); 51 | while(it.hasNext()){ 52 | String key=it.next(); 53 | TCPTun tun=connTable.get(key); 54 | if(tun!=null){ 55 | if(tun.preDataReady){ 56 | //无数据超时 57 | long t=System.currentTimeMillis()-tun.lastReceiveDataTime; 58 | if(t>6000){ 59 | connTable.remove(key); 60 | if(capEnv.client){ 61 | defaultTcpTun=null; 62 | MLog.println("tcp隧道超时"); 63 | } 64 | } 65 | }else{ 66 | //连接中超时 67 | if(System.currentTimeMillis()-tun.createTime>5000){ 68 | connTable.remove(key); 69 | } 70 | } 71 | } 72 | } 73 | } 74 | 75 | public void removeTun(TCPTun tun){ 76 | connTable.remove(tun.key); 77 | } 78 | 79 | Iterator getConnTableIterator(){ 80 | Iterator it=null; 81 | synchronized (syn_scan) { 82 | it=new CopiedIterator(connTable.keySet().iterator()); 83 | } 84 | return it; 85 | } 86 | 87 | public static TunManager get(){ 88 | return tunManager; 89 | } 90 | 91 | public TCPTun getTcpConnection_Client(String remoteAddress,short remotePort,short localPort){ 92 | return connTable.get(remoteAddress+":"+remotePort+":"+localPort); 93 | } 94 | 95 | public void addConnection_Client(TCPTun conn) { 96 | synchronized (syn_scan) { 97 | String key=conn.remoteAddress.getHostAddress()+":"+conn.remotePort+":"+conn.localPort; 98 | //MLog.println("addConnection "+key); 99 | conn.setKey(key); 100 | connTable.put(key, conn); 101 | } 102 | } 103 | 104 | public TCPTun getTcpConnection_Server(String remoteAddress,short remotePort){ 105 | return connTable.get(remoteAddress+":"+remotePort); 106 | } 107 | 108 | public void addConnection_Server(TCPTun conn) { 109 | synchronized (syn_scan) { 110 | String key=conn.remoteAddress.getHostAddress()+":"+conn.remotePort; 111 | //MLog.println("addConnection "+key); 112 | conn.setKey(key); 113 | connTable.put(key, conn); 114 | } 115 | } 116 | 117 | public TCPTun getDefaultTcpTun() { 118 | return defaultTcpTun; 119 | } 120 | 121 | public void setDefaultTcpTun(TCPTun defaultTcpTun) { 122 | this.defaultTcpTun = defaultTcpTun; 123 | } 124 | 125 | } 126 | -------------------------------------------------------------------------------- /src/net/fs/cap/VDatagramSocket.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 D1SM.net 2 | 3 | package net.fs.cap; 4 | 5 | import java.io.IOException; 6 | import java.net.DatagramPacket; 7 | import java.net.DatagramSocket; 8 | import java.net.InetAddress; 9 | import java.net.SocketException; 10 | import java.util.concurrent.LinkedBlockingQueue; 11 | 12 | import net.fs.rudp.Route; 13 | 14 | public class VDatagramSocket extends DatagramSocket{ 15 | 16 | boolean useTcpTun=true; 17 | 18 | boolean client=true; 19 | 20 | LinkedBlockingQueue packetList=new LinkedBlockingQueue (); 21 | 22 | CapEnv capEnv; 23 | 24 | int localPort; 25 | 26 | Object syn_tun=new Object(); 27 | 28 | boolean tunConnecting=false; 29 | 30 | public VDatagramSocket() throws SocketException { 31 | 32 | } 33 | 34 | public VDatagramSocket(int port) throws SocketException { 35 | localPort=port; 36 | } 37 | 38 | public int getLocalPort() { 39 | return localPort; 40 | } 41 | 42 | public void send(DatagramPacket p) throws IOException { 43 | TCPTun tun=null; 44 | if(client){ 45 | tun=capEnv.tcpManager.getDefaultTcpTun(); 46 | if(tun!=null){ 47 | if(!tun.remoteAddress.getHostAddress().equals(p.getAddress().getHostAddress()) 48 | ||CapEnv.toUnsigned(tun.remotePort)!=p.getPort()){ 49 | capEnv.tcpManager.removeTun(tun); 50 | capEnv.tcpManager.setDefaultTcpTun(null); 51 | } 52 | }else { 53 | tryConnectTun_Client(p.getAddress(),(short) p.getPort()); 54 | tun=capEnv.tcpManager.getDefaultTcpTun(); 55 | } 56 | }else { 57 | tun=capEnv.tcpManager.getTcpConnection_Server(p.getAddress().getHostAddress(), (short) p.getPort()); 58 | } 59 | if(tun!=null){ 60 | if(tun.preDataReady){ 61 | tun.sendData(p.getData()); 62 | }else{ 63 | throw new IOException("隧道未连接!"); 64 | } 65 | }else{ 66 | 67 | throw new IOException("隧道不存在! "+" thread "+Route.es.getActiveCount()+" "+p.getAddress()+":"+p.getPort()); 68 | } 69 | } 70 | 71 | 72 | void tryConnectTun_Client(InetAddress dstAddress,short dstPort){ 73 | synchronized (syn_tun) { 74 | if(capEnv.tcpManager.getDefaultTcpTun()==null){ 75 | if(tunConnecting){ 76 | try { 77 | syn_tun.wait(); 78 | } catch (InterruptedException e) { 79 | e.printStackTrace(); 80 | } 81 | }else { 82 | tunConnecting=true; 83 | try { 84 | capEnv.createTcpTun_Client(dstAddress.getHostAddress(), dstPort); 85 | } catch (Exception e) { 86 | e.printStackTrace(); 87 | } 88 | tunConnecting=false; 89 | } 90 | } 91 | } 92 | } 93 | 94 | 95 | public synchronized void receive(DatagramPacket p) throws IOException { 96 | TunData td=null; 97 | try { 98 | td=packetList.take(); 99 | p.setData(td.data); 100 | p.setLength(td.data.length); 101 | p.setAddress(td.tun.remoteAddress); 102 | p.setPort(CapEnv.toUnsigned(td.tun.remotePort)); 103 | } catch (InterruptedException e) { 104 | e.printStackTrace(); 105 | } 106 | } 107 | 108 | void onReceinveFromTun(TunData td){ 109 | packetList.add(td); 110 | } 111 | 112 | public boolean isClient() { 113 | return client; 114 | } 115 | 116 | public void setClient(boolean client) { 117 | this.client = client; 118 | } 119 | 120 | public CapEnv getCapEnv() { 121 | return capEnv; 122 | } 123 | 124 | public void setCapEnv(CapEnv capEnv) { 125 | this.capEnv = capEnv; 126 | capEnv.vDatagramSocket=this; 127 | } 128 | 129 | } 130 | -------------------------------------------------------------------------------- /src/net/fs/rudp/message/DataMessage.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 D1SM.net 2 | 3 | package net.fs.rudp.message; 4 | 5 | 6 | import java.net.DatagramPacket; 7 | import java.net.InetAddress; 8 | 9 | import net.fs.utils.ByteIntConvert; 10 | import net.fs.utils.ByteShortConvert; 11 | 12 | public class DataMessage extends Message{ 13 | short sType=net.fs.rudp.message.MessageType.sType_DataMessage; 14 | int sequence=0; 15 | int length=0; 16 | byte [] data; 17 | byte [] dpData; 18 | int timeId; 19 | 20 | InetAddress dstAddress; 21 | 22 | int dstPort; 23 | 24 | int offset; 25 | 26 | int firstSendTimeId; 27 | 28 | long firstSendTime; 29 | 30 | public DataMessage(int sequence,byte[] dataq,int offset,short length, 31 | int connectId,int clientId){ 32 | this.sequence=sequence; 33 | this.offset=offset; 34 | this.length=(short) (length); 35 | this.data=new byte[this.length]; 36 | this.clientId=clientId; 37 | this.connectId=connectId; 38 | System.arraycopy(dataq, offset, this.data, 0, length); 39 | this.length=data.length; 40 | 41 | } 42 | 43 | public void create(int timeId){ 44 | this.timeId=timeId; 45 | dpData=new byte[this.length+16+8]; 46 | ByteShortConvert.toByteArray(ver, dpData, 0); //add: ver 47 | ByteShortConvert.toByteArray(sType, dpData, 2); //add: service type 48 | 49 | ByteIntConvert.toByteArray(connectId, dpData, 4); //add: sequence 50 | ByteIntConvert.toByteArray(clientId, dpData, 8); //add: sequence 51 | 52 | ByteIntConvert.toByteArray(this.sequence, dpData, 12); //add: sequence 53 | ByteShortConvert.toByteArray((short) this.length, dpData, 16); //add:length 54 | ByteIntConvert.toByteArray(this.timeId, dpData, 18); //add: sequence 55 | System.arraycopy(this.data, 0, dpData, 22, this.length); 56 | dp=new DatagramPacket(dpData,dpData.length); 57 | dp.setAddress(dstAddress); 58 | dp.setPort(dstPort); 59 | 60 | } 61 | 62 | public DataMessage(DatagramPacket dp){ 63 | this.dp=dp; 64 | dpData=dp.getData(); 65 | ver=ByteShortConvert.toShort(dpData, 0); 66 | sType=ByteShortConvert.toShort(dpData, 2); 67 | 68 | connectId=ByteIntConvert.toInt(dpData, 4); 69 | clientId=ByteIntConvert.toInt(dpData, 8); 70 | 71 | sequence=ByteIntConvert.toInt(dpData, 12); 72 | length=ByteShortConvert.toShort(dpData, 16); 73 | timeId=ByteIntConvert.toInt(dpData, 18); 74 | data=new byte[length]; 75 | System.arraycopy(dpData, 22, data, 0, length); 76 | } 77 | 78 | public int getSequence(){ 79 | return sequence; 80 | } 81 | 82 | public byte[] getData(){ 83 | return data; 84 | } 85 | 86 | public int getLength(){ 87 | return length; 88 | } 89 | 90 | public int getTimeId() { 91 | return timeId; 92 | } 93 | 94 | public void setTimeId(int timeId) { 95 | this.timeId = timeId; 96 | } 97 | 98 | public InetAddress getDstAddress() { 99 | return dstAddress; 100 | } 101 | 102 | public void setDstAddress(InetAddress dstAddress) { 103 | this.dstAddress = dstAddress; 104 | } 105 | 106 | public int getDstPort() { 107 | return dstPort; 108 | } 109 | 110 | public void setDstPort(int dstPort) { 111 | this.dstPort = dstPort; 112 | } 113 | 114 | public int getFirstSendTimeId() { 115 | return firstSendTimeId; 116 | } 117 | 118 | public void setFirstSendTimeId(int firstSendTimeId) { 119 | this.firstSendTimeId = firstSendTimeId; 120 | } 121 | 122 | public long getFirstSendTime() { 123 | return firstSendTime; 124 | } 125 | 126 | public void setFirstSendTime(long firstSendTime) { 127 | this.firstSendTime = firstSendTime; 128 | } 129 | 130 | } 131 | -------------------------------------------------------------------------------- /src/net/fs/rudp/ConnectionUDP.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 D1SM.net 2 | 3 | package net.fs.rudp; 4 | import java.net.DatagramPacket; 5 | import java.net.InetAddress; 6 | import java.util.Random; 7 | import java.util.concurrent.LinkedBlockingQueue; 8 | 9 | public class ConnectionUDP { 10 | public InetAddress dstIp; 11 | public int dstPort; 12 | public Sender sender; 13 | public Receiver receiver; 14 | public UDPOutputStream uos; 15 | public UDPInputStream uis; 16 | long connetionId; 17 | Route route; 18 | int mode; 19 | private boolean connected=true; 20 | long lastLiveTime=System.currentTimeMillis(); 21 | long lastSendLiveTime=0; 22 | 23 | static Random ran=new Random(); 24 | 25 | int connectId; 26 | 27 | ConnectionProcessor connectionProcessor; 28 | 29 | private LinkedBlockingQueue dpBuffer=new LinkedBlockingQueue(); 30 | 31 | public ClientControl clientControl; 32 | 33 | public boolean localClosed=false,remoteClosed=false,destroied=false; 34 | 35 | public boolean stopnow=false; 36 | 37 | public ConnectionUDP(Route ro,InetAddress dstIp,int dstPort,int mode,int connectId,ClientControl clientControl) throws Exception { 38 | this.clientControl=clientControl; 39 | this.route=ro; 40 | this.dstIp=dstIp; 41 | this.dstPort=dstPort; 42 | this.mode=mode; 43 | if(mode==1){ 44 | //MLog.println(" 发起连接RUDP "+dstIp+":"+dstPort+" connectId "+connectId); 45 | }else if(mode==2){ 46 | 47 | //MLog.println(" 接受连接RUDP "+dstIp+":"+dstPort+" connectId "+connectId); 48 | } 49 | this.connectId=connectId; 50 | try { 51 | sender=new Sender(this); 52 | receiver=new Receiver(this); 53 | uos=new UDPOutputStream (this); 54 | uis=new UDPInputStream(this); 55 | if(mode==2){ 56 | ro.createTunnelProcessor().process(this); 57 | } 58 | } catch (Exception e) { 59 | e.printStackTrace(); 60 | connected=false; 61 | route.connTable.remove(connectId); 62 | e.printStackTrace(); 63 | //#MLog.println(" 连接失败RUDP "+connectId); 64 | synchronized(this){ 65 | notifyAll(); 66 | } 67 | throw e; 68 | } 69 | //#MLog.println(" 连接成功RUDP "+connectId); 70 | synchronized(this){ 71 | notifyAll(); 72 | } 73 | } 74 | 75 | public DatagramPacket getPacket(int connectId) throws InterruptedException{ 76 | DatagramPacket dp=(DatagramPacket)dpBuffer.take(); 77 | return dp; 78 | } 79 | 80 | @Override 81 | public String toString(){ 82 | return new String(dstIp+":"+dstPort); 83 | } 84 | 85 | public boolean isConnected(){ 86 | return connected; 87 | } 88 | 89 | public void close_local(){ 90 | if(!localClosed){ 91 | localClosed=true; 92 | if(!stopnow){ 93 | sender.sendCloseMessage_Conn(); 94 | } 95 | destroy(false); 96 | } 97 | } 98 | 99 | public void close_remote() { 100 | if(!remoteClosed){ 101 | remoteClosed=true; 102 | destroy(false); 103 | } 104 | } 105 | 106 | //完全关闭 107 | public void destroy(boolean force){ 108 | if(!destroied){ 109 | if((localClosed&&remoteClosed)||force){ 110 | destroied=true; 111 | connected=false; 112 | uis.closeStream_Local(); 113 | uos.closeStream_Local(); 114 | sender.destroy(); 115 | receiver.destroy(); 116 | route.removeConnection(this); 117 | clientControl.removeConnection(this); 118 | } 119 | } 120 | } 121 | 122 | public void close_timeout(){ 123 | ////#MLog.println("超时关闭RDP连接"); 124 | } 125 | 126 | void live(){ 127 | lastLiveTime=System.currentTimeMillis(); 128 | } 129 | } 130 | -------------------------------------------------------------------------------- /src/net/fs/server/MapTunnelProcessor.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 D1SM.net 2 | 3 | package net.fs.server; 4 | 5 | import java.io.IOException; 6 | import java.io.InputStream; 7 | import java.io.OutputStream; 8 | import java.net.Socket; 9 | 10 | import net.fs.client.Pipe; 11 | import net.fs.rudp.ConnectionProcessor; 12 | import net.fs.rudp.ConnectionUDP; 13 | import net.fs.rudp.Constant; 14 | import net.fs.rudp.Route; 15 | import net.fs.rudp.UDPInputStream; 16 | import net.fs.rudp.UDPOutputStream; 17 | import net.fs.utils.MLog; 18 | 19 | import com.alibaba.fastjson.JSONObject; 20 | 21 | 22 | public class MapTunnelProcessor implements ConnectionProcessor{ 23 | 24 | Socket dstSocket=null; 25 | 26 | boolean closed=false; 27 | 28 | MapTunnelProcessor pc; 29 | 30 | ConnectionUDP conn; 31 | 32 | 33 | UDPInputStream tis; 34 | 35 | UDPOutputStream tos; 36 | 37 | InputStream sis; 38 | 39 | OutputStream sos; 40 | 41 | public void process(final ConnectionUDP conn){ 42 | this.conn=conn; 43 | pc=this; 44 | Route.es.execute(new Runnable(){ 45 | public void run(){ 46 | process(); 47 | } 48 | }); 49 | } 50 | 51 | 52 | void process(){ 53 | 54 | tis=conn.uis; 55 | tos=conn.uos; 56 | 57 | byte[] headData; 58 | try { 59 | headData = tis.read2(); 60 | String hs=new String(headData,"utf-8"); 61 | JSONObject requestJSon=JSONObject.parseObject(hs); 62 | final int dstPort=requestJSon.getIntValue("dst_port"); 63 | String message=""; 64 | JSONObject responeJSon=new JSONObject(); 65 | int code=Constant.code_failed; 66 | code=Constant.code_success; 67 | responeJSon.put("code", code); 68 | responeJSon.put("message", message); 69 | byte[] responeData=responeJSon.toJSONString().getBytes("utf-8"); 70 | tos.write(responeData, 0, responeData.length); 71 | if(code!=Constant.code_success){ 72 | close(); 73 | return; 74 | } 75 | dstSocket = new Socket("127.0.0.1", dstPort); 76 | dstSocket.setTcpNoDelay(true); 77 | sis=dstSocket.getInputStream(); 78 | sos=dstSocket.getOutputStream(); 79 | 80 | final Pipe p1=new Pipe(); 81 | final Pipe p2=new Pipe(); 82 | 83 | Route.es.execute(new Runnable() { 84 | 85 | public void run() { 86 | try { 87 | p1.pipe(sis, tos,100*1024,p2); 88 | }catch (Exception e) { 89 | //e.printStackTrace(); 90 | }finally{ 91 | close(); 92 | if(p1.getReadedLength()==0){ 93 | MLog.println("端口"+dstPort+"无返回数据"); 94 | } 95 | } 96 | } 97 | 98 | }); 99 | Route.es.execute(new Runnable() { 100 | 101 | public void run() { 102 | try { 103 | p2.pipe(tis,sos,100*1024*1024,conn); 104 | }catch (Exception e) { 105 | //e.printStackTrace(); 106 | }finally{ 107 | close(); 108 | } 109 | } 110 | }); 111 | 112 | 113 | } catch (Exception e2) { 114 | //e2.printStackTrace(); 115 | close(); 116 | } 117 | 118 | 119 | 120 | } 121 | 122 | void close(){ 123 | if(!closed){ 124 | closed=true; 125 | if(sis!=null){ 126 | try { 127 | sis.close(); 128 | } catch (IOException e) { 129 | //e.printStackTrace(); 130 | } 131 | } 132 | if(sos!=null){ 133 | try { 134 | sos.close(); 135 | } catch (IOException e) { 136 | //e.printStackTrace(); 137 | } 138 | } 139 | if(tos!=null){ 140 | tos.closeStream_Local(); 141 | } 142 | if(tis!=null){ 143 | tis.closeStream_Local(); 144 | } 145 | if(conn!=null){ 146 | conn.close_local(); 147 | } 148 | if(dstSocket!=null){ 149 | try { 150 | dstSocket.close(); 151 | } catch (IOException e) { 152 | //e.printStackTrace(); 153 | } 154 | } 155 | } 156 | } 157 | 158 | } 159 | -------------------------------------------------------------------------------- /src/net/fs/rudp/message/MessageType.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 D1SM.net 2 | 3 | package net.fs.rudp.message; 4 | 5 | public class MessageType { 6 | public static short sType_DataMessage=80; 7 | public static short sType_ConnectMessage1=71; 8 | public static short sType_ConnectMessage2=72; 9 | public static short sType_ConnectMessage3=73; 10 | public static short sType_CloseMessage_Stream=75; 11 | public static short sType_CloseMessage_Conn=76; 12 | 13 | public static short sType_AckMessage=61; 14 | public static short sType_LastReadMessage=65; 15 | public static short sType_AckListMessage=60; 16 | 17 | public static short sType_AskFillMessage=63; 18 | public static short sType_ReSendMessage=62; 19 | 20 | public static short sType_AckListMessageTun=66; 21 | 22 | 23 | public static short sType_UdpTunDataMessage=90; 24 | public static short sType_UdpTunOpenMessage=91; 25 | public static short sType_UdpTunCloseMessage=92; 26 | 27 | public static short sType_CleanMessage1=225; 28 | public static short sType_CleanMessage2=226; 29 | 30 | public static short sType_RegMessage=101; 31 | public static short sType_RegMessage2=102; 32 | public static short sType_ExitMessage=111; 33 | public static short sType_ExitMessage2=112; 34 | public static short sType_PubAddMessage=141; 35 | public static short sType_PubAddMessage2=142; 36 | public static short sType_PubDelMessage=151; 37 | public static short sType_PubDelMessage2=152; 38 | public static short sType_SLiveMessage=131; 39 | public static short sType_SLiveMessage2=132; 40 | public static short sType_GetSNodeMessage=161; 41 | public static short sType_GetSNodeMessage2=162; 42 | public static short sType_JoinDBFailMessage1=168; 43 | public static short sType_JoinDBFailMessage2=169; 44 | public static short sType_TimeSynMessage1=175; 45 | public static short sType_TimeSynMessage2=176; 46 | public static short sType_AdvCSMessage1=178; 47 | public static short sType_AdvCSMessage2=179; 48 | 49 | public static short sType_CastGroupMessage=181; 50 | public static short sType_CastGroupMessage2=182; 51 | public static short sType_CastGroupRandomMessage=191; 52 | public static short sType_CastGroupRandomMessage2=192; 53 | public static short sType_CastGroupRandomMessage3=193; 54 | 55 | public static short sType_Assist_RegMessage=500; 56 | public static short sType_Assist_RegMessage2=501; 57 | public static short sType_Assist_PingMessage1=510; 58 | public static short sType_Assist_PingMessage2=511; 59 | public static short sType_ReversePingMessage1=515; 60 | public static short sType_ReversePingMessage2=516; 61 | public static short sType_ReversePingMessage3=517; 62 | public static short sType_ReverseConnTCPMessage1=518; 63 | public static short sType_ReverseConnTCPMessage2=519; 64 | public static short sType_Assist_OtherOutAddressMessage=520; 65 | public static short sType_Assist_OtherOutAddressMessage2=521; 66 | public static short sType_Assist_OtherOutAddressMessage3=522; 67 | public static short sType_Assist_OtherOutAddressMessage4=523; 68 | 69 | public static short sType_Assist_LiveMessage =4125; 70 | public static short sType_Assist_LiveMessage2=4126; 71 | public static short sType_Assist_ExitMessage=540; 72 | public static short sType_Assist_ExitMessage2=541; 73 | 74 | 75 | public static short sType_DB_CastAddMessage=601; 76 | public static short sType_DB_CastAddMessage2=602; 77 | public static short sType_DB_CastRemoveMessage=701; 78 | public static short sType_DB_CastRemoveMessage2=702; 79 | public static short sType_DB_SourceSearchMessage=711; 80 | public static short sType_DB_SourceSearchMessage2=712; 81 | public static short sType_DB_SourceSumMessage1=715; 82 | public static short sType_DB_SourceSumMessage2=716; 83 | 84 | public static short sType_getOutAddressMessage=1181; 85 | public static short sType_getOutAddressMessage2=1182; 86 | 87 | public static short sType_PingMessage=301; 88 | public static short sType_PingMessage2=302; 89 | 90 | public static short sType_PingMessagec=311; 91 | public static short sType_PingMessagec2=312; 92 | 93 | public static short sType_PingMessager=321; 94 | public static short sType_PingMessager2=322; 95 | 96 | } 97 | -------------------------------------------------------------------------------- /src/net/fs/rudp/message/AckListMessage.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 D1SM.net 2 | 3 | package net.fs.rudp.message; 4 | 5 | import java.net.DatagramPacket; 6 | import java.util.ArrayList; 7 | import java.util.HashMap; 8 | 9 | import net.fs.rudp.SendRecord; 10 | import net.fs.utils.ByteIntConvert; 11 | import net.fs.utils.ByteShortConvert; 12 | 13 | 14 | 15 | 16 | public class AckListMessage extends Message{ 17 | ArrayList ackList; 18 | byte[] dpData=null; 19 | int lastRead; 20 | 21 | int r1,r2,r3,s1,s2,s3; 22 | 23 | @SuppressWarnings("unchecked") 24 | public AckListMessage(long connId,ArrayList ackList,int lastRead, 25 | HashMap sendRecordTable,int timeId, 26 | int connectId,int clientId){ 27 | this.clientId=clientId; 28 | this.connectId=connectId; 29 | this.ackList=ackList; 30 | this.lastRead=lastRead; 31 | int len1=4+4+10+4*ackList.size(); 32 | dpData=new byte[len1+24+9]; 33 | sType=MessageType.sType_AckListMessage; 34 | ByteShortConvert.toByteArray(ver, dpData, 0); //add: ver 35 | ByteShortConvert.toByteArray(sType, dpData, 2); //add: service type 36 | ByteIntConvert.toByteArray(connectId, dpData, 4); //add: sequence 37 | ByteIntConvert.toByteArray(clientId, dpData, 8); //add: sequence 38 | 39 | ByteIntConvert.toByteArray(lastRead, dpData, 4+8); 40 | //dpData[8]=(byte) ackList.size(); 41 | ByteShortConvert.toByteArray((short) ackList.size(), dpData, 8+8); //add: service type 42 | for(int i=0;i(); 95 | int t=0; 96 | for(int i=0;i srcReadBuffer=new ArrayList(); 34 | ArrayList dstReadBuffer=new ArrayList(); 35 | 36 | Thread srcReadThread; 37 | Thread dstWriteThread; 38 | Thread srcWriteThread; 39 | Thread dstReadThread; 40 | byte[] srcPreRead=new byte[0]; 41 | 42 | int maxDstRead=1; 43 | int maxSrcRead=1; 44 | 45 | boolean isSuperSocket=false; 46 | 47 | boolean dstReadComplete=false; 48 | 49 | boolean srcReadComplete=false; 50 | 51 | boolean srcWriteComplete=false; 52 | 53 | boolean dstWriteComplete=false; 54 | 55 | boolean dstClosed=false; 56 | 57 | boolean srcClosed=false; 58 | 59 | String st=" "; 60 | 61 | 62 | String ss=""; 63 | 64 | static int n=0; 65 | 66 | Random ran=new Random(); 67 | 68 | long id; 69 | 70 | static int m=0,a,b; 71 | 72 | boolean closed=false; 73 | 74 | long lastActiveTime=System.currentTimeMillis(); 75 | 76 | //static HashMap procTable=new HashMap(); 77 | 78 | static ExecutorService es; 79 | 80 | MapSocketPorcessor mp; 81 | 82 | Socket socketA,socketB; 83 | 84 | int supserSocketId=-1; 85 | 86 | String requestHost=null; 87 | 88 | static { 89 | es=Executors.newCachedThreadPool(); 90 | } 91 | 92 | public MapSocketPorcessor(){ 93 | 94 | } 95 | 96 | public void setDstSocket(Socket dstSocket){ 97 | this.dstSocket=dstSocket; 98 | } 99 | 100 | public void setId(long id){ 101 | this.id=id; 102 | } 103 | 104 | public boolean isClosed(){ 105 | return closed; 106 | } 107 | 108 | public long getLastActiveTime(){ 109 | return lastActiveTime; 110 | } 111 | 112 | void active(){ 113 | lastActiveTime=System.currentTimeMillis(); 114 | } 115 | 116 | public long getId(){ 117 | return id; 118 | } 119 | 120 | public void closeAll(){ 121 | closeAll(true); 122 | } 123 | 124 | public void closeAll(boolean closeDst){ 125 | //procTable.remove(id); 126 | //Log.println("closeAll AAAAAAAAA"); 127 | if(!closed){ 128 | //Log.println("closeAll BBBBBBBBBB"); 129 | closed=true; 130 | //#MLog.println("MapSocketPorcessor Close"); 131 | try { 132 | srcSocket.close(); 133 | } catch (IOException e) { 134 | e.printStackTrace(); 135 | } 136 | if(closeDst){ 137 | try { 138 | dstSocket.close(); 139 | } catch (IOException e) { 140 | e.printStackTrace(); 141 | } 142 | } 143 | } 144 | } 145 | 146 | void tryClose(){ 147 | closeAll(); 148 | } 149 | 150 | public void start(){ 151 | Runnable t=new Runnable(){ 152 | public void run(){ 153 | try { 154 | ConnInfo connInfo=new ConnInfo(); 155 | StreamPipe p1=new StreamPipe(connInfo,srcIs,dstOs,10*1024,1000*1024); 156 | StreamPipe p2=new StreamPipe(connInfo,dstIs,srcOs,10*1024,1000*1024); 157 | p1.setType(StreamPipe.type_request); 158 | //p1.addListener(mp); 159 | //p2.addListener(mp); 160 | p1.setSocketA(socketA); 161 | p1.setSocketB(socketB); 162 | p2.setType(StreamPipe.type_respone); 163 | p2.setSocketA(socketA); 164 | p2.setSocketB(socketB); 165 | p1.setSupserSocketId(supserSocketId); 166 | p2.setSupserSocketId(supserSocketId); 167 | } catch (Exception e1) { 168 | e1.printStackTrace(); 169 | } 170 | } 171 | }; 172 | es.execute(t); 173 | } 174 | 175 | public void pipeClose() { 176 | //closeAll(); 177 | 178 | } 179 | 180 | public Socket getSocketA() { 181 | return socketA; 182 | } 183 | 184 | public void setSocketA(Socket socketA) { 185 | this.socketA = socketA; 186 | } 187 | 188 | public Socket getSocketB() { 189 | return socketB; 190 | } 191 | 192 | public void setSocketB(Socket socketB) { 193 | this.socketB = socketB; 194 | } 195 | 196 | public int getSupserSocketId() { 197 | return supserSocketId; 198 | } 199 | 200 | public void setSupserSocketId(int supserSocketId) { 201 | this.supserSocketId = supserSocketId; 202 | } 203 | 204 | public String getRequestHost() { 205 | return requestHost; 206 | } 207 | 208 | public void setRequestHost(String requestHost) { 209 | this.requestHost = requestHost; 210 | } 211 | 212 | } 213 | -------------------------------------------------------------------------------- /src/net/fs/rudp/StreamPipe.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 D1SM.net 2 | 3 | package net.fs.rudp; 4 | 5 | import java.io.DataInputStream; 6 | import java.io.DataOutputStream; 7 | import java.io.IOException; 8 | import java.net.Socket; 9 | import java.util.ArrayList; 10 | import java.util.List; 11 | import java.util.Vector; 12 | import java.util.concurrent.Semaphore; 13 | 14 | 15 | public class StreamPipe { 16 | 17 | DataInputStream is; 18 | 19 | DataOutputStream os; 20 | 21 | List listenerList; 22 | 23 | boolean closed=false; 24 | 25 | int maxLen=2000; 26 | 27 | long lastResetTime; 28 | 29 | int maxSpeed=100*1024*1024; 30 | 31 | int port=0; 32 | 33 | int limiteConnectTime; 34 | 35 | String userId=""; 36 | 37 | byte[] preReadData; 38 | 39 | int preReadDataLength; 40 | 41 | Socket socketA,socketB; 42 | 43 | boolean writing=false; 44 | 45 | int BUF_SIZE; 46 | 47 | ArrayList dataList=new ArrayList(); 48 | 49 | Semaphore semp_have_data=new Semaphore(0); 50 | 51 | int cachedSize=0; 52 | 53 | int supserSocketId=-1; 54 | 55 | static int type_request=1; 56 | 57 | static int type_respone=2; 58 | 59 | int type=0; 60 | 61 | ConnInfo connInfo; 62 | 63 | public StreamPipe(ConnInfo connInfo,final DataInputStream is,final DataOutputStream os,final int BUF_SIZE,final int maxSpeed){ 64 | this(connInfo,is, os, BUF_SIZE, maxSpeed, null, 0); 65 | } 66 | 67 | public StreamPipe(ConnInfo ci,final DataInputStream is,final DataOutputStream os,int BUF_SIZE1,final int maxSpeed,final byte[] preReadData,final int preReadDataLength){ 68 | connInfo=ci; 69 | listenerList=new Vector(); 70 | this.maxSpeed=maxSpeed; 71 | this.preReadData=preReadData; 72 | BUF_SIZE=BUF_SIZE1; 73 | if(maxSpeed<=50*1024){ 74 | //BUF_SIZE=100; 75 | } 76 | Runnable thread=new Runnable(){ 77 | 78 | int count=0; 79 | public void run(){ 80 | byte[] data=new byte[BUF_SIZE]; 81 | int len=0; 82 | try { 83 | if(preReadData!=null){ 84 | // String string=new String(preReadData,0,preReadDataLength); 85 | // Log.println("写预读111 "+string); 86 | try { 87 | os.write(preReadData,0,preReadDataLength); 88 | } catch (IOException e) { 89 | e.printStackTrace(); 90 | return; 91 | } 92 | // Log.println("写预读222 "); 93 | } 94 | //Log.println("pipe发送 111 "+supserSocketId+" "); 95 | boolean parsed=false; 96 | try { 97 | while((len=is.read(data))>0){ 98 | try { 99 | os.write(data,0,len); 100 | } catch (IOException e) { 101 | //e.printStackTrace(); 102 | break; 103 | } 104 | 105 | } 106 | } catch (IOException e) { 107 | //e.printStackTrace(); 108 | } 109 | }finally{ 110 | close(); 111 | } 112 | } 113 | }; 114 | Route.es.execute(thread); 115 | } 116 | 117 | void close(){ 118 | if(!closed){ 119 | closed=true; 120 | try { 121 | Thread.sleep(500); 122 | } catch (InterruptedException e1) { 123 | //e1.printStackTrace(); 124 | } 125 | 126 | if(socketA!=null){ 127 | Route.es.execute(new Runnable() { 128 | 129 | public void run() { 130 | try { 131 | socketA.close(); 132 | } catch (IOException e) { 133 | //e.printStackTrace(); 134 | } 135 | } 136 | 137 | }); 138 | 139 | } 140 | 141 | 142 | if(socketB!=null){ 143 | 144 | Route.es.execute(new Runnable() { 145 | 146 | public void run() { 147 | try { 148 | socketB.close(); 149 | } catch (IOException e) { 150 | //e.printStackTrace(); 151 | } 152 | } 153 | }); 154 | 155 | } 156 | fireClose(); 157 | } 158 | } 159 | 160 | class HttpHost{ 161 | String address; 162 | int port=80; 163 | public String getAddress() { 164 | return address; 165 | } 166 | public void setAddress(String address) { 167 | this.address = address; 168 | } 169 | public int getPort() { 170 | return port; 171 | } 172 | public void setPort(int port) { 173 | this.port = port; 174 | } 175 | 176 | } 177 | 178 | HttpHost readHost(String data){ 179 | HttpHost hh=new HttpHost(); 180 | String host=null; 181 | data=data.replaceAll("\r", ""); 182 | data=data.replaceAll(" ", ""); 183 | String[] ls=data.split("\n"); 184 | for(String l:ls){ 185 | if(l.startsWith("Host:")){ 186 | String s1=l.substring(5); 187 | int index2=s1.indexOf(":"); 188 | if(index2>-1){ 189 | int port=Integer.parseInt(s1.substring(index2+1)); 190 | hh.setPort(port); 191 | s1=s1.substring(0,index2); 192 | } 193 | host=s1; 194 | hh.setAddress(host); 195 | ////#MLog.println("ddd "+s1); 196 | } 197 | } 198 | return hh; 199 | } 200 | 201 | public void addListener(PipeListener listener){ 202 | listenerList.add(listener); 203 | } 204 | 205 | void fireClose(){ 206 | //Log.println("StreamPipe关闭 fireClose111 "+listenerList.size()); 207 | for(PipeListener listener:listenerList){ 208 | //Log.println("StreamPipe关闭 fireClose222"); 209 | listener.pipeClose(); 210 | } 211 | } 212 | 213 | public int getPort() { 214 | return port; 215 | } 216 | 217 | public void setPort(int port) { 218 | this.port = port; 219 | } 220 | 221 | public int getLimiteConnectTime() { 222 | return limiteConnectTime; 223 | } 224 | 225 | public void setLimiteConnectTime(int limiteConnectTime) { 226 | this.limiteConnectTime = limiteConnectTime; 227 | } 228 | 229 | public String getUserId() { 230 | return userId; 231 | } 232 | 233 | public void setUserId(String userId) { 234 | this.userId = userId; 235 | } 236 | 237 | public Socket getSocketA() { 238 | return socketA; 239 | } 240 | 241 | public void setSocketA(Socket socketA) { 242 | this.socketA = socketA; 243 | } 244 | 245 | public Socket getSocketB() { 246 | return socketB; 247 | } 248 | 249 | public void setSocketB(Socket socketB) { 250 | this.socketB = socketB; 251 | } 252 | 253 | public int getSupserSocketId() { 254 | return supserSocketId; 255 | } 256 | 257 | public void setSupserSocketId(int supserSocketId) { 258 | this.supserSocketId = supserSocketId; 259 | } 260 | 261 | public int getType() { 262 | return type; 263 | } 264 | 265 | public void setType(int type) { 266 | this.type = type; 267 | } 268 | 269 | public ConnInfo getConnInfo() { 270 | return connInfo; 271 | } 272 | 273 | public void setConnInfo(ConnInfo connInfo) { 274 | this.connInfo = connInfo; 275 | } 276 | 277 | } 278 | -------------------------------------------------------------------------------- /src/net/fs/rudp/Receiver.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 D1SM.net 2 | 3 | package net.fs.rudp; 4 | import java.net.DatagramPacket; 5 | import java.net.InetAddress; 6 | import java.util.ArrayList; 7 | import java.util.HashMap; 8 | 9 | import net.fs.rudp.message.AckListMessage; 10 | import net.fs.rudp.message.CloseMessage_Conn; 11 | import net.fs.rudp.message.CloseMessage_Stream; 12 | import net.fs.rudp.message.DataMessage; 13 | import net.fs.utils.MessageCheck; 14 | 15 | 16 | public class Receiver { 17 | ConnectionUDP conn; 18 | Sender sender; 19 | public InetAddress dstIp; 20 | public int dstPort; 21 | HashMap receiveTable=new HashMap(); 22 | int lastRead=-1; 23 | int lastReceive=-1; 24 | Object availOb=new Object(); 25 | 26 | boolean isReady=false; 27 | Object readyOb=new Object(); 28 | byte[] b4=new byte[4]; 29 | int lastRead1=0; 30 | int maxWinR=10; 31 | int lastRead2=-1; 32 | UDPInputStream uis; 33 | 34 | float availWin=RUDPConfig.maxWin; 35 | 36 | int currentRemoteTimeId; 37 | 38 | int closeOffset; 39 | 40 | boolean streamClose=false; 41 | 42 | boolean reveivedClose=false; 43 | 44 | static int m=0,x,x2,c; 45 | 46 | boolean b=false,b2; 47 | 48 | public int nw; 49 | 50 | long received; 51 | 52 | Receiver(ConnectionUDP conn){ 53 | this.conn=conn; 54 | uis=new UDPInputStream(conn); 55 | this.sender=conn.sender; 56 | this.dstIp=conn.dstIp; 57 | this.dstPort=conn.dstPort; 58 | } 59 | 60 | //接收流数据 61 | public byte[] receive() throws ConnectException { 62 | DataMessage me=null; 63 | if(conn.isConnected()){ 64 | me=receiveTable.get(lastRead+1); 65 | synchronized (availOb){ 66 | if(me==null){ 67 | //MLog.println("等待中 "+conn.connectId+" "+(lastRead+1)); 68 | 69 | try { 70 | availOb.wait(); 71 | } catch (InterruptedException e) { 72 | e.printStackTrace(); 73 | } 74 | me=receiveTable.get(lastRead+1); 75 | //MLog.println("等待完成aaa "+conn.connectId+" "+(lastRead+1)); 76 | } 77 | } 78 | 79 | }else{ 80 | throw new ConnectException("连接未建立"); 81 | } 82 | 83 | if(!streamClose){ 84 | checkCloseOffset_Remote(); 85 | if(me==null){ 86 | throw new ConnectException("连接已断开ccccccc"); 87 | }else { 88 | } 89 | conn.sender.sendLastReadDelay(); 90 | 91 | lastRead++; 92 | synchronized (availOb){ 93 | receiveTable.remove(me.getSequence()); 94 | } 95 | 96 | received+=me.getData().length; 97 | //System.out.println("received "+received/1024/1024+"MB"); 98 | return me.getData(); 99 | }else{ 100 | throw new ConnectException("连接已断开"); 101 | } 102 | } 103 | 104 | public void onReceivePacket(DatagramPacket dp){ 105 | DataMessage me; 106 | if(dp!=null){ 107 | if(conn.isConnected()){ 108 | int ver=MessageCheck.checkVer(dp); 109 | int sType=MessageCheck.checkSType(dp); 110 | if(ver==RUDPConfig.protocal_ver){ 111 | conn.live(); 112 | if(sType==net.fs.rudp.message.MessageType.sType_DataMessage){ 113 | me=new DataMessage(dp); 114 | int timeId=me.getTimeId(); 115 | SendRecord record=conn.clientControl.sendRecordTable_remote.get(timeId); 116 | if(record==null){ 117 | record=new SendRecord(); 118 | record.setTimeId(timeId); 119 | conn.clientControl.sendRecordTable_remote.put(timeId, record); 120 | } 121 | record.addSended(me.getData().length); 122 | 123 | if(timeId>currentRemoteTimeId){ 124 | currentRemoteTimeId=timeId; 125 | } 126 | 127 | int sequence=me.getSequence(); 128 | 129 | conn.sender.sendAckDelay(me.getSequence()); 130 | if(sequence>lastRead){ 131 | synchronized (availOb){ 132 | receiveTable.put(sequence, me); 133 | if(receiveTable.containsKey(lastRead+1)){ 134 | availOb.notify(); 135 | } 136 | } 137 | } 138 | }else if(sType==net.fs.rudp.message.MessageType.sType_AckListMessage){ 139 | AckListMessage alm=new AckListMessage(dp); 140 | int lastRead3=alm.getLastRead(); 141 | if(lastRead3>lastRead2){ 142 | lastRead2=lastRead3; 143 | } 144 | ArrayList ackList=alm.getAckList(); 145 | 146 | for(int i=0;irc1.getAckedSize()){ 153 | rc1.setAckedSize(alm.getS1()); 154 | } 155 | } 156 | 157 | SendRecord rc2=conn.clientControl.getSendRecord(alm.getR2()); 158 | if(rc2!=null){ 159 | if(alm.getS2()>rc2.getAckedSize()){ 160 | rc2.setAckedSize(alm.getS2()); 161 | } 162 | } 163 | 164 | SendRecord rc3=conn.clientControl.getSendRecord(alm.getR3()); 165 | if(rc3!=null){ 166 | if(alm.getS3()>rc3.getAckedSize()){ 167 | rc3.setAckedSize(alm.getS3()); 168 | } 169 | } 170 | 171 | if(checkWin()){ 172 | conn.sender.play(); 173 | } 174 | }else if(sType==net.fs.rudp.message.MessageType.sType_CloseMessage_Stream){ 175 | CloseMessage_Stream cm=new CloseMessage_Stream(dp); 176 | reveivedClose=true; 177 | int n=cm.getCloseOffset(); 178 | closeStream_Remote(n); 179 | }else if(sType==net.fs.rudp.message.MessageType.sType_CloseMessage_Conn){ 180 | CloseMessage_Conn cm2=new CloseMessage_Conn(dp); 181 | conn.close_remote(); 182 | }else{ 183 | ////#MLog.println("未处理数据包 "+sType); 184 | } 185 | } 186 | 187 | } 188 | } 189 | 190 | } 191 | 192 | public void destroy(){ 193 | //#MLog.println("destroy destroy destroy"); 194 | synchronized (availOb) { 195 | receiveTable.clear(); 196 | } 197 | } 198 | 199 | boolean checkWin(){ 200 | nw=conn.sender.sendOffset-lastRead2; 201 | boolean b=false; 202 | if(nw=closeOffset-1){ 220 | streamClose=true; 221 | synchronized (availOb){ 222 | availOb.notifyAll(); 223 | } 224 | conn.sender.closeStream_Remote(); 225 | } 226 | } 227 | } 228 | } 229 | 230 | void closeStream_Local(){ 231 | if(!streamClose){ 232 | c++; 233 | streamClose=true; 234 | synchronized (availOb){ 235 | availOb.notifyAll(); 236 | } 237 | conn.sender.closeStream_Local(); 238 | } 239 | } 240 | 241 | public int getCurrentTimeId() { 242 | return currentRemoteTimeId; 243 | } 244 | 245 | public void setCurrentTimeId(int currentTimeId) { 246 | this.currentRemoteTimeId = currentTimeId; 247 | } 248 | 249 | 250 | public int getCloseOffset() { 251 | return closeOffset; 252 | } 253 | 254 | 255 | public void setCloseOffset(int closeOffset) { 256 | this.closeOffset = closeOffset; 257 | } 258 | 259 | } 260 | -------------------------------------------------------------------------------- /src/net/fs/client/PortMapManager.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 D1SM.net 2 | 3 | package net.fs.client; 4 | 5 | import java.io.DataInputStream; 6 | import java.io.File; 7 | import java.io.FileInputStream; 8 | import java.io.FileOutputStream; 9 | import java.io.IOException; 10 | import java.io.UnsupportedEncodingException; 11 | import java.net.ServerSocket; 12 | import java.net.Socket; 13 | import java.util.ArrayList; 14 | import java.util.HashMap; 15 | 16 | import com.alibaba.fastjson.JSONArray; 17 | import com.alibaba.fastjson.JSONObject; 18 | 19 | import net.fs.rudp.Route; 20 | import net.fs.utils.MLog; 21 | 22 | public class PortMapManager { 23 | 24 | MapClient mapClient; 25 | 26 | ArrayList mapList=new ArrayList(); 27 | 28 | HashMap mapRuleTable=new HashMap(); 29 | 30 | String configFilePath="port_map.json"; 31 | 32 | PortMapManager(MapClient mapClient){ 33 | this.mapClient=mapClient; 34 | //listenPort(); 35 | loadMapRule(); 36 | } 37 | 38 | void addMapRule(MapRule mapRule) throws Exception{ 39 | if(getMapRule(mapRule.name)!=null){ 40 | throw new Exception("映射 "+mapRule.name+" 已存在,请修改名称!"); 41 | } 42 | ServerSocket serverSocket=null; 43 | try { 44 | serverSocket = new ServerSocket(mapRule.getListen_port()); 45 | listen(serverSocket); 46 | mapList.add(mapRule); 47 | mapRuleTable.put(mapRule.listen_port, mapRule); 48 | saveMapRule(); 49 | } catch (IOException e2) { 50 | //e2.printStackTrace(); 51 | throw new Exception("端口 "+mapRule.getListen_port()+" 已经被占用!"); 52 | }finally{ 53 | // if(serverSocket!=null){ 54 | // serverSocket.close(); 55 | // } 56 | } 57 | } 58 | 59 | void removeMapRule(String name){ 60 | MapRule mapRule=getMapRule(name); 61 | if(mapRule!=null){ 62 | mapList.remove(mapRule); 63 | mapRuleTable.remove(mapRule.listen_port); 64 | if(mapRule.serverSocket!=null){ 65 | try { 66 | mapRule.serverSocket.close(); 67 | } catch (IOException e) { 68 | e.printStackTrace(); 69 | } 70 | } 71 | try { 72 | saveMapRule(); 73 | } catch (Exception e) { 74 | e.printStackTrace(); 75 | } 76 | } 77 | } 78 | 79 | void updateMapRule(MapRule mapRule_origin,MapRule mapRule_new) throws Exception{ 80 | if(getMapRule(mapRule_new.name)!=null&&!mapRule_origin.name.equals(mapRule_new.name)){ 81 | throw new Exception("映射 "+mapRule_new.name+" 已存在,请修改名称!"); 82 | } 83 | ServerSocket serverSocket=null; 84 | if(mapRule_origin.listen_port!=mapRule_new.listen_port){ 85 | try { 86 | serverSocket = new ServerSocket(mapRule_new.getListen_port()); 87 | listen(serverSocket); 88 | mapRule_origin.using=false; 89 | if(mapRule_origin.serverSocket!=null){ 90 | mapRule_origin.serverSocket.close(); 91 | } 92 | mapRule_origin.serverSocket=serverSocket; 93 | mapRuleTable.remove(mapRule_origin.listen_port); 94 | mapRuleTable.put(mapRule_new.listen_port, mapRule_new); 95 | } catch (IOException e2) { 96 | //e2.printStackTrace(); 97 | throw new Exception("端口 "+mapRule_new.getListen_port()+" 已经被占用!"); 98 | }finally{ 99 | // if(serverSocket!=null){ 100 | // serverSocket.close(); 101 | // } 102 | } 103 | } 104 | mapRule_origin.name=mapRule_new.name; 105 | mapRule_origin.listen_port=mapRule_new.listen_port; 106 | mapRule_origin.dst_port=mapRule_new.dst_port; 107 | saveMapRule(); 108 | 109 | } 110 | 111 | void saveMapRule() throws Exception{ 112 | JSONObject json=new JSONObject(); 113 | JSONArray json_map_list=new JSONArray(); 114 | json.put("map_list", json_map_list); 115 | if(mapList.size()==0){ 116 | 117 | } 118 | for(MapRule r:mapList){ 119 | JSONObject json_rule=new JSONObject(); 120 | json_rule.put("name", r.name); 121 | json_rule.put("listen_port", r.listen_port); 122 | json_rule.put("dst_port", r.dst_port); 123 | json_map_list.add(json_rule); 124 | } 125 | try { 126 | saveFile(json.toJSONString().getBytes("utf-8"), configFilePath); 127 | } catch (UnsupportedEncodingException e) { 128 | e.printStackTrace(); 129 | } catch (Exception e) { 130 | e.printStackTrace(); 131 | throw new Exception("保存失败!"); 132 | } 133 | } 134 | 135 | void loadMapRule(){ 136 | String content; 137 | JSONObject json=null; 138 | try { 139 | content = readFileUtf8(configFilePath); 140 | json=JSONObject.parseObject(content); 141 | } catch (Exception e) { 142 | //e.printStackTrace(); 143 | } 144 | if(json!=null&&json.containsKey("map_list")){ 145 | JSONArray json_map_list=json.getJSONArray("map_list"); 146 | for(int i=0;i getMapList() { 180 | return mapList; 181 | } 182 | 183 | public void setMapList(ArrayList mapList) { 184 | this.mapList = mapList; 185 | } 186 | 187 | void listen(final ServerSocket serverSocket){ 188 | Route.es.execute(new Runnable() { 189 | 190 | @Override 191 | public void run() { 192 | while(true){ 193 | try { 194 | final Socket socket=serverSocket.accept(); 195 | Route.es.execute(new Runnable() { 196 | 197 | @Override 198 | public void run() { 199 | int listenPort=serverSocket.getLocalPort(); 200 | MapRule mapRule=mapRuleTable.get(listenPort); 201 | if(mapRule!=null){ 202 | Route route=null; 203 | if(mapClient.isUseTcp()){ 204 | route=mapClient.route_tcp; 205 | }else { 206 | route=mapClient.route_udp; 207 | } 208 | PortMapProcess process=new PortMapProcess(mapClient,route, socket,mapClient.serverAddress,mapClient.serverPort,null, 209 | null,mapRule.dst_port); 210 | } 211 | } 212 | 213 | }); 214 | 215 | } catch (IOException e) { 216 | e.printStackTrace(); 217 | break; 218 | } 219 | } 220 | } 221 | }); 222 | } 223 | 224 | void saveFile(byte[] data,String path) throws Exception{ 225 | FileOutputStream fos=null; 226 | try { 227 | fos=new FileOutputStream(path); 228 | fos.write(data); 229 | } catch (Exception e) { 230 | throw e; 231 | } finally { 232 | if(fos!=null){ 233 | fos.close(); 234 | } 235 | } 236 | } 237 | 238 | public static String readFileUtf8(String path) throws Exception{ 239 | String str=null; 240 | FileInputStream fis=null; 241 | DataInputStream dis=null; 242 | try { 243 | File file=new File(path); 244 | 245 | int length=(int) file.length(); 246 | byte[] data=new byte[length]; 247 | 248 | fis=new FileInputStream(file); 249 | dis=new DataInputStream(fis); 250 | dis.readFully(data); 251 | str=new String(data,"utf-8"); 252 | 253 | } catch (Exception e) { 254 | //e.printStackTrace(); 255 | throw e; 256 | }finally{ 257 | if(fis!=null){ 258 | try { 259 | fis.close(); 260 | } catch (IOException e) { 261 | e.printStackTrace(); 262 | } 263 | } 264 | if(dis!=null){ 265 | try { 266 | dis.close(); 267 | } catch (IOException e) { 268 | e.printStackTrace(); 269 | } 270 | } 271 | } 272 | 273 | return str; 274 | } 275 | } 276 | -------------------------------------------------------------------------------- /src/net/fs/rudp/Sender.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 D1SM.net 2 | 3 | package net.fs.rudp; 4 | 5 | import java.io.IOException; 6 | import java.net.DatagramPacket; 7 | import java.net.InetAddress; 8 | import java.util.ArrayList; 9 | import java.util.HashMap; 10 | import java.util.Random; 11 | 12 | import net.fs.rudp.message.AckListMessage; 13 | import net.fs.rudp.message.CloseMessage_Conn; 14 | import net.fs.rudp.message.CloseMessage_Stream; 15 | import net.fs.rudp.message.DataMessage; 16 | 17 | public class Sender { 18 | DataMessage me2=null; 19 | int interval; 20 | 21 | public int sum=0; 22 | int sleepTime=100; 23 | ConnectionUDP conn; 24 | Receiver receiver=null; 25 | boolean bussy=false; 26 | Object bussyOb=new Object(); 27 | boolean isHave=false; 28 | public HashMap sendTable=new HashMap(); 29 | boolean isReady=false; 30 | Object readyOb=new Object(); 31 | Object winOb=new Object(); 32 | public InetAddress dstIp; 33 | public int dstPort; 34 | public int sequence=0; 35 | int sendOffset=-1; 36 | boolean pause=false; 37 | int unAckMin=0; 38 | int unAckMax=-1; 39 | int sendSum=0; 40 | int reSendSum=0; 41 | UDPOutputStream uos; 42 | int sw=0; 43 | 44 | static Random ran=new Random(); 45 | 46 | long lastSendTime=-1; 47 | 48 | boolean closed=false; 49 | 50 | boolean streamClosed=false; 51 | 52 | static int s=0; 53 | 54 | Object syn_send_table=new Object(); 55 | 56 | HashMap unAckTable=new HashMap(); 57 | 58 | Sender(ConnectionUDP conn){ 59 | this.conn=conn; 60 | uos=new UDPOutputStream (conn); 61 | receiver=conn.receiver; 62 | this.dstIp=conn.dstIp; 63 | this.dstPort=conn.dstPort; 64 | } 65 | 66 | void sendData(byte[] data,int offset,int length) throws ConnectException, InterruptedException{ 67 | int packetLength=RUDPConfig.packageSize; 68 | int sum=(length/packetLength); 69 | if(length%packetLength!=0){ 70 | sum+=1; 71 | } 72 | if(sum==0){ 73 | sum=1; 74 | } 75 | int len=packetLength; 76 | if(length<=len){ 77 | sw++; 78 | sendNata(data,0,length); 79 | sw--; 80 | }else{ 81 | for(int i=0;ilength){ 87 | len=length-(sum-1)*packetLength; 88 | } 89 | } 90 | } 91 | } 92 | 93 | void sendNata(byte[] data,int offset,int length) throws ConnectException, InterruptedException{ 94 | 95 | if(!closed){ 96 | if(!streamClosed){ 97 | DataMessage me=new DataMessage(sequence,data,0,(short) length,conn.connectId,conn.route.localclientId); 98 | me.setDstAddress(dstIp); 99 | me.setDstPort(dstPort); 100 | synchronized (syn_send_table) { 101 | sendTable.put(me.getSequence(),me); 102 | } 103 | 104 | synchronized (winOb){ 105 | if(!conn.receiver.checkWin()){ 106 | try { 107 | winOb.wait(); 108 | } catch (InterruptedException e) { 109 | throw e; 110 | } 111 | } 112 | } 113 | 114 | boolean twice=false; 115 | if(RUDPConfig.twice_tcp){ 116 | twice=true; 117 | } 118 | if(RUDPConfig.double_send_start){ 119 | if(me.getSequence()<=5){ 120 | twice=true; 121 | } 122 | } 123 | sendDataMessage(me,false,twice,true); 124 | lastSendTime=System.currentTimeMillis(); 125 | sendOffset++; 126 | s+=me.getData().length; 127 | conn.clientControl.resendMange.addTask(conn, sequence); 128 | sequence++;//必须放最后 129 | }else{ 130 | throw new ConnectException("RDP连接已断开sendData"); 131 | } 132 | }else{ 133 | throw new ConnectException("RDP连接已经关闭"); 134 | } 135 | 136 | } 137 | 138 | public void closeStream_Local(){ 139 | if(!streamClosed){ 140 | streamClosed=true; 141 | conn.receiver.closeStream_Local(); 142 | if(!conn.stopnow){ 143 | sendCloseMessage_Stream(); 144 | } 145 | } 146 | } 147 | 148 | public void closeStream_Remote(){ 149 | if(!streamClosed){ 150 | streamClosed=true; 151 | } 152 | } 153 | 154 | void sendDataMessage(DataMessage me,boolean resend,boolean twice,boolean block){ 155 | synchronized (conn.clientControl.getSynlock()) { 156 | long startTime=System.nanoTime(); 157 | long t1=System.currentTimeMillis(); 158 | conn.clientControl.onSendDataPacket(conn); 159 | 160 | int timeId=conn.clientControl.getCurrentTimeId(); 161 | 162 | me.create(timeId); 163 | 164 | SendRecord record_current=conn.clientControl.getSendRecord(timeId); 165 | if(!resend){ 166 | //第一次发,修改当前时间记录 167 | me.setFirstSendTimeId(timeId); 168 | me.setFirstSendTime(System.currentTimeMillis()); 169 | record_current.addSended_First(me.getData().length); 170 | record_current.addSended(me.getData().length); 171 | }else { 172 | //重发,修改第一次发送时间记录 173 | SendRecord record=conn.clientControl.getSendRecord(me.getFirstSendTimeId()); 174 | record.addResended(me.getData().length); 175 | record_current.addSended(me.getData().length); 176 | } 177 | 178 | try { 179 | sendSum++; 180 | sum++; 181 | unAckMax++; 182 | 183 | long t=System.currentTimeMillis(); 184 | send(me.getDatagramPacket()); 185 | 186 | if(twice){ 187 | send(me.getDatagramPacket());//发两次 188 | } 189 | if(block){ 190 | conn.clientControl.sendSleep(startTime, me.getData().length); 191 | } 192 | TrafficEvent event=new TrafficEvent("",ran.nextLong(),me.getData().length,TrafficEvent.type_uploadTraffic); 193 | Route.fireEvent(event); 194 | } catch (IOException e) { 195 | e.printStackTrace(); 196 | } 197 | } 198 | 199 | } 200 | 201 | void sendAckDelay(int ackSequence){ 202 | conn.route.delayAckManage.addAck(conn, ackSequence); 203 | } 204 | 205 | void sendLastReadDelay(){ 206 | conn.route.delayAckManage.addLastRead(conn); 207 | } 208 | 209 | DataMessage getDataMessage(int sequence){ 210 | return sendTable.get(sequence); 211 | } 212 | 213 | public void reSend(int sequence,int count){ 214 | if(sendTable.containsKey(sequence)){ 215 | DataMessage dm=sendTable.get(sequence); 216 | if(dm!=null){ 217 | sendDataMessage(dm,true,false,true); 218 | } 219 | } 220 | } 221 | 222 | public void destroy(){ 223 | synchronized (syn_send_table) { 224 | sendTable.clear(); 225 | } 226 | } 227 | 228 | //删除后不会重发 229 | void removeSended_Ack(int sequence){ 230 | synchronized (syn_send_table) { 231 | DataMessage dm=sendTable.remove(sequence); 232 | } 233 | } 234 | 235 | void play(){ 236 | synchronized (winOb){ 237 | winOb.notifyAll(); 238 | } 239 | } 240 | 241 | void close(){ 242 | synchronized (winOb){ 243 | closed=true; 244 | winOb.notifyAll(); 245 | } 246 | } 247 | 248 | void sendCloseMessage_Stream(){ 249 | CloseMessage_Stream cm=new CloseMessage_Stream(conn.connectId,conn.route.localclientId,sequence); 250 | cm.setDstAddress(dstIp); 251 | cm.setDstPort(dstPort); 252 | try { 253 | send(cm.getDatagramPacket()); 254 | } catch (IOException e) { 255 | e.printStackTrace(); 256 | } 257 | try { 258 | send(cm.getDatagramPacket()); 259 | } catch (IOException e) { 260 | e.printStackTrace(); 261 | } 262 | } 263 | 264 | void sendCloseMessage_Conn(){ 265 | CloseMessage_Conn cm=new CloseMessage_Conn(conn.connectId,conn.route.localclientId); 266 | cm.setDstAddress(dstIp); 267 | cm.setDstPort(dstPort); 268 | try { 269 | send(cm.getDatagramPacket()); 270 | } catch (IOException e) { 271 | e.printStackTrace(); 272 | } 273 | try { 274 | send(cm.getDatagramPacket()); 275 | } catch (IOException e) { 276 | e.printStackTrace(); 277 | } 278 | } 279 | 280 | void sendALMessage(ArrayList ackList){ 281 | int currentTimeId=conn.receiver.getCurrentTimeId(); 282 | AckListMessage alm=new AckListMessage(conn.connetionId,ackList,conn.receiver.lastRead,conn 283 | .clientControl.sendRecordTable_remote,currentTimeId, 284 | conn.connectId,conn.route.localclientId); 285 | alm.setDstAddress(dstIp); 286 | alm.setDstPort(dstPort); 287 | try { 288 | send(alm.getDatagramPacket()); 289 | } catch (IOException e) { 290 | e.printStackTrace(); 291 | } 292 | } 293 | 294 | void send(DatagramPacket dp) throws IOException { 295 | sendPacket(dp,conn.connectId); 296 | } 297 | 298 | public void sendPacket(DatagramPacket dp,Integer di) throws IOException{ 299 | conn.clientControl.sendPacket(dp); 300 | } 301 | 302 | } 303 | -------------------------------------------------------------------------------- /src/net/fs/rudp/ClientControl.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 D1SM.net 2 | 3 | package net.fs.rudp; 4 | 5 | import java.io.IOException; 6 | import java.net.DatagramPacket; 7 | import java.net.InetAddress; 8 | import java.util.HashMap; 9 | import java.util.Iterator; 10 | import java.util.Random; 11 | 12 | import net.fs.rudp.message.PingMessage; 13 | import net.fs.rudp.message.PingMessage2; 14 | import net.fs.utils.ByteIntConvert; 15 | import net.fs.utils.MLog; 16 | import net.fs.utils.MessageCheck; 17 | 18 | public class ClientControl { 19 | 20 | int clientId; 21 | 22 | 23 | Thread sendThread; 24 | 25 | Object synlock=new Object(); 26 | 27 | private HashMap sendRecordTable=new HashMap(); 28 | 29 | 30 | HashMap sendRecordTable_remote=new HashMap(); 31 | 32 | 33 | long startSendTime=0; 34 | 35 | int maxSpeed=(int) (1024*1024); 36 | 37 | int initSpeed=(int) maxSpeed; 38 | 39 | int currentSpeed=initSpeed; 40 | 41 | int lastTime=-1; 42 | 43 | Object syn_timeid=new Object(); 44 | 45 | long sended=0; 46 | 47 | long markTime=0; 48 | 49 | long lastSendPingTime,lastReceivePingTime=System.currentTimeMillis(); 50 | 51 | Random ran=new Random(); 52 | 53 | HashMap pingTable=new HashMap(); 54 | 55 | public int pingDelay=250; 56 | 57 | int clientId_real=-1; 58 | 59 | long needSleep_All,trueSleep_All; 60 | 61 | int maxAcked=0; 62 | 63 | long lastLockTime; 64 | 65 | Route route; 66 | 67 | InetAddress dstIp; 68 | 69 | int dstPort; 70 | 71 | public HashMap connTable=new HashMap(); 72 | 73 | Object syn_connTable=new Object(); 74 | 75 | Object syn_tunTable=new Object(); 76 | 77 | String password; 78 | 79 | public ResendManage resendMange; 80 | 81 | boolean closed=false; 82 | 83 | { 84 | resendMange = new ResendManage(); 85 | } 86 | 87 | ClientControl(Route route,int clientId,InetAddress dstIp,int dstPort){ 88 | this.clientId=clientId; 89 | this.route=route; 90 | this.dstIp=dstIp; 91 | this.dstPort=dstPort; 92 | } 93 | 94 | public void onReceivePacket(DatagramPacket dp){ 95 | byte[] dpData=dp.getData(); 96 | int sType=0; 97 | sType=MessageCheck.checkSType(dp); 98 | int remote_clientId=ByteIntConvert.toInt(dpData, 8); 99 | if(sType==net.fs.rudp.message.MessageType.sType_PingMessage){ 100 | PingMessage pm=new PingMessage(dp); 101 | sendPingMessage2(pm.getPingId(),dp.getAddress(),dp.getPort()); 102 | currentSpeed=pm.getDownloadSpeed()*1024; 103 | }else if(sType==net.fs.rudp.message.MessageType.sType_PingMessage2){ 104 | PingMessage2 pm=new PingMessage2(dp); 105 | lastReceivePingTime=System.currentTimeMillis(); 106 | Long t=pingTable.get(pm.getPingId()); 107 | if(t!=null){ 108 | pingDelay=(int) (System.currentTimeMillis()-t); 109 | String protocal=""; 110 | if(route.isUseTcpTun()){ 111 | protocal="tcp"; 112 | }else { 113 | protocal="udp"; 114 | } 115 | //MLog.println(" receive_ping222: "+pm.getPingId()+" "+new Date()); 116 | MLog.println("delay_"+protocal+" "+pingDelay+"ms "+dp.getAddress().getHostAddress()+":"+dp.getPort()); 117 | } 118 | } 119 | } 120 | 121 | public void sendPacket(DatagramPacket dp) throws IOException{ 122 | 123 | //加密 124 | 125 | route.sendPacket(dp); 126 | } 127 | 128 | void addConnection(ConnectionUDP conn){ 129 | synchronized (syn_connTable) { 130 | connTable.put(conn.connectId, conn); 131 | } 132 | } 133 | 134 | void removeConnection(ConnectionUDP conn){ 135 | synchronized (syn_connTable) { 136 | connTable.remove(conn.connectId); 137 | } 138 | } 139 | 140 | public void close(){ 141 | closed=true; 142 | route.clientManager.removeClient(clientId); 143 | synchronized (syn_connTable) { 144 | Iterator it=getConnTableIterator(); 145 | while(it.hasNext()){ 146 | final ConnectionUDP conn=connTable.get(it.next()); 147 | if(conn!=null){ 148 | Route.es.execute(new Runnable() { 149 | 150 | @Override 151 | public void run() { 152 | conn.stopnow=true; 153 | conn.destroy(true); 154 | } 155 | }); 156 | 157 | } 158 | } 159 | } 160 | } 161 | 162 | Iterator getConnTableIterator(){ 163 | Iterator it=null; 164 | synchronized (syn_connTable) { 165 | it=new CopiedIterator(connTable.keySet().iterator()); 166 | } 167 | return it; 168 | } 169 | 170 | public void updateClientId(int newClientId){ 171 | clientId_real=newClientId; 172 | sendRecordTable.clear(); 173 | sendRecordTable_remote.clear(); 174 | } 175 | 176 | public void onSendDataPacket(ConnectionUDP conn){ 177 | 178 | } 179 | 180 | public void sendPingMessage(){ 181 | int pingid=Math.abs(ran.nextInt()); 182 | long pingTime=System.currentTimeMillis(); 183 | pingTable.put(pingid, pingTime); 184 | lastSendPingTime=System.currentTimeMillis(); 185 | PingMessage lm=new PingMessage(0,route.localclientId,pingid,Route.localDownloadSpeed,Route.localUploadSpeed); 186 | lm.setDstAddress(dstIp); 187 | lm.setDstPort(dstPort); 188 | try { 189 | sendPacket(lm.getDatagramPacket()); 190 | } catch (IOException e) { 191 | //e.printStackTrace(); 192 | } 193 | } 194 | 195 | public void sendPingMessage2(int pingId,InetAddress dstIp,int dstPort){ 196 | PingMessage2 lm=new PingMessage2(0,route.localclientId,pingId); 197 | lm.setDstAddress(dstIp); 198 | lm.setDstPort(dstPort); 199 | try { 200 | sendPacket(lm.getDatagramPacket()); 201 | } catch (IOException e) { 202 | e.printStackTrace(); 203 | } 204 | } 205 | 206 | public void onReceivePing(PingMessage pm){ 207 | if(route.mode==2){ 208 | currentSpeed=pm.getDownloadSpeed()*1024; 209 | //#MLog.println("更新对方速度: "+currentSpeed); 210 | } 211 | } 212 | 213 | SendRecord getSendRecord(int timeId){ 214 | SendRecord record=null; 215 | synchronized (syn_timeid) { 216 | record=sendRecordTable.get(timeId); 217 | if(record==null){ 218 | record=new SendRecord(); 219 | record.setTimeId(timeId); 220 | sendRecordTable.put(timeId, record); 221 | } 222 | } 223 | return record; 224 | } 225 | 226 | public int getCurrentTimeId(){ 227 | long current=System.currentTimeMillis(); 228 | if(startSendTime==0){ 229 | startSendTime=current; 230 | } 231 | int timeId=(int) ((current-startSendTime)/1000); 232 | return timeId; 233 | } 234 | 235 | public int getTimeId(long time){ 236 | int timeId=(int) ((time-startSendTime)/1000); 237 | return timeId; 238 | } 239 | 240 | //纳秒 241 | public synchronized void sendSleep(long startTime,int length){ 242 | if(route.mode==1){ 243 | currentSpeed=Route.localUploadSpeed; 244 | } 245 | if(sended==0){ 246 | markTime=startTime; 247 | } 248 | sended+=length; 249 | //10K sleep 250 | if(sended>10*1024){ 251 | long needTime=(long) (1000*1000*1000f*sended/currentSpeed); 252 | long usedTime=System.nanoTime()-markTime; 253 | if(usedTime0){ 259 | if(sleepTime<=moreTime){ 260 | sleepTime=0; 261 | trueSleep_All-=sleepTime; 262 | } 263 | } 264 | 265 | long s=needTime/(1000*1000); 266 | int n=(int) (needTime%(1000*1000)); 267 | long t1=System.nanoTime(); 268 | if(sleepTime>0){ 269 | try { 270 | Thread.sleep(s, n); 271 | } catch (InterruptedException e) { 272 | e.printStackTrace(); 273 | } 274 | trueSleep_All+=(System.nanoTime()-t1); 275 | //#MLog.println("sssssssssss "+(trueSleep_All-needSleep_All)/(1000*1000)); 276 | } 277 | ////#MLog.println("sleepb "+sleepTime+" l "+sended+" s "+s+" n "+n+" tt "+(moreTime)); 278 | } 279 | sended=0; 280 | } 281 | 282 | } 283 | 284 | public Object getSynlock() { 285 | return synlock; 286 | } 287 | 288 | public void setSynlock(Object synlock) { 289 | this.synlock = synlock; 290 | } 291 | 292 | public void setClientId(int clientId) { 293 | this.clientId = clientId; 294 | } 295 | 296 | public int getClientId_real() { 297 | return clientId_real; 298 | } 299 | 300 | public void setClientId_real(int clientId_real) { 301 | this.clientId_real = clientId_real; 302 | lastReceivePingTime=System.currentTimeMillis(); 303 | } 304 | 305 | public long getLastSendPingTime() { 306 | return lastSendPingTime; 307 | } 308 | 309 | public void setLastSendPingTime(long lastSendPingTime) { 310 | this.lastSendPingTime = lastSendPingTime; 311 | } 312 | 313 | public long getLastReceivePingTime() { 314 | return lastReceivePingTime; 315 | } 316 | 317 | public void setLastReceivePingTime(long lastReceivePingTime) { 318 | this.lastReceivePingTime = lastReceivePingTime; 319 | } 320 | 321 | public String getPassword() { 322 | return password; 323 | } 324 | 325 | public void setPassword(String password) { 326 | this.password = password; 327 | } 328 | 329 | } 330 | -------------------------------------------------------------------------------- /src/net/fs/rudp/Route.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 D1SM.net 2 | 3 | package net.fs.rudp; 4 | 5 | import java.io.IOException; 6 | import java.net.DatagramPacket; 7 | import java.net.DatagramSocket; 8 | import java.net.InetAddress; 9 | import java.util.HashMap; 10 | import java.util.HashSet; 11 | import java.util.List; 12 | import java.util.Random; 13 | import java.util.Vector; 14 | import java.util.concurrent.LinkedBlockingQueue; 15 | import java.util.concurrent.SynchronousQueue; 16 | import java.util.concurrent.ThreadPoolExecutor; 17 | import java.util.concurrent.TimeUnit; 18 | 19 | import net.fs.cap.CapEnv; 20 | import net.fs.cap.VDatagramSocket; 21 | import net.fs.rudp.message.MessageType; 22 | import net.fs.utils.ByteIntConvert; 23 | import net.fs.utils.MLog; 24 | import net.fs.utils.MessageCheck; 25 | 26 | 27 | public class Route { 28 | 29 | private DatagramSocket ds; 30 | public HashMap connTable; 31 | Route route; 32 | Thread mainThread; 33 | Thread reveiveThread; 34 | 35 | public static ThreadPoolExecutor es; 36 | 37 | public AckListManage delayAckManage; 38 | 39 | Object syn_ds2Table=new Object(); 40 | 41 | Object syn_tunTable=new Object(); 42 | 43 | Random ran=new Random(); 44 | 45 | public int localclientId=Math.abs(ran.nextInt()); 46 | 47 | LinkedBlockingQueue packetBuffer=new LinkedBlockingQueue(); 48 | 49 | public static int mode_server=2; 50 | 51 | public static int mode_client=1; 52 | 53 | public int mode=mode_client;//1客户端,2服务端 54 | 55 | String pocessName=""; 56 | 57 | HashSet setedTable=new HashSet(); 58 | 59 | static int vv; 60 | 61 | HashSet closedTable=new HashSet(); 62 | 63 | public static int localDownloadSpeed,localUploadSpeed; 64 | 65 | ClientManager clientManager; 66 | 67 | HashSet pingTable=new HashSet(); 68 | 69 | public CapEnv capEnv=null; 70 | 71 | public ClientControl lastClientControl; 72 | 73 | public boolean useTcpTun=true; 74 | 75 | public HashMap contentTable=new HashMap(); 76 | 77 | private static List listenerList=new Vector(); 78 | 79 | { 80 | 81 | delayAckManage = new AckListManage(); 82 | } 83 | 84 | static{ 85 | SynchronousQueue queue = new SynchronousQueue(); 86 | ThreadPoolExecutor executor = new ThreadPoolExecutor(100, Integer.MAX_VALUE, 10*1000, TimeUnit.MILLISECONDS, queue); 87 | es=executor; 88 | } 89 | 90 | public Route(String pocessName,short routePort,int mode2,boolean tcp,boolean tcpEnvSuccess) throws Exception{ 91 | 92 | this.mode=mode2; 93 | useTcpTun=tcp; 94 | this.pocessName=pocessName; 95 | if(useTcpTun){ 96 | if(mode==2){ 97 | //服务端 98 | VDatagramSocket d=new VDatagramSocket(routePort); 99 | d.setClient(false); 100 | try { 101 | capEnv=new CapEnv(false,tcpEnvSuccess); 102 | capEnv.setListenPort(routePort); 103 | capEnv.init(); 104 | } catch (Exception e) { 105 | //e.printStackTrace(); 106 | throw e; 107 | } 108 | d.setCapEnv(capEnv); 109 | 110 | ds=d; 111 | }else { 112 | //客户端 113 | VDatagramSocket d=new VDatagramSocket(); 114 | d.setClient(true); 115 | try { 116 | capEnv=new CapEnv(true,tcpEnvSuccess); 117 | capEnv.init(); 118 | } catch (Exception e) { 119 | //e.printStackTrace(); 120 | throw e; 121 | } 122 | d.setCapEnv(capEnv); 123 | 124 | ds=d; 125 | } 126 | }else { 127 | if(mode==2){ 128 | MLog.info("Listen udp port: "+CapEnv.toUnsigned(routePort)); 129 | ds=new DatagramSocket(CapEnv.toUnsigned(routePort)); 130 | }else { 131 | ds=new DatagramSocket(); 132 | } 133 | } 134 | 135 | connTable=new HashMap(); 136 | clientManager=new ClientManager(this); 137 | reveiveThread=new Thread(){ 138 | @Override 139 | public void run(){ 140 | while(true){ 141 | byte[] b=new byte[1500]; 142 | DatagramPacket dp=new DatagramPacket(b,b.length); 143 | try { 144 | ds.receive(dp); 145 | //MLog.println("接收 "+dp.getAddress()); 146 | packetBuffer.add(dp); 147 | } catch (IOException e) { 148 | e.printStackTrace(); 149 | try { 150 | Thread.sleep(1); 151 | } catch (InterruptedException e1) { 152 | e1.printStackTrace(); 153 | } 154 | continue; 155 | } 156 | } 157 | } 158 | }; 159 | reveiveThread.start(); 160 | 161 | mainThread=new Thread(){ 162 | public void run() { 163 | while(true){ 164 | DatagramPacket dp=null; 165 | try { 166 | dp = packetBuffer.take(); 167 | } catch (InterruptedException e1) { 168 | e1.printStackTrace(); 169 | } 170 | if(dp==null){ 171 | continue; 172 | } 173 | long t1=System.currentTimeMillis(); 174 | byte[] dpData=dp.getData(); 175 | 176 | int sType=0; 177 | if(dp.getData().length<4){ 178 | return; 179 | } 180 | sType=MessageCheck.checkSType(dp); 181 | //MLog.println("route receive MessageType111#"+sType+" "+dp.getAddress()+":"+dp.getPort()); 182 | if(dp!=null){ 183 | 184 | final int connectId=ByteIntConvert.toInt(dpData, 4); 185 | int remote_clientId=ByteIntConvert.toInt(dpData, 8); 186 | 187 | if(closedTable.contains(connectId)&&connectId!=0){ 188 | //#MLog.println("忽略已关闭连接包 "+connectId); 189 | continue; 190 | } 191 | 192 | if(sType==net.fs.rudp.message.MessageType.sType_PingMessage 193 | ||sType==net.fs.rudp.message.MessageType.sType_PingMessage2){ 194 | ClientControl clientControl=null; 195 | if(mode==2){ 196 | //发起 197 | clientControl=clientManager.getClientControl(remote_clientId,dp.getAddress(),dp.getPort()); 198 | }else if(mode==1){ 199 | //接收 200 | String key=dp.getAddress().getHostAddress()+":"+dp.getPort(); 201 | int sim_clientId=Math.abs(key.hashCode()); 202 | clientControl=clientManager.getClientControl(sim_clientId,dp.getAddress(),dp.getPort()); 203 | } 204 | clientControl.onReceivePacket(dp); 205 | }else { 206 | //发起 207 | if(mode==1){ 208 | if(!setedTable.contains(remote_clientId)){ 209 | String key=dp.getAddress().getHostAddress()+":"+dp.getPort(); 210 | int sim_clientId=Math.abs(key.hashCode()); 211 | ClientControl clientControl=clientManager.getClientControl(sim_clientId,dp.getAddress(),dp.getPort()); 212 | if(clientControl.getClientId_real()==-1){ 213 | clientControl.setClientId_real(remote_clientId); 214 | //#MLog.println("首次设置clientId "+remote_clientId); 215 | }else { 216 | if(clientControl.getClientId_real()!=remote_clientId){ 217 | //#MLog.println("服务端重启更新clientId "+sType+" "+clientControl.getClientId_real()+" new: "+remote_clientId); 218 | clientControl.updateClientId(remote_clientId); 219 | } 220 | } 221 | //#MLog.println("cccccc "+sType+" "+remote_clientId); 222 | setedTable.add(remote_clientId); 223 | } 224 | } 225 | 226 | 227 | //udp connection 228 | if(mode==2){ 229 | //接收 230 | try { 231 | getConnection2(dp.getAddress(),dp.getPort(),connectId,remote_clientId); 232 | } catch (Exception e) { 233 | e.printStackTrace(); 234 | } 235 | } 236 | 237 | final ConnectionUDP ds3=connTable.get(connectId); 238 | if(ds3!=null){ 239 | final DatagramPacket dp2=dp; 240 | ds3.receiver.onReceivePacket(dp2); 241 | if(sType==MessageType.sType_DataMessage){ 242 | TrafficEvent event=new TrafficEvent("",ran.nextLong(),dp.getLength(),TrafficEvent.type_downloadTraffic); 243 | fireEvent(event); 244 | } 245 | } 246 | 247 | } 248 | } 249 | } 250 | } 251 | }; 252 | mainThread.start(); 253 | 254 | } 255 | 256 | public static void addTrafficlistener(Trafficlistener listener){ 257 | listenerList.add(listener); 258 | } 259 | 260 | static void fireEvent(TrafficEvent event){ 261 | for(Trafficlistener listener:listenerList){ 262 | int type=event.getType(); 263 | if(type==TrafficEvent.type_downloadTraffic){ 264 | listener.trafficDownload(event); 265 | }else if(type==TrafficEvent.type_uploadTraffic){ 266 | listener.trafficUpload(event); 267 | } 268 | } 269 | } 270 | 271 | public void sendPacket(DatagramPacket dp) throws IOException{ 272 | ds.send(dp); 273 | } 274 | 275 | public ConnectionProcessor createTunnelProcessor(){ 276 | ConnectionProcessor o=null; 277 | try { 278 | Class onwClass = Class.forName(pocessName); 279 | o = (ConnectionProcessor) onwClass.newInstance(); 280 | } catch (ClassNotFoundException e) { 281 | e.printStackTrace(); 282 | } catch (InstantiationException e) { 283 | e.printStackTrace(); 284 | } catch (IllegalAccessException e) { 285 | e.printStackTrace(); 286 | } 287 | return o; 288 | } 289 | 290 | void removeConnection(ConnectionUDP conn){ 291 | synchronized (syn_ds2Table){ 292 | closedTable.add(conn.connectId); 293 | connTable.remove(conn.connectId); 294 | } 295 | } 296 | 297 | //接收连接 298 | public ConnectionUDP getConnection2(InetAddress dstIp,int dstPort,int connectId,int clientId) throws Exception{ 299 | ConnectionUDP conn=connTable.get(connectId); 300 | if(conn==null){ 301 | ClientControl clientControl=clientManager.getClientControl(clientId,dstIp,dstPort); 302 | conn=new ConnectionUDP(this,dstIp,dstPort,2,connectId,clientControl); 303 | synchronized (syn_ds2Table){ 304 | connTable.put(connectId, conn); 305 | } 306 | clientControl.addConnection(conn); 307 | } 308 | return conn; 309 | } 310 | 311 | //发起连接 312 | public ConnectionUDP getConnection(String address,int dstPort,String password) throws Exception{ 313 | InetAddress dstIp=InetAddress.getByName(address); 314 | int connectId=Math.abs(ran.nextInt()); 315 | String key=dstIp.getHostAddress()+":"+dstPort; 316 | int remote_clientId=Math.abs(key.hashCode()); 317 | ClientControl clientControl=clientManager.getClientControl(remote_clientId,dstIp,dstPort); 318 | clientControl.setPassword(password); 319 | ConnectionUDP conn=new ConnectionUDP(this,dstIp,dstPort,1,connectId,clientControl); 320 | synchronized (syn_ds2Table){ 321 | connTable.put(connectId, conn); 322 | } 323 | clientControl.addConnection(conn); 324 | lastClientControl=clientControl; 325 | return conn; 326 | } 327 | 328 | public boolean isUseTcpTun() { 329 | return useTcpTun; 330 | } 331 | 332 | public void setUseTcpTun(boolean useTcpTun) { 333 | this.useTcpTun = useTcpTun; 334 | } 335 | 336 | } 337 | 338 | 339 | -------------------------------------------------------------------------------- /src/net/fs/cap/CustomTcpSackOption.java: -------------------------------------------------------------------------------- 1 | /*_########################################################################## 2 | _## 3 | _## Copyright (C) 2014 Pcap4J.org 4 | _## 5 | _########################################################################## 6 | */ 7 | 8 | package net.fs.cap; 9 | 10 | import static org.pcap4j.util.ByteArrays.*; 11 | 12 | import java.io.Serializable; 13 | import java.util.ArrayList; 14 | import java.util.List; 15 | 16 | import org.pcap4j.packet.IllegalRawDataException; 17 | import org.pcap4j.packet.LengthBuilder; 18 | import org.pcap4j.packet.TcpPacket.TcpOption; 19 | import org.pcap4j.packet.namednumber.TcpOptionKind; 20 | import org.pcap4j.util.ByteArrays; 21 | 22 | /** 23 | * @author Kaito Yamada 24 | * @since pcap4j 1.2.0 25 | */ 26 | public final class CustomTcpSackOption implements TcpOption { 27 | 28 | /* 29 | * http://tools.ietf.org/html/rfc2018 30 | * 31 | * +--------+--------+ 32 | * | Kind=5 | Length | 33 | * +--------+--------+--------+--------+ 34 | * | Left Edge of 1st Block | 35 | * +--------+--------+--------+--------+ 36 | * | Right Edge of 1st Block | 37 | * +--------+--------+--------+--------+ 38 | * | | 39 | * / . . . / 40 | * | | 41 | * +--------+--------+--------+--------+ 42 | * | Left Edge of nth Block | 43 | * +--------+--------+--------+--------+ 44 | * | Right Edge of nth Block | 45 | * +--------+--------+--------+--------+ 46 | */ 47 | 48 | /** 49 | * 50 | */ 51 | private static final long serialVersionUID = -3308738405807657257L; 52 | 53 | private final TcpOptionKind kind = TcpOptionKind.SACK; 54 | private final byte length; 55 | private final List sacks = new ArrayList(); 56 | 57 | /** 58 | * A static factory method. 59 | * This method validates the arguments by {@link ByteArrays#validateBounds(byte[], int, int)}, 60 | * which may throw exceptions undocumented here. 61 | * 62 | * @param rawData rawData 63 | * @param offset offset 64 | * @param length length 65 | * @return a new TcpSackOption object. 66 | * @throws IllegalRawDataException if parsing the raw data fails. 67 | */ 68 | public static CustomTcpSackOption newInstance( 69 | byte[] rawData, int offset, int length 70 | ) throws IllegalRawDataException { 71 | ByteArrays.validateBounds(rawData, offset, length); 72 | return new CustomTcpSackOption(rawData, offset, length); 73 | } 74 | 75 | private CustomTcpSackOption(byte[] rawData, int offset, int length) throws IllegalRawDataException { 76 | if (length < 2) { 77 | StringBuilder sb = new StringBuilder(50); 78 | sb.append("The raw data length must be more than 1. rawData: ") 79 | .append(ByteArrays.toHexString(rawData, " ")) 80 | .append(", offset: ") 81 | .append(offset) 82 | .append(", length: ") 83 | .append(length); 84 | throw new IllegalRawDataException(sb.toString()); 85 | } 86 | if (rawData[offset] != kind.value()) { 87 | StringBuilder sb = new StringBuilder(100); 88 | sb.append("The kind must be: ") 89 | .append(kind.valueAsString()) 90 | .append(" rawData: ") 91 | .append(ByteArrays.toHexString(rawData, " ")) 92 | .append(", offset: ") 93 | .append(offset) 94 | .append(", length: ") 95 | .append(length); 96 | throw new IllegalRawDataException(sb.toString()); 97 | } 98 | 99 | this.length = rawData[1 + offset]; 100 | int lengthFieldAsInt = getLengthAsInt(); 101 | if (lengthFieldAsInt < 2) { 102 | throw new IllegalRawDataException( 103 | "The value of length field must be more than 1 but: " + lengthFieldAsInt 104 | ); 105 | } 106 | 107 | if ((lengthFieldAsInt - 2) % (INT_SIZE_IN_BYTES * 2) != 0) { 108 | StringBuilder sb = new StringBuilder(100); 109 | sb.append( 110 | "The value of length field must be an integer multiple of 8 octets long but: " 111 | ) 112 | .append(lengthFieldAsInt); 113 | throw new IllegalRawDataException(sb.toString()); 114 | } 115 | if (length < lengthFieldAsInt) { 116 | StringBuilder sb = new StringBuilder(100); 117 | sb.append("rawData is too short. length field: ") 118 | .append(lengthFieldAsInt) 119 | .append(", rawData: ") 120 | .append(ByteArrays.toHexString(rawData, " ")) 121 | .append(", offset: ") 122 | .append(offset) 123 | .append(", length: ") 124 | .append(length); 125 | throw new IllegalRawDataException(sb.toString()); 126 | } 127 | 128 | for (int i = 2; i < lengthFieldAsInt; i += INT_SIZE_IN_BYTES * 2) { 129 | sacks.add( 130 | new Sack( 131 | ByteArrays.getInt(rawData, i + offset), 132 | ByteArrays.getInt(rawData, i + INT_SIZE_IN_BYTES + offset) 133 | ) 134 | ); 135 | } 136 | } 137 | 138 | private CustomTcpSackOption(Builder builder) { 139 | if ( 140 | builder == null 141 | || builder.sacks == null 142 | ) { 143 | StringBuilder sb = new StringBuilder(); 144 | sb.append("builder: ").append(builder) 145 | .append(" builder.sacks: ").append(builder.sacks); 146 | throw new NullPointerException(sb.toString()); 147 | } 148 | 149 | this.sacks.addAll(builder.sacks); 150 | 151 | if (builder.correctLengthAtBuild) { 152 | this.length = (byte)length(); 153 | } 154 | else { 155 | this.length = builder.length; 156 | } 157 | } 158 | 159 | @Override 160 | public TcpOptionKind getKind() { 161 | return kind; 162 | } 163 | 164 | /** 165 | * 166 | * @return length 167 | */ 168 | public byte getLength() { return length; } 169 | 170 | /** 171 | * 172 | * @return length 173 | */ 174 | public int getLengthAsInt() { return 0xFF & length; } 175 | 176 | @Override 177 | public int length() { 178 | return sacks.size() * INT_SIZE_IN_BYTES * 2 + 2; 179 | } 180 | 181 | @Override 182 | public byte[] getRawData() { 183 | byte[] rawData = new byte[length()]; 184 | rawData[0] = kind.value(); 185 | rawData[1] = length; 186 | 187 | int offset = 2; 188 | for (Sack sack: sacks) { 189 | System.arraycopy( 190 | ByteArrays.toByteArray(sack.leftEdge), 0, 191 | rawData, offset, INT_SIZE_IN_BYTES 192 | ); 193 | System.arraycopy( 194 | ByteArrays.toByteArray(sack.rightEdge), 0, 195 | rawData, offset + INT_SIZE_IN_BYTES, INT_SIZE_IN_BYTES 196 | ); 197 | offset += INT_SIZE_IN_BYTES * 2; 198 | } 199 | 200 | return rawData; 201 | } 202 | 203 | /** 204 | * 205 | * @return a new Builder object populated with this object's fields. 206 | */ 207 | public Builder getBuilder() { 208 | return new Builder(this); 209 | } 210 | 211 | @Override 212 | public String toString() { 213 | StringBuilder sb = new StringBuilder(); 214 | sb.append("[Kind: ") 215 | .append(kind); 216 | sb.append("] [Length: ") 217 | .append(getLengthAsInt()) 218 | .append(" bytes]"); 219 | for (Sack sack: sacks) { 220 | sb.append(" [LE: ") 221 | .append(sack.getLeftEdgeAsLong()) 222 | .append(" RE: ") 223 | .append(sack.getRightEdgeAsLong()) 224 | .append("]"); 225 | } 226 | return sb.toString(); 227 | } 228 | 229 | @Override 230 | public boolean equals(Object obj) { 231 | if (obj == this) { return true; } 232 | if (!this.getClass().isInstance(obj)) { return false; } 233 | 234 | CustomTcpSackOption other = (CustomTcpSackOption)obj; 235 | return 236 | length == other.length 237 | && sacks.equals(other.sacks); 238 | } 239 | 240 | public List getSacks() { 241 | return sacks; 242 | } 243 | 244 | @Override 245 | public int hashCode() { 246 | int result = 17; 247 | result = 31 * result + length; 248 | result = 31 * result + sacks.hashCode(); 249 | return result; 250 | } 251 | 252 | /** 253 | * @author Kaito Yamada 254 | * @since pcap4j 1.2.0 255 | */ 256 | public static final class Builder 257 | implements LengthBuilder { 258 | 259 | private byte length; 260 | private boolean correctLengthAtBuild; 261 | private List sacks; 262 | 263 | /** 264 | * 265 | */ 266 | public Builder() {} 267 | 268 | private Builder(CustomTcpSackOption option) { 269 | this.length = option.length; 270 | } 271 | 272 | /** 273 | * @param length length 274 | * @return this Builder object for method chaining. 275 | */ 276 | public Builder length(byte length) { 277 | this.length = length; 278 | return this; 279 | } 280 | 281 | /** 282 | * @param sacks sacks 283 | * @return this Builder object for method chaining. 284 | */ 285 | public Builder sacks(List sacks) { 286 | this.sacks = sacks; 287 | return this; 288 | } 289 | 290 | @Override 291 | public Builder correctLengthAtBuild(boolean correctLengthAtBuild) { 292 | this.correctLengthAtBuild = correctLengthAtBuild; 293 | return this; 294 | } 295 | 296 | @Override 297 | public CustomTcpSackOption build() { 298 | return new CustomTcpSackOption(this); 299 | } 300 | 301 | } 302 | 303 | /** 304 | * @author Kaito Yamada 305 | * @since pcap4j 1.2.0 306 | */ 307 | public static final class Sack implements Serializable { 308 | 309 | /** 310 | * 311 | */ 312 | private static final long serialVersionUID = 1218420566089129438L; 313 | 314 | private final int leftEdge; 315 | private final int rightEdge; 316 | 317 | /** 318 | * @param leftEdge leftEdge 319 | * @param rightEdge rightEdge 320 | */ 321 | public Sack(int leftEdge, int rightEdge) { 322 | this.leftEdge = leftEdge; 323 | this.rightEdge = rightEdge; 324 | } 325 | 326 | /** 327 | * @return leftEdge 328 | */ 329 | public int getLeftEdge() { 330 | return leftEdge; 331 | } 332 | 333 | /** 334 | * @return leftEdge 335 | */ 336 | public long getLeftEdgeAsLong() { 337 | return 0xFFFFFFFFL & leftEdge; 338 | } 339 | 340 | /** 341 | * @return rightEdge 342 | */ 343 | public int getRightEdge() { 344 | return rightEdge; 345 | } 346 | 347 | /** 348 | * @return rightEdge 349 | */ 350 | public long getRightEdgeAsLong() { 351 | return 0xFFFFFFFFL & rightEdge; 352 | } 353 | 354 | @Override 355 | public boolean equals(Object obj) { 356 | if (obj == this) { return true; } 357 | if (!this.getClass().isInstance(obj)) { return false; } 358 | 359 | Sack other = (Sack)obj; 360 | return 361 | leftEdge == other.leftEdge 362 | && rightEdge == other.rightEdge; 363 | } 364 | 365 | @Override 366 | public int hashCode() { 367 | int result = 17; 368 | result = 31 * result + leftEdge; 369 | result = 31 * result + rightEdge; 370 | return result; 371 | } 372 | 373 | } 374 | 375 | } 376 | -------------------------------------------------------------------------------- /src/net/fs/server/FSServer.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 D1SM.net 2 | 3 | // Copyright (c) 2015 D1SM.net 4 | 5 | package net.fs.server; 6 | 7 | import java.io.BufferedReader; 8 | import java.io.DataInputStream; 9 | import java.io.File; 10 | import java.io.FileInputStream; 11 | import java.io.IOException; 12 | import java.io.InputStream; 13 | import java.io.InputStreamReader; 14 | import java.net.BindException; 15 | 16 | import net.fs.rudp.ConnectionProcessor; 17 | import net.fs.rudp.Route; 18 | import net.fs.utils.MLog; 19 | 20 | public class FSServer { 21 | 22 | ConnectionProcessor imTunnelProcessor; 23 | 24 | Route route_udp, route_tcp, route; 25 | 26 | int routePort = 150; 27 | 28 | static FSServer udpServer; 29 | 30 | String systemName = System.getProperty("os.name").toLowerCase(); 31 | 32 | boolean success_firewall_windows=true; 33 | 34 | public static void main(String[] args) { 35 | try { 36 | FSServer fs = new FSServer(); 37 | } catch (Exception e) { 38 | e.printStackTrace(); 39 | if(e instanceof BindException){ 40 | MLog.println("Udp port already in use."); 41 | } 42 | MLog.println("Start failed."); 43 | System.exit(0); 44 | } 45 | } 46 | 47 | static FSServer get() { 48 | return udpServer; 49 | } 50 | 51 | public FSServer() throws Exception { 52 | MLog.info(""); 53 | MLog.info("FinalSpeed server starting... "); 54 | MLog.info("System Name: " + systemName); 55 | udpServer = this; 56 | final MapTunnelProcessor mp = new MapTunnelProcessor(); 57 | 58 | String port_s = readFileData("./cnf/listen_port"); 59 | if (port_s != null && !port_s.trim().equals("")) { 60 | port_s = port_s.replaceAll("\n", "").replaceAll("\r", ""); 61 | routePort = Integer.parseInt(port_s); 62 | } 63 | route_udp = new Route(mp.getClass().getName(), (short) routePort, Route.mode_server, false,true); 64 | if (systemName.equals("linux")) { 65 | startFirewall_linux(); 66 | setFireWall_linux_udp(); 67 | }else if(systemName.contains("windows")){ 68 | startFirewall_windows(); 69 | } 70 | 71 | Route.es.execute(new Runnable() { 72 | 73 | @Override 74 | public void run() { 75 | try { 76 | route_tcp = new Route(mp.getClass().getName(), (short) routePort, Route.mode_server, true,true); 77 | if (systemName.equals("linux")) { 78 | setFireWall_linux_tcp(); 79 | }else if(systemName.contains("windows")){ 80 | if(success_firewall_windows){ 81 | setFireWall_windows_tcp(); 82 | }else{ 83 | System.out.println("启动windows防火墙失败,请先运行防火墙服务."); 84 | } 85 | } 86 | } catch (Exception e) { 87 | // e.printStackTrace(); 88 | } 89 | } 90 | }); 91 | 92 | } 93 | 94 | void startFirewall_windows(){ 95 | 96 | String runFirewall="netsh advfirewall set allprofiles state on"; 97 | Thread standReadThread=null; 98 | Thread errorReadThread=null; 99 | try { 100 | final Process p = Runtime.getRuntime().exec(runFirewall,null); 101 | standReadThread=new Thread(){ 102 | public void run(){ 103 | InputStream is=p.getInputStream(); 104 | BufferedReader localBufferedReader = new BufferedReader(new InputStreamReader(is)); 105 | while (true){ 106 | String line; 107 | try { 108 | line = localBufferedReader.readLine(); 109 | if (line == null){ 110 | break; 111 | }else{ 112 | if(line.contains("Windows")){ 113 | success_firewall_windows=false; 114 | } 115 | } 116 | } catch (IOException e) { 117 | e.printStackTrace(); 118 | //error(); 119 | break; 120 | } 121 | } 122 | } 123 | }; 124 | standReadThread.start(); 125 | 126 | errorReadThread=new Thread(){ 127 | public void run(){ 128 | InputStream is=p.getErrorStream(); 129 | BufferedReader localBufferedReader = new BufferedReader(new InputStreamReader(is)); 130 | while (true){ 131 | String line; 132 | try { 133 | line = localBufferedReader.readLine(); 134 | if (line == null){ 135 | break; 136 | }else{ 137 | System.out.println("error"+line); 138 | } 139 | } catch (IOException e) { 140 | e.printStackTrace(); 141 | //error(); 142 | break; 143 | } 144 | } 145 | } 146 | }; 147 | errorReadThread.start(); 148 | } catch (IOException e) { 149 | e.printStackTrace(); 150 | success_firewall_windows=false; 151 | //error(); 152 | } 153 | 154 | if(standReadThread!=null){ 155 | try { 156 | standReadThread.join(); 157 | } catch (InterruptedException e) { 158 | e.printStackTrace(); 159 | } 160 | } 161 | if(errorReadThread!=null){ 162 | try { 163 | errorReadThread.join(); 164 | } catch (InterruptedException e) { 165 | e.printStackTrace(); 166 | } 167 | } 168 | 169 | } 170 | 171 | void setFireWall_windows_tcp() { 172 | cleanRule_windows(); 173 | try { 174 | if(systemName.contains("xp")||systemName.contains("2003")){ 175 | String cmd_add1="ipseccmd -w REG -p \"tcptun_fs_server\" -r \"Block TCP/"+routePort+"\" -f *+0:"+routePort+":TCP "+" -n BLOCK -x "; 176 | final Process p2 = Runtime.getRuntime().exec(cmd_add1,null); 177 | p2.waitFor(); 178 | }else { 179 | String cmd_add1="netsh advfirewall firewall add rule name=tcptun_fs_server protocol=TCP dir=out localport="+routePort+" action=block "; 180 | final Process p2 = Runtime.getRuntime().exec(cmd_add1,null); 181 | p2.waitFor(); 182 | String cmd_add2="netsh advfirewall firewall add rule name=tcptun_fs_server protocol=TCP dir=in localport="+routePort+" action=block "; 183 | Process p3 = Runtime.getRuntime().exec(cmd_add2,null); 184 | p3.waitFor(); 185 | } 186 | } catch (Exception e1) { 187 | e1.printStackTrace(); 188 | } 189 | } 190 | 191 | void cleanRule_windows(){ 192 | try { 193 | if(systemName.contains("xp")||systemName.contains("2003")){ 194 | String cmd_delete="ipseccmd -p \"tcptun_fs_server\" -w reg -y"; 195 | final Process p1 = Runtime.getRuntime().exec(cmd_delete,null); 196 | p1.waitFor(); 197 | }else { 198 | String cmd_delete="netsh advfirewall firewall delete rule name=tcptun_fs_server "; 199 | final Process p1 = Runtime.getRuntime().exec(cmd_delete,null); 200 | p1.waitFor(); 201 | } 202 | 203 | } catch (Exception e) { 204 | e.printStackTrace(); 205 | } 206 | 207 | } 208 | 209 | void startFirewall_linux() { 210 | String cmd1 = "service iptables start"; 211 | runCommand(cmd1); 212 | } 213 | 214 | void setFireWall_linux_udp() { 215 | cleanUdpTunRule(); 216 | String cmd2 = "iptables -I INPUT -p udp --dport " + routePort + " -j ACCEPT" 217 | + " -m comment --comment udptun_fs_server"; 218 | runCommand(cmd2); 219 | } 220 | 221 | void cleanUdpTunRule() { 222 | while (true) { 223 | int row = getRow("udptun_fs_server"); 224 | if (row > 0) { 225 | // MLog.println("删除行 "+row); 226 | String cmd = "iptables -D INPUT " + row; 227 | runCommand(cmd); 228 | } else { 229 | break; 230 | } 231 | } 232 | } 233 | 234 | void setFireWall_linux_tcp() { 235 | cleanTcpTunRule(); 236 | String cmd2 = "iptables -I INPUT -p tcp --dport " + routePort + " -j DROP" 237 | + " -m comment --comment tcptun_fs_server "; 238 | runCommand(cmd2); 239 | 240 | } 241 | 242 | void cleanTcpTunRule() { 243 | while (true) { 244 | int row = getRow("tcptun_fs_server"); 245 | if (row > 0) { 246 | // MLog.println("删除行 "+row); 247 | String cmd = "iptables -D INPUT " + row; 248 | runCommand(cmd); 249 | } else { 250 | break; 251 | } 252 | } 253 | } 254 | 255 | int getRow(String name) { 256 | int row_delect = -1; 257 | String cme_list_rule = "iptables -L -n --line-number"; 258 | // String [] cmd={"netsh","advfirewall set allprofiles state on"}; 259 | Thread errorReadThread = null; 260 | try { 261 | final Process p = Runtime.getRuntime().exec(cme_list_rule, null); 262 | 263 | errorReadThread = new Thread() { 264 | public void run() { 265 | InputStream is = p.getErrorStream(); 266 | BufferedReader localBufferedReader = new BufferedReader(new InputStreamReader(is)); 267 | while (true) { 268 | String line; 269 | try { 270 | line = localBufferedReader.readLine(); 271 | if (line == null) { 272 | break; 273 | } else { 274 | // System.out.println("erroraaa "+line); 275 | } 276 | } catch (IOException e) { 277 | e.printStackTrace(); 278 | // error(); 279 | break; 280 | } 281 | } 282 | } 283 | }; 284 | errorReadThread.start(); 285 | 286 | InputStream is = p.getInputStream(); 287 | BufferedReader localBufferedReader = new BufferedReader(new InputStreamReader(is)); 288 | while (true) { 289 | String line; 290 | try { 291 | line = localBufferedReader.readLine(); 292 | // System.out.println("standaaa "+line); 293 | if (line == null) { 294 | break; 295 | } else { 296 | if (line.contains(name)) { 297 | int index = line.indexOf(" "); 298 | if (index > 0) { 299 | String n = line.substring(0, index); 300 | try { 301 | if (row_delect < 0) { 302 | // System.out.println("standaaabbb 303 | // "+line); 304 | row_delect = Integer.parseInt(n); 305 | } 306 | } catch (Exception e) { 307 | 308 | } 309 | } 310 | } 311 | ; 312 | } 313 | } catch (IOException e) { 314 | e.printStackTrace(); 315 | break; 316 | } 317 | } 318 | 319 | errorReadThread.join(); 320 | p.waitFor(); 321 | } catch (Exception e) { 322 | e.printStackTrace(); 323 | // error(); 324 | } 325 | return row_delect; 326 | } 327 | 328 | void runCommand(String command) { 329 | Thread standReadThread = null; 330 | Thread errorReadThread = null; 331 | try { 332 | final Process p = Runtime.getRuntime().exec(command, null); 333 | standReadThread = new Thread() { 334 | public void run() { 335 | InputStream is = p.getInputStream(); 336 | BufferedReader localBufferedReader = new BufferedReader(new InputStreamReader(is)); 337 | while (true) { 338 | String line; 339 | try { 340 | line = localBufferedReader.readLine(); 341 | // System.out.println("stand "+line); 342 | if (line == null) { 343 | break; 344 | } 345 | } catch (IOException e) { 346 | e.printStackTrace(); 347 | break; 348 | } 349 | } 350 | } 351 | }; 352 | standReadThread.start(); 353 | 354 | errorReadThread = new Thread() { 355 | public void run() { 356 | InputStream is = p.getErrorStream(); 357 | BufferedReader localBufferedReader = new BufferedReader(new InputStreamReader(is)); 358 | while (true) { 359 | String line; 360 | try { 361 | line = localBufferedReader.readLine(); 362 | if (line == null) { 363 | break; 364 | } else { 365 | // System.out.println("error "+line); 366 | } 367 | } catch (IOException e) { 368 | e.printStackTrace(); 369 | // error(); 370 | break; 371 | } 372 | } 373 | } 374 | }; 375 | errorReadThread.start(); 376 | standReadThread.join(); 377 | errorReadThread.join(); 378 | p.waitFor(); 379 | } catch (Exception e) { 380 | e.printStackTrace(); 381 | // error(); 382 | } 383 | } 384 | 385 | String readFileData(String path) { 386 | String content = null; 387 | FileInputStream fis = null; 388 | DataInputStream dis = null; 389 | try { 390 | File file = new File(path); 391 | fis = new FileInputStream(file); 392 | dis = new DataInputStream(fis); 393 | byte[] data = new byte[(int) file.length()]; 394 | dis.readFully(data); 395 | content = new String(data, "utf-8"); 396 | } catch (Exception e) { 397 | // e.printStackTrace(); 398 | } finally { 399 | if (dis != null) { 400 | try { 401 | dis.close(); 402 | } catch (IOException e) { 403 | e.printStackTrace(); 404 | } 405 | } 406 | } 407 | return content; 408 | } 409 | 410 | public int getRoutePort() { 411 | return routePort; 412 | } 413 | 414 | } 415 | -------------------------------------------------------------------------------- /src/net/fs/client/MapClient.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 D1SM.net 2 | 3 | package net.fs.client; 4 | 5 | import java.io.BufferedReader; 6 | import java.io.File; 7 | import java.io.FileOutputStream; 8 | import java.io.IOException; 9 | import java.io.InputStream; 10 | import java.io.InputStreamReader; 11 | import java.net.InetAddress; 12 | import java.net.ServerSocket; 13 | import java.net.Socket; 14 | import java.security.NoSuchAlgorithmException; 15 | import java.util.ArrayList; 16 | import java.util.HashSet; 17 | import java.util.Random; 18 | 19 | import javax.crypto.KeyGenerator; 20 | import javax.crypto.SecretKey; 21 | 22 | import net.fs.rudp.ClientProcessorInterface; 23 | import net.fs.rudp.ConnectionProcessor; 24 | import net.fs.rudp.RUDPConfig; 25 | import net.fs.rudp.Route; 26 | import net.fs.rudp.TrafficEvent; 27 | import net.fs.rudp.Trafficlistener; 28 | import net.fs.utils.MLog; 29 | import net.fs.utils.NetStatus; 30 | 31 | public class MapClient implements Trafficlistener{ 32 | 33 | ConnectionProcessor imTunnelProcessor; 34 | 35 | Route route_udp,route_tcp; 36 | 37 | short routePort=45; 38 | 39 | ClientUII ui; 40 | 41 | String serverAddress=""; 42 | 43 | InetAddress address=null; 44 | 45 | int serverPort=130; 46 | 47 | NetStatus netStatus; 48 | 49 | long lastTrafficTime; 50 | 51 | int downloadSum=0; 52 | 53 | int uploadSum=0; 54 | 55 | Thread clientUISpeedUpdateThread; 56 | 57 | int connNum=0; 58 | 59 | HashSet processTable=new HashSet(); 60 | 61 | Object syn_process=new Object(); 62 | 63 | static MapClient mapClient; 64 | 65 | PortMapManager portMapManager; 66 | 67 | public String mapdstAddress; 68 | 69 | public int mapdstPort; 70 | 71 | static int monPort=25874; 72 | 73 | String systemName=System.getProperty("os.name").toLowerCase(); 74 | 75 | boolean useTcp=true; 76 | 77 | long clientId; 78 | 79 | Random ran=new Random(); 80 | 81 | boolean tcpEnable; 82 | 83 | MapClient(ClientUI ui,boolean tcpEnvSuccess) throws Exception { 84 | this.ui=ui; 85 | mapClient=this; 86 | try { 87 | final ServerSocket socket=new ServerSocket(monPort); 88 | new Thread(){ 89 | public void run(){ 90 | try { 91 | socket.accept(); 92 | } catch (IOException e) { 93 | e.printStackTrace(); 94 | System.exit(0); 95 | } 96 | } 97 | }.start(); 98 | } catch (Exception e) { 99 | //e.printStackTrace(); 100 | System.exit(0); 101 | } 102 | try { 103 | route_tcp = new Route(null,routePort,Route.mode_client,true,tcpEnvSuccess); 104 | } catch (Exception e1) { 105 | //e1.printStackTrace(); 106 | throw e1; 107 | } 108 | try { 109 | route_udp = new Route(null,routePort,Route.mode_client,false,tcpEnvSuccess); 110 | } catch (Exception e1) { 111 | //e1.printStackTrace(); 112 | throw e1; 113 | } 114 | netStatus=new NetStatus(); 115 | 116 | portMapManager=new PortMapManager(this); 117 | 118 | clientUISpeedUpdateThread=new Thread(){ 119 | public void run(){ 120 | while(true){ 121 | try { 122 | Thread.sleep(500); 123 | } catch (InterruptedException e1) { 124 | e1.printStackTrace(); 125 | } 126 | } 127 | } 128 | }; 129 | clientUISpeedUpdateThread.start(); 130 | 131 | Route.addTrafficlistener(this); 132 | 133 | } 134 | 135 | public static MapClient get(){ 136 | return mapClient; 137 | } 138 | 139 | 140 | public void setMapServer(String serverAddress,int serverPort,int remotePort,String passwordMd5,String password_proxy_Md5,boolean direct_cn,boolean tcp, 141 | String password){ 142 | if(this.serverAddress==null 143 | ||!this.serverAddress.equals(serverAddress) 144 | ||this.serverPort!=serverPort){ 145 | 146 | if(route_tcp.lastClientControl!=null){ 147 | route_tcp.lastClientControl.close(); 148 | } 149 | 150 | if(route_udp.lastClientControl!=null){ 151 | route_udp.lastClientControl.close(); 152 | } 153 | 154 | cleanRule(); 155 | if(serverAddress!=null&&!serverAddress.equals("")){ 156 | setFireWallRule(serverAddress,serverPort); 157 | } 158 | 159 | } 160 | this.serverAddress=serverAddress; 161 | this.serverPort=serverPort; 162 | address=null; 163 | useTcp=tcp; 164 | resetConnection(); 165 | } 166 | 167 | 168 | void setFireWallRule(String serverAddress,int serverPort){ 169 | String ip; 170 | try { 171 | ip = InetAddress.getByName(serverAddress).getHostAddress(); 172 | if(systemName.contains("mac os")){ 173 | if(ui.isOsx_fw_pf ()){ 174 | String tempPath="./pf.conf"; 175 | File f=new File(tempPath); 176 | File d=f.getParentFile(); 177 | if(!d.exists()){ 178 | d.mkdirs(); 179 | } 180 | if(f.exists()){ 181 | f.delete(); 182 | } 183 | //必须换行结束 184 | String content="block drop quick proto tcp from any to "+ip+" port = "+serverPort+"\n"; 185 | saveFile(content.getBytes(), tempPath); 186 | 187 | String cmd1="pfctl -d"; 188 | runCommand(cmd1); 189 | 190 | String cmd2="pfctl -Rf "+f.getAbsolutePath(); 191 | runCommand(cmd2); 192 | 193 | String cmd3="pfctl -e"; 194 | runCommand(cmd3); 195 | 196 | //f.delete(); 197 | }else if(ui.isOsx_fw_ipfw()){ 198 | String cmd2="sudo ipfw add 5050 deny tcp from any to "+ip+" "+serverAddress+" out"; 199 | runCommand(cmd2); 200 | } 201 | }else if(systemName.contains("linux")){ 202 | String cmd2="iptables -t filter -A OUTPUT -d "+ip+" -p tcp --dport "+serverPort+" -j DROP -m comment --comment tcptun_fs "; 203 | runCommand(cmd2); 204 | }else if (systemName.contains("windows")) { 205 | try { 206 | if(systemName.contains("xp")||systemName.contains("2003")){ 207 | String cmd_add1="ipseccmd -w REG -p \"tcptun_fs\" -r \"Block TCP/"+serverPort+"\" -f 0/255.255.255.255="+ip+"/255.255.255.255:"+serverPort+":tcp -n BLOCK -x "; 208 | final Process p2 = Runtime.getRuntime().exec(cmd_add1,null); 209 | p2.waitFor(); 210 | }else { 211 | String cmd_add1="netsh advfirewall firewall add rule name=tcptun_fs protocol=TCP dir=out remoteport="+serverPort+" remoteip="+ip+" action=block "; 212 | final Process p2 = Runtime.getRuntime().exec(cmd_add1,null); 213 | p2.waitFor(); 214 | String cmd_add2="netsh advfirewall firewall add rule name=tcptun_fs protocol=TCP dir=in remoteport="+serverPort+" remoteip="+ip+" action=block "; 215 | Process p3 = Runtime.getRuntime().exec(cmd_add2,null); 216 | p3.waitFor(); 217 | } 218 | } catch (Exception e1) { 219 | e1.printStackTrace(); 220 | } 221 | } 222 | } catch (Exception e) { 223 | e.printStackTrace(); 224 | } 225 | 226 | } 227 | 228 | void saveFile(byte[] data,String path) throws Exception{ 229 | FileOutputStream fos=null; 230 | try { 231 | fos=new FileOutputStream(path); 232 | fos.write(data); 233 | } catch (Exception e) { 234 | throw e; 235 | } finally { 236 | if(fos!=null){ 237 | fos.close(); 238 | } 239 | } 240 | } 241 | 242 | void cleanRule(){ 243 | if(systemName.contains("mac os")){ 244 | cleanTcpTunRule_osx(); 245 | }else if(systemName.contains("linux")){ 246 | cleanTcpTunRule_linux(); 247 | }else { 248 | try { 249 | if(systemName.contains("xp")||systemName.contains("2003")){ 250 | String cmd_delete="ipseccmd -p \"tcptun_fs\" -w reg -y"; 251 | final Process p1 = Runtime.getRuntime().exec(cmd_delete,null); 252 | p1.waitFor(); 253 | }else { 254 | String cmd_delete="netsh advfirewall firewall delete rule name=tcptun_fs "; 255 | final Process p1 = Runtime.getRuntime().exec(cmd_delete,null); 256 | p1.waitFor(); 257 | } 258 | 259 | } catch (Exception e) { 260 | e.printStackTrace(); 261 | } 262 | } 263 | } 264 | 265 | void cleanTcpTunRule_osx(){ 266 | String cmd2="sudo ipfw delete 5050"; 267 | runCommand(cmd2); 268 | } 269 | 270 | 271 | void cleanTcpTunRule_linux(){ 272 | while(true){ 273 | int row=getRow_linux(); 274 | if(row>0){ 275 | //MLog.println("删除行 "+row); 276 | String cmd="iptables -D OUTPUT "+row; 277 | runCommand(cmd); 278 | }else { 279 | break; 280 | } 281 | } 282 | } 283 | 284 | int getRow_linux(){ 285 | int row_delect=-1; 286 | String cme_list_rule="iptables -L -n --line-number"; 287 | //String [] cmd={"netsh","advfirewall set allprofiles state on"}; 288 | Thread errorReadThread=null; 289 | try { 290 | final Process p = Runtime.getRuntime().exec(cme_list_rule,null); 291 | 292 | errorReadThread=new Thread(){ 293 | public void run(){ 294 | InputStream is=p.getErrorStream(); 295 | BufferedReader localBufferedReader = new BufferedReader(new InputStreamReader(is)); 296 | while (true){ 297 | String line; 298 | try { 299 | line = localBufferedReader.readLine(); 300 | if (line == null){ 301 | break; 302 | }else{ 303 | //System.out.println("erroraaa "+line); 304 | } 305 | } catch (IOException e) { 306 | e.printStackTrace(); 307 | //error(); 308 | break; 309 | } 310 | } 311 | } 312 | }; 313 | errorReadThread.start(); 314 | 315 | 316 | 317 | InputStream is=p.getInputStream(); 318 | BufferedReader localBufferedReader = new BufferedReader(new InputStreamReader(is)); 319 | while (true){ 320 | String line; 321 | try { 322 | line = localBufferedReader.readLine(); 323 | // System.out.println("standaaa "+line); 324 | if (line == null){ 325 | break; 326 | }else{ 327 | if(line.contains("tcptun_fs")){ 328 | int index=line.indexOf(" "); 329 | if(index>0){ 330 | String n=line.substring(0, index); 331 | try { 332 | if(row_delect<0){ 333 | //System.out.println("standaaabbb "+line); 334 | row_delect=Integer.parseInt(n); 335 | } 336 | } catch (Exception e) { 337 | 338 | } 339 | } 340 | }; 341 | } 342 | } catch (IOException e) { 343 | e.printStackTrace(); 344 | break; 345 | } 346 | } 347 | 348 | 349 | errorReadThread.join(); 350 | p.waitFor(); 351 | } catch (Exception e) { 352 | e.printStackTrace(); 353 | //error(); 354 | } 355 | return row_delect; 356 | } 357 | 358 | void resetConnection(){ 359 | synchronized (syn_process) { 360 | 361 | } 362 | } 363 | 364 | public void onProcessClose(ClientProcessorInterface process){ 365 | synchronized (syn_process) { 366 | processTable.remove(process); 367 | } 368 | } 369 | 370 | synchronized public void closeAndTryConnect_Login(boolean testSpeed){ 371 | close(); 372 | boolean loginOK=ui.login(); 373 | if(loginOK){ 374 | ui.updateNode(testSpeed); 375 | //testPool(); 376 | } 377 | } 378 | 379 | synchronized public void closeAndTryConnect(){ 380 | close(); 381 | //testPool(); 382 | } 383 | 384 | public void close(){ 385 | //closeAllProxyRequest(); 386 | //poolManage.close(); 387 | //CSocketPool.closeAll(); 388 | } 389 | 390 | public void trafficDownload(TrafficEvent event) { 391 | ////#MLog.println("下载 "+event.getTraffic()); 392 | netStatus.addDownload(event.getTraffic()); 393 | lastTrafficTime=System.currentTimeMillis(); 394 | downloadSum+=event.getTraffic(); 395 | } 396 | 397 | public void trafficUpload(TrafficEvent event) { 398 | ////#MLog.println("上传 "+event.getTraffic()); 399 | netStatus.addUpload(event.getTraffic()); 400 | lastTrafficTime=System.currentTimeMillis(); 401 | uploadSum+=event.getTraffic(); 402 | } 403 | 404 | static void runCommand(String command){ 405 | Thread standReadThread=null; 406 | Thread errorReadThread=null; 407 | try { 408 | final Process p = Runtime.getRuntime().exec(command,null); 409 | standReadThread=new Thread(){ 410 | public void run(){ 411 | InputStream is=p.getInputStream(); 412 | BufferedReader localBufferedReader = new BufferedReader(new InputStreamReader(is)); 413 | while (true){ 414 | String line; 415 | try { 416 | line = localBufferedReader.readLine(); 417 | //System.out.println("stand "+line); 418 | if (line == null){ 419 | break; 420 | } 421 | } catch (IOException e) { 422 | e.printStackTrace(); 423 | break; 424 | } 425 | } 426 | } 427 | }; 428 | standReadThread.start(); 429 | 430 | errorReadThread=new Thread(){ 431 | public void run(){ 432 | InputStream is=p.getErrorStream(); 433 | BufferedReader localBufferedReader = new BufferedReader(new InputStreamReader(is)); 434 | while (true){ 435 | String line; 436 | try { 437 | line = localBufferedReader.readLine(); 438 | if (line == null){ 439 | break; 440 | }else{ 441 | //System.out.println("error "+line); 442 | } 443 | } catch (IOException e) { 444 | e.printStackTrace(); 445 | //error(); 446 | break; 447 | } 448 | } 449 | } 450 | }; 451 | errorReadThread.start(); 452 | standReadThread.join(); 453 | errorReadThread.join(); 454 | p.waitFor(); 455 | } catch (Exception e) { 456 | e.printStackTrace(); 457 | //error(); 458 | } 459 | } 460 | 461 | public boolean isUseTcp() { 462 | return useTcp; 463 | } 464 | 465 | public void setUseTcp(boolean useTcp) { 466 | this.useTcp = useTcp; 467 | } 468 | 469 | public ClientUII getUi() { 470 | return ui; 471 | } 472 | 473 | public void setUi(ClientUII ui) { 474 | this.ui = ui; 475 | } 476 | 477 | } 478 | -------------------------------------------------------------------------------- /src/net/fs/cap/TCPTun.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 D1SM.net 2 | 3 | package net.fs.cap; 4 | 5 | import java.net.Inet4Address; 6 | import java.net.InetAddress; 7 | import java.util.ArrayList; 8 | import java.util.HashMap; 9 | import java.util.HashSet; 10 | import java.util.Random; 11 | 12 | import net.fs.utils.MLog; 13 | 14 | import org.pcap4j.core.NotOpenException; 15 | import org.pcap4j.core.PcapHandle; 16 | import org.pcap4j.core.PcapNativeException; 17 | import org.pcap4j.packet.EthernetPacket.EthernetHeader; 18 | import org.pcap4j.packet.IpV4Packet.IpV4Header; 19 | import org.pcap4j.packet.Packet; 20 | import org.pcap4j.packet.TcpPacket; 21 | import org.pcap4j.packet.TcpPacket.TcpHeader; 22 | import org.pcap4j.util.MacAddress; 23 | 24 | 25 | public class TCPTun { 26 | 27 | HashMap sendedTable_server=new HashMap (); 28 | HashMap sendedTable_history_server=new HashMap (); 29 | 30 | int clientSequence=Integer.MIN_VALUE; 31 | 32 | static Random random=new Random(); 33 | 34 | PcapHandle sendHandle; 35 | 36 | HashSet selfAckTable=new HashSet(); 37 | 38 | HashMap sendrecordTable=new HashMap(); 39 | 40 | MacAddress dstMacaAddress; 41 | 42 | int sequenceNum=-1; 43 | 44 | Thread sendThread; 45 | 46 | boolean sended=false; 47 | 48 | Packet basePacket_server; 49 | 50 | short baseIdent=100; 51 | 52 | IPacket dst_readed_packet,last_send_packet; 53 | 54 | int presend_server; 55 | 56 | ArrayList packetList=new ArrayList(); 57 | 58 | HashMap packetTable_l=new HashMap(); 59 | 60 | HashMap packetTable=new HashMap(); 61 | 62 | ArrayList unacked_list=new ArrayList(); 63 | 64 | Object syn_packetList=new Object(); 65 | 66 | int max_client_ack=Integer.MIN_VALUE; 67 | 68 | int sendIndex=0; 69 | 70 | long lasSetDelayTime=0; 71 | 72 | long lastDelay=300; 73 | 74 | Object syn_delay=new Object(); 75 | 76 | Thread resendScanThread; 77 | 78 | boolean connectReady=false; 79 | 80 | boolean preDataReady=false; 81 | 82 | CapEnv capEnv; 83 | 84 | public Inet4Address remoteAddress; 85 | public short remotePort; 86 | int remoteStartSequence; 87 | int remoteSequence; 88 | int remoteIdent; 89 | int remoteSequence_max; 90 | 91 | Inet4Address localAddress; 92 | short localPort; 93 | int localStartSequence=random.nextInt(); 94 | int localSequence; 95 | int localIdent=random.nextInt(Short.MAX_VALUE-100); 96 | 97 | Object syn_send_data=new Object(); 98 | 99 | long lastSendAckTime; 100 | 101 | long lastReceiveDataTime; 102 | 103 | long createTime=System.currentTimeMillis();; 104 | 105 | String key; 106 | 107 | Object syn_ident=new Object(); 108 | 109 | //客户端发起 110 | TCPTun(CapEnv capEnv, 111 | Inet4Address serverAddress,short serverPort, 112 | MacAddress srcAddress_mac,MacAddress dstAddrress_mac){ 113 | this.capEnv=capEnv; 114 | sendHandle=capEnv.sendHandle; 115 | this.remoteAddress=serverAddress; 116 | this.remotePort=serverPort; 117 | localAddress=capEnv.local_ipv4; 118 | localPort=(short)(random.nextInt(64*1024-1-10000)+10000); 119 | Packet syncPacket=null; 120 | try { 121 | syncPacket = PacketUtils.createSync(srcAddress_mac, dstAddrress_mac, localAddress, localPort,serverAddress, serverPort, localStartSequence,getIdent()); 122 | try { 123 | sendHandle.sendPacket(syncPacket); 124 | localSequence=localStartSequence+1; 125 | } catch (Exception e) { 126 | e.printStackTrace(); 127 | } 128 | } catch (Exception e1) { 129 | e1.printStackTrace(); 130 | } 131 | MLog.println("发送第一次握手 "+" ident "+localIdent); 132 | MLog.println(""+syncPacket); 133 | 134 | } 135 | 136 | //服务端接收 137 | TCPTun(CapEnv capServerEnv, 138 | Inet4Address remoteAddress,short remotePort){ 139 | this.capEnv=capServerEnv; 140 | this.remoteAddress=remoteAddress; 141 | this.remotePort=remotePort; 142 | sendHandle=capEnv.sendHandle; 143 | localPort=capServerEnv.listenPort; 144 | localAddress=capEnv.local_ipv4; 145 | } 146 | 147 | void init_client(Inet4Address clientAddress,int clientPort, 148 | Inet4Address serverAddress,int serverPort, 149 | int client_start_sequence){ 150 | 151 | } 152 | 153 | void init_server(Inet4Address clientAddress,int clientPort, 154 | Inet4Address serverAddress,int serverPort, 155 | int client_start_sequence,int server_start_sequence){ 156 | 157 | } 158 | 159 | public void process_server(final Packet packet,EthernetHeader ethernetHeader,IpV4Header ipV4Header,TcpPacket tcpPacket,boolean client){ 160 | TcpHeader tcpHeader=tcpPacket.getHeader(); 161 | 162 | if(!preDataReady){ 163 | if(!connectReady){ 164 | //第一次握手 165 | dstMacaAddress=ethernetHeader.getSrcAddr(); 166 | if(tcpHeader.getSyn()&&!tcpHeader.getAck()){ 167 | remoteStartSequence=tcpHeader.getSequenceNumber(); 168 | remoteSequence=remoteStartSequence+1; 169 | remoteSequence_max=remoteSequence; 170 | MLog.println("接收第一次握手 "+remoteAddress.getHostAddress()+":"+remotePort+"->"+localAddress.getHostAddress()+":"+localPort+" ident "+ipV4Header.getIdentification()); 171 | MLog.println(""+packet); 172 | Packet responePacket=PacketUtils.createSyncAck( 173 | capEnv.local_mac, 174 | capEnv.gateway_mac, 175 | localAddress,(short)localPort, 176 | ipV4Header.getSrcAddr(),tcpHeader.getSrcPort().value(), 177 | tcpHeader.getSequenceNumber()+1,localStartSequence,(short)0 178 | ); 179 | try { 180 | sendHandle.sendPacket(responePacket); 181 | } catch (Exception e) { 182 | e.printStackTrace(); 183 | } 184 | localSequence=localStartSequence+1; 185 | MLog.println("发送第二次握手 "+capEnv.local_mac+"->"+capEnv.gateway_mac+" "+localAddress+"->"+" ident "+0); 186 | 187 | MLog.println(""+responePacket); 188 | } 189 | 190 | if(!tcpHeader.getSyn()&&tcpHeader.getAck()){ 191 | if(tcpPacket.getPayload()==null){ 192 | //第三次握手,客户端确认 193 | if(tcpHeader.getAcknowledgmentNumber()==localSequence){ 194 | MLog.println("接收第三次握手 "+" ident "+ipV4Header.getIdentification()); 195 | MLog.println(packet+""); 196 | Thread t1=new Thread(){ 197 | public void run(){ 198 | //startSend(basePacket_server,syc_sequence_client+1); 199 | } 200 | }; 201 | //t1.start(); 202 | connectReady=true; 203 | } 204 | } 205 | //MLog.println("客户端响应preview\n "+packet); 206 | //MLog.println("request "+tcp.ack()); 207 | sendedTable_server.remove(tcpHeader.getAcknowledgmentNumber()); 208 | boolean selfAck=selfAckTable.contains(ipV4Header.getIdentification()); 209 | //MLog.println("客户端确认 "+"selfack "+selfAck+" id "+ipV4Header.getIdentification()+" ack_sequence "+tcpHeader.getAcknowledgmentNumberAsLong()+" "+sendedTable_server.size()+"ppppppp "+tcpHeader); 210 | } 211 | 212 | }else { 213 | if(tcpPacket.getPayload()!=null){ 214 | preDataReady=true; 215 | onReceiveDataPacket( tcpPacket, tcpHeader, ipV4Header ); 216 | byte[] sim=getSimResponeHead(); 217 | sendData(sim); 218 | } 219 | } 220 | }else { 221 | if(tcpPacket.getPayload()!=null){ 222 | onReceiveDataPacket( tcpPacket, tcpHeader, ipV4Header ); 223 | TunData td=new TunData(); 224 | td.tun=this; 225 | td.data=tcpPacket.getPayload().getRawData(); 226 | capEnv.vDatagramSocket.onReceinveFromTun(td); 227 | } 228 | } 229 | if(tcpHeader.getRst()){ 230 | MLog.println("reset packet "+ipV4Header.getIdentification()+" "+tcpHeader.getSequenceNumber()+" "+remoteAddress.getHostAddress()+":"+remotePort+"->"+localAddress.getHostAddress()+":"+localPort+" "+" ident "+ipV4Header.getIdentification()); 231 | } 232 | 233 | } 234 | 235 | public void process_client(CapEnv capEnv,final Packet packet,EthernetHeader ethernetHeader,IpV4Header ipV4Header,TcpPacket tcpPacket,boolean client){ 236 | 237 | TcpHeader tcpHeader=tcpPacket.getHeader(); 238 | byte[] payload=null; 239 | if(tcpPacket.getPayload()!=null){ 240 | payload=tcpPacket.getPayload().getRawData(); 241 | } 242 | 243 | if(!preDataReady){ 244 | if(!connectReady){ 245 | if(tcpHeader.getAck()&&tcpHeader.getSyn()){ 246 | if(tcpHeader.getAcknowledgmentNumber()==(localStartSequence+1)){ 247 | MLog.println("接收第二次握手 "+" ident "+ipV4Header.getIdentification()); 248 | MLog.println(""+packet); 249 | remoteStartSequence=tcpHeader.getSequenceNumber(); 250 | remoteSequence=remoteStartSequence+1; 251 | remoteSequence_max=remoteSequence; 252 | Packet p3=PacketUtils.createAck(capEnv.local_mac, capEnv.gateway_mac, capEnv.local_ipv4, localPort, remoteAddress, remotePort, remoteSequence , localSequence,getIdent()); 253 | try { 254 | sendHandle.sendPacket(p3); 255 | MLog.println("发送第三次握手 "+" ident "+localIdent); 256 | MLog.println(""+p3); 257 | connectReady=true; 258 | 259 | byte[] sim=getSimRequestHead(remotePort); 260 | sendData(sim); 261 | MLog.println("发送请求 "+" ident "+localIdent); 262 | } catch (PcapNativeException e) { 263 | e.printStackTrace(); 264 | } catch (NotOpenException e) { 265 | e.printStackTrace(); 266 | } 267 | } 268 | } 269 | }else { 270 | if(tcpPacket.getPayload()!=null){ 271 | preDataReady=true; 272 | onReceiveDataPacket( tcpPacket, tcpHeader, ipV4Header ); 273 | MLog.println("接收响应 "+" ident "+ipV4Header.getIdentification()); 274 | } 275 | } 276 | 277 | }else { 278 | if(tcpPacket.getPayload()!=null){ 279 | //MLog.println("客户端正式接收数据 "+capClientEnv.vDatagramSocket); 280 | onReceiveDataPacket( tcpPacket, tcpHeader, ipV4Header ); 281 | TunData td=new TunData(); 282 | td.tun=this; 283 | td.data=tcpPacket.getPayload().getRawData(); 284 | capEnv.vDatagramSocket. 285 | onReceinveFromTun(td); 286 | } 287 | } 288 | if(tcpHeader.getRst()){ 289 | MLog.println("reset packet "+ipV4Header.getIdentification()+" "+tcpHeader.getSequenceNumber()+" "+remoteAddress.getHostAddress()+":"+remotePort+"->"+localAddress.getHostAddress()+":"+localPort); 290 | } 291 | 292 | } 293 | 294 | void onReceiveDataPacket(TcpPacket tcpPacket,TcpHeader tcpHeader,IpV4Header ipV4Header ){ 295 | if(System.currentTimeMillis()-lastSendAckTime>1000){ 296 | int rs=tcpHeader.getSequenceNumber()+tcpPacket.getPayload().getRawData().length; 297 | if(rs>remoteSequence_max){ 298 | remoteSequence_max=rs; 299 | } 300 | Packet ackPacket=PacketUtils.createAck( 301 | capEnv.local_mac, 302 | capEnv.gateway_mac, 303 | localAddress,(short)localPort, 304 | ipV4Header.getSrcAddr(),tcpHeader.getSrcPort().value(), 305 | remoteSequence_max, localSequence,getIdent()); 306 | try { 307 | sendHandle.sendPacket(ackPacket); 308 | } catch (Exception e) { 309 | e.printStackTrace(); 310 | 311 | } 312 | lastSendAckTime=System.currentTimeMillis(); 313 | lastReceiveDataTime=System.currentTimeMillis(); 314 | } 315 | } 316 | 317 | void sendData(byte[] data){ 318 | Packet dataPacket=PacketUtils.createDataPacket(capEnv.local_mac, 319 | capEnv.gateway_mac, 320 | localAddress,localPort, 321 | remoteAddress,remotePort, 322 | localSequence,remoteSequence_max, data, (short) getIdent()); 323 | synchronized (syn_send_data) { 324 | try { 325 | sendHandle.sendPacket(dataPacket); 326 | localSequence+=data.length; 327 | } catch (Exception e) { 328 | e.printStackTrace(); 329 | } 330 | } 331 | 332 | } 333 | 334 | short getIdent(){ 335 | synchronized (syn_ident) { 336 | localIdent++; 337 | if(localIdent>=Short.MAX_VALUE){ 338 | localIdent=0; 339 | } 340 | } 341 | return (short) localIdent; 342 | } 343 | 344 | public static byte[] getSimResponeHead(){ 345 | StringBuffer sb=new StringBuffer(); 346 | 347 | sb.append("HTTP/1.1 200 OK"+"\r\n"); 348 | sb.append("Server: Apache/2.2.15 (CentOS)"+"\r\n"); 349 | sb.append("Accept-Ranges: bytes"+"\r\n"); 350 | sb.append("Content-Length: "+(Math.abs(random.nextInt()))+"\r\n"); 351 | sb.append("Connection: Keep-Alive"+"\r\n"); 352 | sb.append("Content-Type: application/octet-stream"+"\r\n"); 353 | sb.append("\r\n"); 354 | 355 | String simRequest=sb.toString(); 356 | byte[] simData=simRequest.getBytes(); 357 | return simData; 358 | } 359 | 360 | public static byte[] getSimRequestHead(int port){ 361 | StringBuffer sb=new StringBuffer(); 362 | String domainName=getRandomString(5+random.nextInt(10))+".com"; 363 | sb.append("GET /"+getRandomString(8+random.nextInt(10))+"."+getRandomString(2+random.nextInt(5))+" HTTP/1.1"+"\r\n"); 364 | sb.append("Accept: application/x-ms-application, image/jpeg, application/xaml+xml, image/gif, image/pjpeg, application/x-ms-xbap, */*"+"\r\n"); 365 | sb.append("Accept-Language: zh-CN"+"\r\n"); 366 | sb.append("Accept-Encoding: gzip, deflate"+"\r\n"); 367 | sb.append("User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:36.0) Gecko/20100101 Firefox/36.0"+"\r\n"); 368 | sb.append("Host: "+domainName+"\r\n"); 369 | sb.append("Connection: Keep-Alive"+"\r\n"); 370 | sb.append("\r\n"); 371 | String simRequest=sb.toString(); 372 | byte[] simData=simRequest.getBytes(); 373 | return simData; 374 | } 375 | 376 | public static String getRandomString(int length) { //length表示生成字符串的长度 377 | String base = "abcdefghkmnopqrstuvwxyz"; 378 | Random random = new Random(); 379 | StringBuffer sb = new StringBuffer(); 380 | for (int i = 0; i < length; i++) { 381 | int number = random.nextInt(base.length()); 382 | sb.append(base.charAt(number)); 383 | } 384 | return sb.toString(); 385 | } 386 | 387 | public InetAddress getSourcrAddress() { 388 | return localAddress; 389 | } 390 | 391 | public int getSourcePort() { 392 | return localPort; 393 | } 394 | 395 | public void setSourcePort(short sourcePort) { 396 | this.localPort = sourcePort; 397 | } 398 | 399 | public boolean isConnectReady() { 400 | return connectReady; 401 | } 402 | 403 | public void setConnectReady(boolean connectReady) { 404 | this.connectReady = connectReady; 405 | } 406 | 407 | public String getKey() { 408 | return key; 409 | } 410 | 411 | public void setKey(String key) { 412 | this.key = key; 413 | } 414 | 415 | } 416 | -------------------------------------------------------------------------------- /src/net/fs/cap/PacketUtils.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 D1SM.net 2 | 3 | package net.fs.cap; 4 | 5 | import java.net.Inet4Address; 6 | import java.util.ArrayList; 7 | 8 | import org.pcap4j.packet.EthernetPacket; 9 | import org.pcap4j.packet.IpV4Packet; 10 | import org.pcap4j.packet.IpV4Rfc1349Tos; 11 | import org.pcap4j.packet.Packet; 12 | import org.pcap4j.packet.TcpMaximumSegmentSizeOption; 13 | import org.pcap4j.packet.TcpNoOperationOption; 14 | import org.pcap4j.packet.TcpPacket; 15 | import org.pcap4j.packet.TcpPacket.TcpOption; 16 | import org.pcap4j.packet.TcpSackPermittedOption; 17 | import org.pcap4j.packet.TcpWindowScaleOption; 18 | import org.pcap4j.packet.UnknownPacket; 19 | import org.pcap4j.packet.namednumber.EtherType; 20 | import org.pcap4j.packet.namednumber.IpNumber; 21 | import org.pcap4j.packet.namednumber.IpVersion; 22 | import org.pcap4j.packet.namednumber.TcpPort; 23 | import org.pcap4j.util.MacAddress; 24 | 25 | import net.fs.utils.ByteShortConvert; 26 | 27 | public class PacketUtils { 28 | 29 | static byte ttl=64; 30 | 31 | static short mtu=1440; 32 | 33 | static byte shiftCount=6; 34 | 35 | static short window=(short) (64*1024-1); 36 | 37 | public static boolean ppp=false; 38 | 39 | public static byte[] pppHead_static={0x11,0x00,0x44,0x44,0x00,0x44,0x00,0x21}; 40 | 41 | 42 | public static Packet buildIpV4( 43 | MacAddress srcAddress_mac, 44 | MacAddress dstAddrress_mac, 45 | IpV4Packet.Builder builder_ipv4){ 46 | 47 | org.pcap4j.packet.Packet.Builder builder=null; 48 | EtherType etherType=null; 49 | Packet p=null; 50 | if(ppp){ 51 | etherType=EtherType.PPPOE_SESSION_STAGE; 52 | 53 | UnknownPacket.Builder pppBuilder=new UnknownPacket.Builder(); 54 | byte[] ipData=builder_ipv4.build().getRawData(); 55 | 56 | byte[] lenb=new byte[2]; 57 | ByteShortConvert.toByteArray((short) (ipData.length+2), lenb, 0); 58 | 59 | byte[] pppHead=new byte[8]; 60 | System.arraycopy(pppHead_static, 0, pppHead, 0, pppHead.length); 61 | System.arraycopy(lenb, 0, pppHead, 4, 2); 62 | 63 | byte[] newData=new byte[pppHead.length+ipData.length]; 64 | System.arraycopy(pppHead, 0, newData, 0, pppHead.length); 65 | System.arraycopy(ipData, 0, newData, 8, ipData.length); 66 | pppBuilder.rawData(newData); 67 | 68 | builder=pppBuilder; 69 | }else { 70 | etherType=EtherType.IPV4; 71 | builder=builder_ipv4; 72 | } 73 | 74 | EthernetPacket.Builder etherBuilder = new EthernetPacket.Builder(); 75 | etherBuilder.dstAddr(dstAddrress_mac) 76 | .srcAddr(srcAddress_mac) 77 | .type(etherType) 78 | .payloadBuilder(builder) 79 | .paddingAtBuild(true); 80 | 81 | p = etherBuilder.build(); 82 | 83 | return p; 84 | } 85 | 86 | static Packet createDataPacket( 87 | MacAddress srcAddress_mac, 88 | MacAddress dstAddrress_mac, 89 | Inet4Address srcAddress,short srcPort, 90 | Inet4Address dstAddress,short dstPort, 91 | int sequence,int ack, byte[] data,short ident){ 92 | Packet p=null; 93 | 94 | TcpPacket.Builder builder_tcp=new TcpPacket.Builder(); 95 | builder_tcp.payloadBuilder(new UnknownPacket.Builder().rawData(data)); 96 | builder_tcp.correctChecksumAtBuild(true); 97 | builder_tcp.correctLengthAtBuild(true); 98 | builder_tcp.paddingAtBuild(true); 99 | builder_tcp.ack(true); 100 | builder_tcp.acknowledgmentNumber(ack); 101 | //builder_tcp.checksum(tcpHeader.getChecksum()); 102 | //builder_tcp.dataOffset((byte)8); 103 | builder_tcp.dstAddr(dstAddress); 104 | builder_tcp.dstPort(new TcpPort( dstPort,"")); 105 | builder_tcp.fin(false); 106 | //builder_tcp.options(tcpHeader.getOptions()); 107 | //builder_tcp.padding(tcpHeader.getPadding()); 108 | builder_tcp.psh(false); 109 | builder_tcp.reserved((byte) 0); 110 | builder_tcp.rst(false); 111 | builder_tcp.sequenceNumber(sequence); 112 | builder_tcp.srcAddr(srcAddress); 113 | builder_tcp.srcPort(new TcpPort( srcPort,"")); 114 | builder_tcp.syn(false); 115 | builder_tcp.urg(false); 116 | //builder_tcp.urgentPointer(tcpHeader.getUrgentPointer()); 117 | builder_tcp.window( window); 118 | 119 | IpV4Packet.Builder builder_ipv4=new IpV4Packet.Builder(); 120 | builder_ipv4.correctChecksumAtBuild(true); 121 | builder_ipv4.correctLengthAtBuild(true); 122 | builder_ipv4.dontFragmentFlag(true); 123 | builder_ipv4.paddingAtBuild(true); 124 | builder_ipv4.dstAddr(dstAddress); 125 | builder_ipv4.fragmentOffset( (short)0); 126 | //builder_ipv4.headerChecksum(ipV4Header.getHeaderChecksum()); 127 | //short identification= Math.abs(random.nextInt(Short.MAX_VALUE)); 128 | //identification=ident; 129 | builder_ipv4.identification(ident); 130 | builder_ipv4.ihl((byte) 5); 131 | builder_ipv4.moreFragmentFlag(false); 132 | //builder_ipv4.options(ipV4Header.getOptions()); 133 | //builder_ipv4.padding(ipV4Header.getPadding()); 134 | 135 | builder_ipv4.protocol(IpNumber.TCP); 136 | //builder_ipv4.reservedFlag(ipV4Header.getReservedFlag()); 137 | builder_ipv4.srcAddr(srcAddress); 138 | builder_ipv4.tos(IpV4Rfc1349Tos.newInstance((byte) 0)); 139 | //builder_ipv4.totalLength( 52); 140 | builder_ipv4.ttl(ttl); 141 | builder_ipv4.version(IpVersion.IPV4); 142 | builder_ipv4.payloadBuilder(builder_tcp); 143 | 144 | p = buildIpV4(srcAddress_mac,dstAddrress_mac,builder_ipv4); 145 | 146 | return p; 147 | } 148 | 149 | static Packet createAck( 150 | MacAddress srcAddress_mac, 151 | MacAddress dstAddrress_mac, 152 | Inet4Address srcAddress,short srcPort, 153 | Inet4Address dstAddress,short dstPort, 154 | int ack_sequence,int sequence,short ident){ 155 | 156 | TcpPacket.Builder builder_tcp=new TcpPacket.Builder(); 157 | //builder_tcp.payloadBuilder(new UnknownPacket.Builder().rawData(new byte[0])); 158 | builder_tcp.correctChecksumAtBuild(true); 159 | builder_tcp.correctLengthAtBuild(true); 160 | builder_tcp.paddingAtBuild(true); 161 | builder_tcp.ack(true); 162 | builder_tcp.acknowledgmentNumber(ack_sequence); 163 | //builder_tcp.checksum(tcpHeader.getChecksum()); 164 | //builder_tcp.dataOffset((byte) 8); 165 | builder_tcp.dstAddr(dstAddress); 166 | builder_tcp.dstPort(new TcpPort( dstPort,"")); 167 | //builder_tcp.fin(tcpHeader.getFin()); 168 | 169 | builder_tcp.psh(false); 170 | builder_tcp.reserved((byte) 0); 171 | builder_tcp.rst(false); 172 | builder_tcp.sequenceNumber(sequence); 173 | builder_tcp.srcAddr(srcAddress); 174 | builder_tcp.srcPort(new TcpPort( srcPort,"")); 175 | builder_tcp.syn(false); 176 | builder_tcp.urg(false); 177 | //builder_tcp.urgentPointer(tcpHeader.getUrgentPointer()); 178 | builder_tcp.window( window); 179 | 180 | IpV4Packet.Builder builder_ipv4=new IpV4Packet.Builder(); 181 | builder_ipv4.correctChecksumAtBuild(true); 182 | builder_ipv4.correctLengthAtBuild(true); 183 | builder_ipv4.paddingAtBuild(true); 184 | builder_ipv4.dstAddr(dstAddress); 185 | builder_ipv4.dontFragmentFlag(true); 186 | builder_ipv4.fragmentOffset( (short) 0); 187 | //builder_ipv4.headerChecksum(ipV4Header.getHeaderChecksum()); 188 | //short identification= Math.abs(random.nextInt(Short.MAX_VALUE)); 189 | builder_ipv4.identification(ident); 190 | builder_ipv4.ihl((byte) 5); 191 | //builder_ipv4.moreFragmentFlag(ipV4Header.getMoreFragmentFlag()); 192 | //builder_ipv4.options(ipV4Header.getOptions()); 193 | //builder_ipv4.padding(ipV4Header.getPadding()); 194 | 195 | builder_ipv4.protocol(IpNumber.TCP); 196 | // builder_ipv4.reservedFlag(ipV4Header.getReservedFlag()); 197 | builder_ipv4.srcAddr(srcAddress); 198 | builder_ipv4.tos(IpV4Rfc1349Tos.newInstance((byte) 0)); 199 | //builder_ipv4.totalLength( 52); 200 | builder_ipv4.ttl(ttl); 201 | builder_ipv4.version(IpVersion.IPV4); 202 | builder_ipv4.payloadBuilder(builder_tcp); 203 | // 204 | 205 | Packet p = buildIpV4(srcAddress_mac,dstAddrress_mac,builder_ipv4); 206 | //System.out.println("自定义确认 "+" identification "+identification+" ack_sequence "+ack_sequence+" # "+tcpPacket.getHeader()); 207 | return p; 208 | 209 | } 210 | 211 | 212 | static Packet createSyncAck( 213 | MacAddress srcAddress_mac, 214 | MacAddress dstAddrress_mac, 215 | Inet4Address srcAddress,short srcPort, 216 | Inet4Address dstAddress,short dstPort, 217 | int ack_sequence,int sequence,short ident){ 218 | 219 | TcpPacket.Builder builder_tcp=new TcpPacket.Builder(); 220 | //builder_tcp.payloadBuilder(new UnknownPacket.Builder().rawData(new byte[0])); 221 | builder_tcp.correctChecksumAtBuild(true); 222 | builder_tcp.correctLengthAtBuild(true); 223 | builder_tcp.paddingAtBuild(true); 224 | builder_tcp.ack(true); 225 | builder_tcp.acknowledgmentNumber(ack_sequence); 226 | //builder_tcp.checksum(tcpHeader.getChecksum()); 227 | //builder_tcp.dataOffset((byte) 8); 228 | builder_tcp.dstAddr(dstAddress); 229 | builder_tcp.dstPort(new TcpPort(dstPort,"")); 230 | //builder_tcp.fin(tcpHeader.getFin()); 231 | 232 | 233 | ArrayList tcp_options=new ArrayList(); 234 | 235 | TcpNoOperationOption nop=TcpNoOperationOption.getInstance(); 236 | 237 | TcpMaximumSegmentSizeOption seg_option=new TcpMaximumSegmentSizeOption.Builder().maxSegSize(mtu).correctLengthAtBuild(true).build(); 238 | tcp_options.add(seg_option); 239 | 240 | tcp_options.add(nop); 241 | tcp_options.add(nop); 242 | 243 | TcpSackPermittedOption sack_permit_option=TcpSackPermittedOption.getInstance(); 244 | tcp_options.add(sack_permit_option); 245 | 246 | tcp_options.add(nop); 247 | 248 | TcpWindowScaleOption win_option=new TcpWindowScaleOption.Builder().shiftCount(shiftCount).correctLengthAtBuild(true).build(); 249 | tcp_options.add(win_option); 250 | 251 | builder_tcp.options(tcp_options); 252 | 253 | //builder_tcp.padding(tcpHeader.getPadding()); 254 | builder_tcp.psh(false); 255 | builder_tcp.reserved((byte) 0); 256 | builder_tcp.rst(false); 257 | builder_tcp.sequenceNumber(sequence); 258 | builder_tcp.srcAddr(srcAddress); 259 | builder_tcp.srcPort(new TcpPort(srcPort,"")); 260 | builder_tcp.syn(true); 261 | builder_tcp.urg(false); 262 | //builder_tcp.urgentPointer(tcpHeader.getUrgentPointer()); 263 | builder_tcp.window( window); 264 | 265 | IpV4Packet.Builder builder_ipv4=new IpV4Packet.Builder(); 266 | builder_ipv4.correctChecksumAtBuild(true); 267 | builder_ipv4.correctLengthAtBuild(true); 268 | builder_ipv4.paddingAtBuild(true); 269 | builder_ipv4.dstAddr(dstAddress); 270 | builder_ipv4.dontFragmentFlag(true); 271 | builder_ipv4.fragmentOffset((short)0); 272 | //builder_ipv4.headerChecksum(ipV4Header.getHeaderChecksum()); 273 | // short identification= Math.abs(random.nextInt(Short.MAX_VALUE)); 274 | builder_ipv4.identification(ident); 275 | builder_ipv4.ihl((byte) 5); 276 | //builder_ipv4.moreFragmentFlag(ipV4Header.getMoreFragmentFlag()); 277 | //builder_ipv4.options(ipV4Header.getOptions()); 278 | //builder_ipv4.padding(ipV4Header.getPadding()); 279 | 280 | builder_ipv4.protocol(IpNumber.TCP); 281 | // builder_ipv4.reservedFlag(ipV4Header.getReservedFlag()); 282 | builder_ipv4.srcAddr(srcAddress); 283 | builder_ipv4.tos(IpV4Rfc1349Tos.newInstance((byte) 0)); 284 | //builder_ipv4.totalLength( 52); 285 | builder_ipv4.ttl(ttl); 286 | builder_ipv4.version(IpVersion.IPV4); 287 | builder_ipv4.payloadBuilder(builder_tcp); 288 | // 289 | Packet p = buildIpV4(srcAddress_mac,dstAddrress_mac,builder_ipv4); 290 | //System.out.println("自定义确认 "+" identification "+identification+" ack_sequence "+ack_sequence+" # "+tcpPacket.getHeader()); 291 | return p; 292 | 293 | } 294 | 295 | static Packet createSync( 296 | MacAddress srcAddress_mac, 297 | MacAddress dstAddrress_mac, 298 | Inet4Address srcAddress,short srcPort, 299 | Inet4Address dstAddress,short dstPort, 300 | int sequence,short ident){ 301 | TcpPacket.Builder builder_tcp=new TcpPacket.Builder(); 302 | //builder_tcp.payloadBuilder(new UnknownPacket.Builder().rawData(new byte[0])); 303 | builder_tcp.correctChecksumAtBuild(true); 304 | builder_tcp.correctLengthAtBuild(true); 305 | builder_tcp.paddingAtBuild(true); 306 | //builder_tcp.ack(true); 307 | //builder_tcp.acknowledgmentNumber(ack_sequence); 308 | //builder_tcp.checksum(tcpHeader.getChecksum()); 309 | //builder_tcp.dataOffset((byte) 8); 310 | builder_tcp.dstAddr(dstAddress); 311 | builder_tcp.dstPort(new TcpPort( dstPort,"")); 312 | //builder_tcp.fin(tcpHeader.getFin()); 313 | 314 | TcpNoOperationOption nop=TcpNoOperationOption.getInstance(); 315 | 316 | ArrayList tcp_options=new ArrayList(); 317 | 318 | TcpMaximumSegmentSizeOption seg_option=new TcpMaximumSegmentSizeOption.Builder().maxSegSize(mtu).correctLengthAtBuild(true).build(); 319 | tcp_options.add(seg_option); 320 | 321 | tcp_options.add(nop); 322 | 323 | TcpWindowScaleOption win_option=new TcpWindowScaleOption.Builder().shiftCount((byte)6).correctLengthAtBuild(true).build(); 324 | tcp_options.add(win_option); 325 | 326 | tcp_options.add(nop); 327 | tcp_options.add(nop); 328 | 329 | TcpSackPermittedOption sack_permit_option=TcpSackPermittedOption.getInstance(); 330 | tcp_options.add(sack_permit_option); 331 | 332 | builder_tcp.options(tcp_options); 333 | 334 | //builder_tcp.padding(tcpHeader.getPadding()); 335 | builder_tcp.psh(false); 336 | builder_tcp.reserved((byte) 0); 337 | builder_tcp.rst(false); 338 | builder_tcp.sequenceNumber(sequence); 339 | builder_tcp.srcAddr(srcAddress); 340 | builder_tcp.srcPort(new TcpPort( srcPort,"")); 341 | builder_tcp.syn(true); 342 | builder_tcp.urg(false); 343 | //builder_tcp.urgentPointer(tcpHeader.getUrgentPointer()); 344 | builder_tcp.window( window); 345 | 346 | IpV4Packet.Builder builder_ipv4=new IpV4Packet.Builder(); 347 | builder_ipv4.correctChecksumAtBuild(true); 348 | builder_ipv4.correctLengthAtBuild(true); 349 | builder_ipv4.paddingAtBuild(true); 350 | builder_ipv4.dstAddr(dstAddress); 351 | builder_ipv4.dontFragmentFlag(true); 352 | builder_ipv4.fragmentOffset((short)0); 353 | //builder_ipv4.headerChecksum(ipV4Header.getHeaderChecksum()); 354 | //short identification= Math.abs(random.nextInt(Short.MAX_VALUE)); 355 | builder_ipv4.identification(ident); 356 | builder_ipv4.ihl((byte) 5); 357 | //builder_ipv4.moreFragmentFlag(ipV4Header.getMoreFragmentFlag()); 358 | //builder_ipv4.options(ipV4Header.getOptions()); 359 | //builder_ipv4.padding(ipV4Header.getPadding()); 360 | 361 | builder_ipv4.protocol(IpNumber.TCP); 362 | // builder_ipv4.reservedFlag(ipV4Header.getReservedFlag()); 363 | builder_ipv4.srcAddr(srcAddress); 364 | builder_ipv4.tos(IpV4Rfc1349Tos.newInstance((byte) 0)); 365 | //builder_ipv4.totalLength( 52); 366 | builder_ipv4.ttl(ttl); 367 | builder_ipv4.version(IpVersion.IPV4); 368 | builder_ipv4.payloadBuilder(builder_tcp); 369 | // 370 | Packet p = buildIpV4(srcAddress_mac,dstAddrress_mac,builder_ipv4); 371 | // IpV4Packet p4=builder_ipv4.build(); 372 | // TcpPacket tcpPacket=builder_tcp.build(); 373 | //selfAckTable.add(identification); 374 | //System.out.println("自定义确认 "+" identification "+identification+" ack_sequence "+ack_sequence+" # "+tcpPacket.getHeader()); 375 | return p; 376 | 377 | } 378 | 379 | } 380 | -------------------------------------------------------------------------------- /src/net/fs/cap/CapEnv.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 D1SM.net 2 | 3 | package net.fs.cap; 4 | 5 | import java.io.IOException; 6 | import java.net.DatagramPacket; 7 | import java.net.DatagramSocket; 8 | import java.net.Inet4Address; 9 | import java.net.InetAddress; 10 | import java.net.Socket; 11 | import java.net.UnknownHostException; 12 | import java.util.HashMap; 13 | import java.util.Iterator; 14 | import java.util.List; 15 | import java.util.Random; 16 | import java.util.concurrent.LinkedBlockingQueue; 17 | 18 | import net.fs.rudp.Route; 19 | import net.fs.utils.ByteShortConvert; 20 | import net.fs.utils.MLog; 21 | 22 | import org.pcap4j.core.NotOpenException; 23 | import org.pcap4j.core.PacketListener; 24 | import org.pcap4j.core.PcapHandle; 25 | import org.pcap4j.core.PcapNativeException; 26 | import org.pcap4j.core.PcapNetworkInterface; 27 | import org.pcap4j.core.PcapNetworkInterface.PromiscuousMode; 28 | import org.pcap4j.core.PcapStat; 29 | import org.pcap4j.core.Pcaps; 30 | import org.pcap4j.packet.EthernetPacket; 31 | import org.pcap4j.packet.EthernetPacket.EthernetHeader; 32 | import org.pcap4j.packet.IllegalPacket; 33 | import org.pcap4j.packet.IllegalRawDataException; 34 | import org.pcap4j.packet.IpV4Packet; 35 | import org.pcap4j.packet.IpV4Packet.IpV4Header; 36 | import org.pcap4j.packet.Packet; 37 | import org.pcap4j.packet.TcpPacket; 38 | import org.pcap4j.packet.TcpPacket.TcpHeader; 39 | import org.pcap4j.util.MacAddress; 40 | 41 | 42 | public class CapEnv { 43 | 44 | public MacAddress gateway_mac; 45 | 46 | public MacAddress local_mac; 47 | 48 | Inet4Address local_ipv4; 49 | 50 | public PcapHandle sendHandle; 51 | 52 | VDatagramSocket vDatagramSocket; 53 | 54 | String testIp_tcp=""; 55 | 56 | String testIp_udp="5.5.5.5"; 57 | 58 | String selectedInterfaceName=null; 59 | 60 | String selectedInterfaceDes=""; 61 | 62 | PcapNetworkInterface nif; 63 | 64 | private final int COUNT=-1; 65 | 66 | private final int READ_TIMEOUT=1; 67 | 68 | private final int SNAPLEN= 10*1024; 69 | 70 | HashMap tunTable=new HashMap(); 71 | 72 | LinkedBlockingQueue packetList=new LinkedBlockingQueue(); 73 | 74 | Random random=new Random(); 75 | 76 | boolean client=false; 77 | 78 | short listenPort; 79 | 80 | TunManager tcpManager=null; 81 | 82 | CapEnv capEnv; 83 | 84 | Thread versinMonThread; 85 | 86 | boolean detect_by_tcp=true; 87 | 88 | public boolean tcpEnable=false; 89 | 90 | public boolean fwSuccess=true; 91 | 92 | boolean ppp=false; 93 | 94 | { 95 | capEnv=this; 96 | } 97 | 98 | public CapEnv(boolean isClient,boolean fwSuccess){ 99 | this.client=isClient; 100 | this.fwSuccess=fwSuccess; 101 | tcpManager=new TunManager(this); 102 | } 103 | 104 | public void init() throws Exception{ 105 | initInterface(); 106 | Thread thread_process=new Thread(){ 107 | 108 | public void run(){ 109 | while(true){ 110 | try { 111 | Packet packet=packetList.take(); 112 | EthernetPacket packet_eth=(EthernetPacket) packet; 113 | EthernetHeader head_eth=packet_eth.getHeader(); 114 | 115 | IpV4Packet ipV4Packet=null; 116 | if(ppp){ 117 | ipV4Packet=getIpV4Packet_pppoe(packet_eth); 118 | }else { 119 | if(packet_eth.getPayload() instanceof IpV4Packet){ 120 | ipV4Packet=(IpV4Packet) packet_eth.getPayload(); 121 | } 122 | } 123 | if(ipV4Packet!=null){ 124 | IpV4Header ipV4Header=ipV4Packet.getHeader(); 125 | if(ipV4Packet.getPayload() instanceof TcpPacket){ 126 | TcpPacket tcpPacket=(TcpPacket) ipV4Packet.getPayload(); 127 | TcpHeader tcpHeader=tcpPacket.getHeader(); 128 | if(client){ 129 | TCPTun conn=tcpManager.getTcpConnection_Client(ipV4Header.getSrcAddr().getHostAddress(),tcpHeader.getSrcPort().value(), tcpHeader.getDstPort().value()); 130 | if(conn!=null){ 131 | conn.process_client(capEnv,packet,head_eth,ipV4Header,tcpPacket,false); 132 | } 133 | }else { 134 | TCPTun conn=null;conn = tcpManager.getTcpConnection_Server(ipV4Header.getSrcAddr().getHostAddress(),tcpHeader.getSrcPort().value()); 135 | if( 136 | tcpHeader.getDstPort().value()==listenPort){ 137 | if(tcpHeader.getSyn()&&!tcpHeader.getAck()&&conn==null){ 138 | conn=new TCPTun(capEnv,ipV4Header.getSrcAddr(),tcpHeader.getSrcPort().value()); 139 | tcpManager.addConnection_Server(conn); 140 | } 141 | conn = tcpManager.getTcpConnection_Server(ipV4Header.getSrcAddr().getHostAddress(),tcpHeader.getSrcPort().value()); 142 | if(conn!=null){ 143 | conn.process_server(packet,head_eth,ipV4Header,tcpPacket,true); 144 | } 145 | } 146 | } 147 | }else if(packet_eth.getPayload() instanceof IllegalPacket){ 148 | MLog.println("IllegalPacket!!!"); 149 | } 150 | } 151 | } catch (InterruptedException e) { 152 | e.printStackTrace(); 153 | } catch (IllegalRawDataException e) { 154 | e.printStackTrace(); 155 | } 156 | } 157 | } 158 | 159 | }; 160 | thread_process.start(); 161 | 162 | Thread systemSleepScanThread=new Thread(){ 163 | public void run(){ 164 | long t=System.currentTimeMillis(); 165 | while(true){ 166 | if(System.currentTimeMillis()-t>5*1000){ 167 | for(int i=0;i<10;i++){ 168 | MLog.info("休眠恢复... "+(i+1)); 169 | try { 170 | boolean success=initInterface(); 171 | if(success){ 172 | MLog.info("休眠恢复成功 "+(i+1)); 173 | break; 174 | } 175 | } catch (Exception e1) { 176 | e1.printStackTrace(); 177 | } 178 | 179 | try { 180 | Thread.sleep(5*1000); 181 | } catch (InterruptedException e) { 182 | e.printStackTrace(); 183 | } 184 | } 185 | 186 | } 187 | t=System.currentTimeMillis(); 188 | try { 189 | Thread.sleep(1*1000); 190 | } catch (InterruptedException e) { 191 | e.printStackTrace(); 192 | } 193 | } 194 | } 195 | }; 196 | systemSleepScanThread.start(); 197 | } 198 | 199 | PromiscuousMode getMode(PcapNetworkInterface pi){ 200 | PromiscuousMode mode=null; 201 | String string=(pi.getDescription()+":"+pi.getName()).toLowerCase(); 202 | if(string.contains("wireless")){ 203 | mode=PromiscuousMode.NONPROMISCUOUS; 204 | }else { 205 | mode=PromiscuousMode.PROMISCUOUS; 206 | } 207 | return mode; 208 | } 209 | 210 | boolean initInterface() throws Exception{ 211 | boolean success=false; 212 | detectInterface(); 213 | List allDevs = Pcaps.findAllDevs(); 214 | MLog.println("Network Interface List: "); 215 | for(PcapNetworkInterface pi:allDevs){ 216 | String desString=""; 217 | if(pi.getDescription()!=null){ 218 | desString=pi.getDescription(); 219 | } 220 | MLog.info(" "+desString+" "+pi.getName()); 221 | if(pi.getName().equals(selectedInterfaceName) 222 | &&desString.equals(selectedInterfaceDes)){ 223 | nif=pi; 224 | //break; 225 | } 226 | } 227 | if(nif!=null){ 228 | String desString=""; 229 | if(nif.getDescription()!=null){ 230 | desString=nif.getDescription(); 231 | } 232 | success=true; 233 | MLog.info("Selected Network Interface:\n"+" "+desString+" "+nif.getName()); 234 | if(fwSuccess){ 235 | tcpEnable=true; 236 | } 237 | }else { 238 | tcpEnable=false; 239 | MLog.info("Select Network Interface failed,can't use TCP protocal!\n"); 240 | } 241 | if(tcpEnable){ 242 | sendHandle = nif.openLive(SNAPLEN,getMode(nif), READ_TIMEOUT); 243 | final PcapHandle handle= nif.openLive(SNAPLEN, getMode(nif), READ_TIMEOUT); 244 | 245 | final PacketListener listener= new PacketListener() { 246 | @Override 247 | public void gotPacket(Packet packet) { 248 | 249 | try { 250 | if(packet instanceof EthernetPacket){ 251 | packetList.add(packet); 252 | } 253 | } catch (Exception e) { 254 | e.printStackTrace(); 255 | } 256 | 257 | } 258 | }; 259 | 260 | Thread thread=new Thread(){ 261 | 262 | public void run(){ 263 | try { 264 | handle.loop(COUNT, listener); 265 | PcapStat ps = handle.getStats(); 266 | handle.close(); 267 | } catch (Exception e) { 268 | e.printStackTrace(); 269 | } 270 | } 271 | 272 | }; 273 | thread.start(); 274 | } 275 | 276 | if(!client){ 277 | MLog.info("FinalSpeed server start success."); 278 | } 279 | return success; 280 | 281 | } 282 | 283 | void detectInterface() { 284 | List allDevs = null; 285 | HashMap handleTable=new HashMap(); 286 | try { 287 | allDevs = Pcaps.findAllDevs(); 288 | } catch (PcapNativeException e1) { 289 | e1.printStackTrace(); 290 | return; 291 | } 292 | for(final PcapNetworkInterface pi:allDevs){ 293 | try { 294 | final PcapHandle handle = pi.openLive(SNAPLEN, getMode(pi), READ_TIMEOUT); 295 | handleTable.put(pi, handle); 296 | final PacketListener listener= new PacketListener() { 297 | @Override 298 | public void gotPacket(Packet packet) { 299 | 300 | try { 301 | if(packet instanceof EthernetPacket){ 302 | EthernetPacket packet_eth=(EthernetPacket) packet; 303 | EthernetHeader head_eth=packet_eth.getHeader(); 304 | 305 | if(head_eth.getType().value()==0xffff8864){ 306 | ppp=true; 307 | PacketUtils.ppp=ppp; 308 | } 309 | 310 | IpV4Packet ipV4Packet=null; 311 | IpV4Header ipV4Header=null; 312 | 313 | if(ppp){ 314 | ipV4Packet=getIpV4Packet_pppoe(packet_eth); 315 | }else { 316 | if(packet_eth.getPayload() instanceof IpV4Packet){ 317 | ipV4Packet=(IpV4Packet) packet_eth.getPayload(); 318 | } 319 | } 320 | if(ipV4Packet!=null){ 321 | ipV4Header=ipV4Packet.getHeader(); 322 | 323 | if(ipV4Header.getSrcAddr().getHostAddress().equals(testIp_tcp)){ 324 | local_mac=head_eth.getDstAddr(); 325 | gateway_mac=head_eth.getSrcAddr(); 326 | local_ipv4=ipV4Header.getDstAddr(); 327 | selectedInterfaceName=pi.getName(); 328 | if(pi.getDescription()!=null){ 329 | selectedInterfaceDes=pi.getDescription(); 330 | } 331 | //MLog.println("local_mac_tcp1 "+gateway_mac+" gateway_mac "+gateway_mac+" local_ipv4 "+local_ipv4); 332 | } 333 | if(ipV4Header.getDstAddr().getHostAddress().equals(testIp_tcp)){ 334 | local_mac=head_eth.getSrcAddr(); 335 | gateway_mac=head_eth.getDstAddr(); 336 | local_ipv4=ipV4Header.getSrcAddr(); 337 | selectedInterfaceName=pi.getName(); 338 | if(pi.getDescription()!=null){ 339 | selectedInterfaceDes=pi.getDescription(); 340 | } 341 | //MLog.println("local_mac_tcp2 local_mac "+local_mac+" gateway_mac "+gateway_mac+" local_ipv4 "+local_ipv4); 342 | } 343 | //udp 344 | if(ipV4Header.getDstAddr().getHostAddress().equals(testIp_udp)){ 345 | local_mac=head_eth.getSrcAddr(); 346 | gateway_mac=head_eth.getDstAddr(); 347 | local_ipv4=ipV4Header.getSrcAddr(); 348 | selectedInterfaceName=pi.getName(); 349 | if(pi.getDescription()!=null){ 350 | selectedInterfaceDes=pi.getDescription(); 351 | } 352 | //MLog.println("local_mac_udp "+gateway_mac+" gateway_mac"+gateway_mac+" local_ipv4 "+local_ipv4); 353 | } 354 | 355 | } 356 | } 357 | } catch (Exception e) { 358 | e.printStackTrace(); 359 | } 360 | 361 | } 362 | }; 363 | 364 | Thread thread=new Thread(){ 365 | 366 | public void run(){ 367 | try { 368 | handle.loop(COUNT, listener); 369 | PcapStat ps = handle.getStats(); 370 | handle.close(); 371 | } catch (Exception e) { 372 | //e.printStackTrace(); 373 | } 374 | } 375 | 376 | }; 377 | thread.start(); 378 | } catch (PcapNativeException e1) { 379 | 380 | } 381 | 382 | } 383 | 384 | //detectMac_udp(); 385 | try { 386 | detectMac_tcp(); 387 | } catch (UnknownHostException e) { 388 | e.printStackTrace(); 389 | } 390 | 391 | 392 | Iterator it=handleTable.keySet().iterator(); 393 | while(it.hasNext()){ 394 | PcapNetworkInterface pi=it.next(); 395 | PcapHandle handle=handleTable.get(pi); 396 | try { 397 | handle.breakLoop(); 398 | } catch (NotOpenException e) { 399 | e.printStackTrace(); 400 | } 401 | //handle.close();//linux下会阻塞 402 | } 403 | } 404 | 405 | IpV4Packet getIpV4Packet_pppoe(EthernetPacket packet_eth) throws IllegalRawDataException{ 406 | IpV4Packet ipV4Packet=null; 407 | byte[] pppData=packet_eth.getPayload().getRawData(); 408 | if(pppData.length>8&&pppData[8]==0x45){ 409 | byte[] b2=new byte[2]; 410 | System.arraycopy(pppData, 4, b2, 0, 2); 411 | short len=(short) ByteShortConvert.toShort(b2, 0); 412 | int ipLength=toUnsigned(len)-2; 413 | byte[] ipData=new byte[ipLength]; 414 | //设置ppp参数 415 | PacketUtils.pppHead_static[2]=pppData[2]; 416 | PacketUtils.pppHead_static[3]=pppData[3]; 417 | if(ipLength==(pppData.length-8)){ 418 | System.arraycopy(pppData, 8, ipData, 0, ipLength); 419 | ipV4Packet=IpV4Packet.newPacket(ipData, 0, ipData.length); 420 | }else { 421 | MLog.println("长度不符!"); 422 | } 423 | } 424 | return ipV4Packet; 425 | } 426 | 427 | 428 | 429 | public static String printHexString(byte[] b) { 430 | StringBuffer sb=new StringBuffer(); 431 | for (int i = 0; i < b.length; i++) 432 | { 433 | String hex = Integer.toHexString(b[i] & 0xFF); 434 | hex= hex.replaceAll(":", " "); 435 | if (hex.length() == 1) 436 | { 437 | hex = '0' + hex; 438 | } 439 | sb.append(hex + " "); 440 | } 441 | return sb.toString(); 442 | } 443 | 444 | public void createTcpTun_Client(String dstAddress,short dstPort) throws Exception{ 445 | Inet4Address serverAddress=(Inet4Address) Inet4Address.getByName(dstAddress); 446 | TCPTun conn=new TCPTun(this,serverAddress,dstPort,local_mac,gateway_mac); 447 | tcpManager.addConnection_Client(conn); 448 | boolean success=false; 449 | for(int i=0;i<6;i++){ 450 | try { 451 | Thread.sleep(500); 452 | } catch (InterruptedException e) { 453 | e.printStackTrace(); 454 | } 455 | if(conn.preDataReady){ 456 | success=true; 457 | break; 458 | } 459 | } 460 | if(success){ 461 | tcpManager.setDefaultTcpTun(conn); 462 | }else { 463 | tcpManager.removeTun(conn); 464 | tcpManager.setDefaultTcpTun(null); 465 | throw new Exception("创建隧道失败!"); 466 | } 467 | } 468 | 469 | private void detectMac_tcp() throws UnknownHostException{ 470 | InetAddress address=InetAddress.getByName("www.bing.com"); 471 | final int por=80; 472 | testIp_tcp=address.getHostAddress(); 473 | for(int i=0;i<5;i++){ 474 | try { 475 | Route.es.execute(new Runnable() { 476 | 477 | @Override 478 | public void run() { 479 | try { 480 | Socket socket=new Socket(testIp_tcp,por); 481 | socket.close(); 482 | } catch (UnknownHostException e) { 483 | e.printStackTrace(); 484 | } catch (IOException e) { 485 | e.printStackTrace(); 486 | } 487 | } 488 | }); 489 | Thread.sleep(500); 490 | if(local_mac!=null){ 491 | break; 492 | } 493 | } catch (Exception e) { 494 | e.printStackTrace(); 495 | try { 496 | Thread.sleep(1); 497 | } catch (InterruptedException e1) { 498 | e1.printStackTrace(); 499 | } 500 | } 501 | } 502 | } 503 | 504 | private void detectMac_udp(){ 505 | for(int i=0;i<10;i++){ 506 | try { 507 | DatagramSocket ds=new DatagramSocket(); 508 | DatagramPacket dp=new DatagramPacket(new byte[1000], 1000); 509 | dp.setAddress(InetAddress.getByName(testIp_udp)); 510 | dp.setPort(5555); 511 | ds.send(dp); 512 | ds.close(); 513 | Thread.sleep(500); 514 | if(local_mac!=null){ 515 | break; 516 | } 517 | } catch (Exception e) { 518 | e.printStackTrace(); 519 | try { 520 | Thread.sleep(1); 521 | } catch (InterruptedException e1) { 522 | e1.printStackTrace(); 523 | } 524 | } 525 | } 526 | 527 | } 528 | 529 | public short getListenPort() { 530 | return listenPort; 531 | } 532 | 533 | public void setListenPort(short listenPort) { 534 | this.listenPort = listenPort; 535 | if(!client){ 536 | MLog.info("Listen tcp port: "+toUnsigned(listenPort)); 537 | } 538 | } 539 | 540 | public static int toUnsigned(short s) { 541 | return s & 0x0FFFF; 542 | } 543 | 544 | } 545 | --------------------------------------------------------------------------------