├── 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