├── .classpath
├── .gitignore
├── .project
├── LICENSE
├── README.md
├── ipseccmd.exe
├── lib
├── fastjson-1.1.6.jar
├── fsclient.jar
├── jna.jar
├── miglayout-swing.jar
├── pcap4j-core.jar
├── pcap4j-packetfactory-static.jar
├── slf4j-api-1.6.6.jar
└── slf4j-nop-1.6.1.jar
└── src
└── net
└── fs
├── cap
├── CapEnv.java
├── CapServer.java
├── CustomTcpSackOption.java
├── IPacket.java
├── PacketUtils.java
├── SendRecord.java
├── TCPTun.java
├── TunData.java
├── TunManager.java
└── VDatagramSocket.java
├── client
├── AddMapFrame.java
├── AlignCellRenderer.java
├── ClientConfig.java
├── ClientNoUI.java
├── ClientStartNoUI.java
├── ClientUI.java
├── ClientUII.java
├── FSClient.java
├── MapClient.java
├── MapRule.java
├── MapRuleListModel.java
├── MapRuleListTable.java
├── MapRuleRender.java
├── Pipe.java
├── PortMapManager.java
├── PortMapProcess.java
├── SpeedSetFrame.java
└── TextComponentPopupMenu.java
├── rudp
├── AckListManage.java
├── AckListTask.java
├── ClientControl.java
├── ClientManager.java
├── ClientProcessorInterface.java
├── ConnInfo.java
├── ConnectException.java
├── ConnectionProcessor.java
├── ConnectionUDP.java
├── Constant.java
├── CopiedIterator.java
├── MapSocketPorcessor.java
├── MessageInterface.java
├── PipeListener.java
├── RUDPConfig.java
├── ReceivePingException.java
├── Receiver.java
├── ResendItem.java
├── ResendManage.java
├── Route.java
├── SendRecord.java
├── Sender.java
├── StreamPipe.java
├── TrafficEvent.java
├── Trafficlistener.java
├── UDPInputStream.java
├── UDPOutputStream.java
└── message
│ ├── AckListMessage.java
│ ├── CloseMessage_Conn.java
│ ├── CloseMessage_Stream.java
│ ├── DataMessage.java
│ ├── Message.java
│ ├── MessageType.java
│ ├── PingMessage.java
│ └── PingMessage2.java
├── server
├── FSServer.java
└── MapTunnelProcessor.java
└── utils
├── ByteIntConvert.java
├── ByteShortConvert.java
├── MLog.java
├── MessageCheck.java
├── NetStatus.java
└── Tools.java
/.classpath:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | /bin/
2 | /client_config.json
3 | /port_map.json
4 | *.iml
5 | .idea/
--------------------------------------------------------------------------------
/.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 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # finalspeed
2 | FinalSpeed是高速双边加速软件,可加速所有基于tcp协议的网络服务,在高丢包和高延迟环境下,仍可达到90%的物理带宽利用率,即使高峰时段也能轻松跑满带宽.
3 |
4 | ### 安装教程
5 | [客户端安装说明](http://www.d1sm.net/thread-7-1-1.html)
6 |
7 | [服务端安装说明](http://www.d1sm.net/thread-8-1-1.html)
8 |
9 |
10 | ### 命令行版本的客户端
11 | 默认是图形化版本的客户端,不方便部署在服务器。如果需要命令行版本的,请在 [Releases](https://github.com/zqhong/finalspeed/releases) 中下载。
12 |
13 |
14 | 要求
15 | * 管理员运行权限
16 | * jre >= 1.6(如果下载上面提供的客户端的话)
17 |
18 | 使用方法:`sudo java -jar client.jar`。如果在 Windows 下,则需要使用管理员运行。
19 |
20 | 配置文件 - clien_config.json
21 | ```
22 | {
23 | // 下载速度,单位是 B,字节。这里换算起来就是 11MB。请把这里改成本机的下载速度
24 | "download_speed": 11200698,
25 | // 协议:tcp 或 udp。注意:服务端如果是 OpenVZ 架构的话,则只支持 udp。
26 | "protocal": "udp",
27 | // 服务器地址
28 | "server_address": "1.2.3.4",
29 | // 一般不需要更改,保持默认即可。
30 | "server_port": 150,
31 | // 不需要更改,保持默认即可。
32 | "socks5_port": 1083,
33 | // 上传速度,单位是 B,字节。
34 | "upload_speed": 357469
35 | }
36 | ```
37 |
38 | 配置文件 - port_map.json
39 | ```
40 | {
41 | "map_list": [
42 | {
43 | // 要加速的服务器端口
44 | "dst_port": 12345,
45 | // 本地端口
46 | "listen_port": 1099,
47 | // 备注信息
48 | "name": "ss"
49 | },
50 | {
51 | "dst_port": 23456,
52 | "listen_port": 2200,
53 | "name": "ssh"
54 | }
55 | ]
56 | }
57 | ```
58 |
59 | > 注意:这两个配置文件不能删除,不然会弹出配置文件的窗口。(没有完全去掉图形化界面的缘故)
60 |
61 |
62 | ### 其他信息
63 | 项目运行需要安装libpcap,windows下为winpcap.
64 |
65 | 客户端启动类: net.fs.client.FSClient
66 |
67 | 服务端启动类: net.fs.server.FSServer
68 |
69 | 论坛 http://www.d1sm.net/forum-44-1.html
70 |
71 | #### 感谢
72 | 该项目 fork 自 [dlsm/finalspeed](https://github.com/d1sm/finalspeed),感谢作者的辛勤付出。
73 |
--------------------------------------------------------------------------------
/ipseccmd.exe:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zqhong/finalspeed/6bd98942e992f6bbebdc8cf3631298ba25c53b3b/ipseccmd.exe
--------------------------------------------------------------------------------
/lib/fastjson-1.1.6.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zqhong/finalspeed/6bd98942e992f6bbebdc8cf3631298ba25c53b3b/lib/fastjson-1.1.6.jar
--------------------------------------------------------------------------------
/lib/fsclient.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zqhong/finalspeed/6bd98942e992f6bbebdc8cf3631298ba25c53b3b/lib/fsclient.jar
--------------------------------------------------------------------------------
/lib/jna.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zqhong/finalspeed/6bd98942e992f6bbebdc8cf3631298ba25c53b3b/lib/jna.jar
--------------------------------------------------------------------------------
/lib/miglayout-swing.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zqhong/finalspeed/6bd98942e992f6bbebdc8cf3631298ba25c53b3b/lib/miglayout-swing.jar
--------------------------------------------------------------------------------
/lib/pcap4j-core.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zqhong/finalspeed/6bd98942e992f6bbebdc8cf3631298ba25c53b3b/lib/pcap4j-core.jar
--------------------------------------------------------------------------------
/lib/pcap4j-packetfactory-static.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zqhong/finalspeed/6bd98942e992f6bbebdc8cf3631298ba25c53b3b/lib/pcap4j-packetfactory-static.jar
--------------------------------------------------------------------------------
/lib/slf4j-api-1.6.6.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zqhong/finalspeed/6bd98942e992f6bbebdc8cf3631298ba25c53b3b/lib/slf4j-api-1.6.6.jar
--------------------------------------------------------------------------------
/lib/slf4j-nop-1.6.1.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zqhong/finalspeed/6bd98942e992f6bbebdc8cf3631298ba25c53b3b/lib/slf4j-nop-1.6.1.jar
--------------------------------------------------------------------------------
/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);
12 | capEnv.init();
13 | } catch (Exception e) {
14 | e.printStackTrace();
15 | }
16 | }
17 |
18 | }
19 |
--------------------------------------------------------------------------------
/src/net/fs/cap/CustomTcpSackOption.java:
--------------------------------------------------------------------------------
1 | /*_##########################################################################
2 | _##
3 | _## Copyright (C) 2014 Pcap4J.org
4 | _##
5 | _##########################################################################
6 | */
7 |
8 | package net.fs.cap;
9 |
10 | import static org.pcap4j.util.ByteArrays.*;
11 |
12 | import java.io.Serializable;
13 | import java.util.ArrayList;
14 | import java.util.List;
15 |
16 | import org.pcap4j.packet.IllegalRawDataException;
17 | import org.pcap4j.packet.LengthBuilder;
18 | import org.pcap4j.packet.TcpPacket.TcpOption;
19 | import org.pcap4j.packet.namednumber.TcpOptionKind;
20 | import org.pcap4j.util.ByteArrays;
21 |
22 | /**
23 | * @author Kaito Yamada
24 | * @since pcap4j 1.2.0
25 | */
26 | public final class CustomTcpSackOption implements TcpOption {
27 |
28 | /*
29 | * http://tools.ietf.org/html/rfc2018
30 | *
31 | * +--------+--------+
32 | * | Kind=5 | Length |
33 | * +--------+--------+--------+--------+
34 | * | Left Edge of 1st Block |
35 | * +--------+--------+--------+--------+
36 | * | Right Edge of 1st Block |
37 | * +--------+--------+--------+--------+
38 | * | |
39 | * / . . . /
40 | * | |
41 | * +--------+--------+--------+--------+
42 | * | Left Edge of nth Block |
43 | * +--------+--------+--------+--------+
44 | * | Right Edge of nth Block |
45 | * +--------+--------+--------+--------+
46 | */
47 |
48 | /**
49 | *
50 | */
51 | private static final long serialVersionUID = -3308738405807657257L;
52 |
53 | private final TcpOptionKind kind = TcpOptionKind.SACK;
54 | private final byte length;
55 | private final List sacks = new ArrayList();
56 |
57 | /**
58 | * A static factory method.
59 | * This method validates the arguments by {@link ByteArrays#validateBounds(byte[], int, int)},
60 | * which may throw exceptions undocumented here.
61 | *
62 | * @param rawData rawData
63 | * @param offset offset
64 | * @param length length
65 | * @return a new TcpSackOption object.
66 | * @throws IllegalRawDataException if parsing the raw data fails.
67 | */
68 | public static CustomTcpSackOption newInstance(
69 | byte[] rawData, int offset, int length
70 | ) throws IllegalRawDataException {
71 | ByteArrays.validateBounds(rawData, offset, length);
72 | return new CustomTcpSackOption(rawData, offset, length);
73 | }
74 |
75 | private CustomTcpSackOption(byte[] rawData, int offset, int length) throws IllegalRawDataException {
76 | if (length < 2) {
77 | StringBuilder sb = new StringBuilder(50);
78 | sb.append("The raw data length must be more than 1. rawData: ")
79 | .append(ByteArrays.toHexString(rawData, " "))
80 | .append(", offset: ")
81 | .append(offset)
82 | .append(", length: ")
83 | .append(length);
84 | throw new IllegalRawDataException(sb.toString());
85 | }
86 | if (rawData[offset] != kind.value()) {
87 | StringBuilder sb = new StringBuilder(100);
88 | sb.append("The kind must be: ")
89 | .append(kind.valueAsString())
90 | .append(" rawData: ")
91 | .append(ByteArrays.toHexString(rawData, " "))
92 | .append(", offset: ")
93 | .append(offset)
94 | .append(", length: ")
95 | .append(length);
96 | throw new IllegalRawDataException(sb.toString());
97 | }
98 |
99 | this.length = rawData[1 + offset];
100 | int lengthFieldAsInt = getLengthAsInt();
101 | if (lengthFieldAsInt < 2) {
102 | throw new IllegalRawDataException(
103 | "The value of length field must be more than 1 but: " + lengthFieldAsInt
104 | );
105 | }
106 |
107 | if ((lengthFieldAsInt - 2) % (INT_SIZE_IN_BYTES * 2) != 0) {
108 | StringBuilder sb = new StringBuilder(100);
109 | sb.append(
110 | "The value of length field must be an integer multiple of 8 octets long but: "
111 | )
112 | .append(lengthFieldAsInt);
113 | throw new IllegalRawDataException(sb.toString());
114 | }
115 | if (length < lengthFieldAsInt) {
116 | StringBuilder sb = new StringBuilder(100);
117 | sb.append("rawData is too short. length field: ")
118 | .append(lengthFieldAsInt)
119 | .append(", rawData: ")
120 | .append(ByteArrays.toHexString(rawData, " "))
121 | .append(", offset: ")
122 | .append(offset)
123 | .append(", length: ")
124 | .append(length);
125 | throw new IllegalRawDataException(sb.toString());
126 | }
127 |
128 | for (int i = 2; i < lengthFieldAsInt; i += INT_SIZE_IN_BYTES * 2) {
129 | sacks.add(
130 | new Sack(
131 | ByteArrays.getInt(rawData, i + offset),
132 | ByteArrays.getInt(rawData, i + INT_SIZE_IN_BYTES + offset)
133 | )
134 | );
135 | }
136 | }
137 |
138 | private CustomTcpSackOption(Builder builder) {
139 | if (
140 | builder == null
141 | || builder.sacks == null
142 | ) {
143 | StringBuilder sb = new StringBuilder();
144 | sb.append("builder: ").append(builder)
145 | .append(" builder.sacks: ").append(builder.sacks);
146 | throw new NullPointerException(sb.toString());
147 | }
148 |
149 | this.sacks.addAll(builder.sacks);
150 |
151 | if (builder.correctLengthAtBuild) {
152 | this.length = (byte)length();
153 | }
154 | else {
155 | this.length = builder.length;
156 | }
157 | }
158 |
159 | @Override
160 | public TcpOptionKind getKind() {
161 | return kind;
162 | }
163 |
164 | /**
165 | *
166 | * @return length
167 | */
168 | public byte getLength() { return length; }
169 |
170 | /**
171 | *
172 | * @return length
173 | */
174 | public int getLengthAsInt() { return 0xFF & length; }
175 |
176 | @Override
177 | public int length() {
178 | return sacks.size() * INT_SIZE_IN_BYTES * 2 + 2;
179 | }
180 |
181 | @Override
182 | public byte[] getRawData() {
183 | byte[] rawData = new byte[length()];
184 | rawData[0] = kind.value();
185 | rawData[1] = length;
186 |
187 | int offset = 2;
188 | for (Sack sack: sacks) {
189 | System.arraycopy(
190 | ByteArrays.toByteArray(sack.leftEdge), 0,
191 | rawData, offset, INT_SIZE_IN_BYTES
192 | );
193 | System.arraycopy(
194 | ByteArrays.toByteArray(sack.rightEdge), 0,
195 | rawData, offset + INT_SIZE_IN_BYTES, INT_SIZE_IN_BYTES
196 | );
197 | offset += INT_SIZE_IN_BYTES * 2;
198 | }
199 |
200 | return rawData;
201 | }
202 |
203 | /**
204 | *
205 | * @return a new Builder object populated with this object's fields.
206 | */
207 | public Builder getBuilder() {
208 | return new Builder(this);
209 | }
210 |
211 | @Override
212 | public String toString() {
213 | StringBuilder sb = new StringBuilder();
214 | sb.append("[Kind: ")
215 | .append(kind);
216 | sb.append("] [Length: ")
217 | .append(getLengthAsInt())
218 | .append(" bytes]");
219 | for (Sack sack: sacks) {
220 | sb.append(" [LE: ")
221 | .append(sack.getLeftEdgeAsLong())
222 | .append(" RE: ")
223 | .append(sack.getRightEdgeAsLong())
224 | .append("]");
225 | }
226 | return sb.toString();
227 | }
228 |
229 | @Override
230 | public boolean equals(Object obj) {
231 | if (obj == this) { return true; }
232 | if (!this.getClass().isInstance(obj)) { return false; }
233 |
234 | CustomTcpSackOption other = (CustomTcpSackOption)obj;
235 | return
236 | length == other.length
237 | && sacks.equals(other.sacks);
238 | }
239 |
240 | public List getSacks() {
241 | return sacks;
242 | }
243 |
244 | @Override
245 | public int hashCode() {
246 | int result = 17;
247 | result = 31 * result + length;
248 | result = 31 * result + sacks.hashCode();
249 | return result;
250 | }
251 |
252 | /**
253 | * @author Kaito Yamada
254 | * @since pcap4j 1.2.0
255 | */
256 | public static final class Builder
257 | implements LengthBuilder {
258 |
259 | private byte length;
260 | private boolean correctLengthAtBuild;
261 | private List sacks;
262 |
263 | /**
264 | *
265 | */
266 | public Builder() {}
267 |
268 | private Builder(CustomTcpSackOption option) {
269 | this.length = option.length;
270 | }
271 |
272 | /**
273 | * @param length length
274 | * @return this Builder object for method chaining.
275 | */
276 | public Builder length(byte length) {
277 | this.length = length;
278 | return this;
279 | }
280 |
281 | /**
282 | * @param sacks sacks
283 | * @return this Builder object for method chaining.
284 | */
285 | public Builder sacks(List sacks) {
286 | this.sacks = sacks;
287 | return this;
288 | }
289 |
290 | @Override
291 | public Builder correctLengthAtBuild(boolean correctLengthAtBuild) {
292 | this.correctLengthAtBuild = correctLengthAtBuild;
293 | return this;
294 | }
295 |
296 | @Override
297 | public CustomTcpSackOption build() {
298 | return new CustomTcpSackOption(this);
299 | }
300 |
301 | }
302 |
303 | /**
304 | * @author Kaito Yamada
305 | * @since pcap4j 1.2.0
306 | */
307 | public static final class Sack implements Serializable {
308 |
309 | /**
310 | *
311 | */
312 | private static final long serialVersionUID = 1218420566089129438L;
313 |
314 | private final int leftEdge;
315 | private final int rightEdge;
316 |
317 | /**
318 | * @param leftEdge leftEdge
319 | * @param rightEdge rightEdge
320 | */
321 | public Sack(int leftEdge, int rightEdge) {
322 | this.leftEdge = leftEdge;
323 | this.rightEdge = rightEdge;
324 | }
325 |
326 | /**
327 | * @return leftEdge
328 | */
329 | public int getLeftEdge() {
330 | return leftEdge;
331 | }
332 |
333 | /**
334 | * @return leftEdge
335 | */
336 | public long getLeftEdgeAsLong() {
337 | return 0xFFFFFFFFL & leftEdge;
338 | }
339 |
340 | /**
341 | * @return rightEdge
342 | */
343 | public int getRightEdge() {
344 | return rightEdge;
345 | }
346 |
347 | /**
348 | * @return rightEdge
349 | */
350 | public long getRightEdgeAsLong() {
351 | return 0xFFFFFFFFL & rightEdge;
352 | }
353 |
354 | @Override
355 | public boolean equals(Object obj) {
356 | if (obj == this) { return true; }
357 | if (!this.getClass().isInstance(obj)) { return false; }
358 |
359 | Sack other = (Sack)obj;
360 | return
361 | leftEdge == other.leftEdge
362 | && rightEdge == other.rightEdge;
363 | }
364 |
365 | @Override
366 | public int hashCode() {
367 | int result = 17;
368 | result = 31 * result + leftEdge;
369 | result = 31 * result + rightEdge;
370 | return result;
371 | }
372 |
373 | }
374 |
375 | }
376 |
--------------------------------------------------------------------------------
/src/net/fs/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/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/cap/TCPTun.java:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2015 D1SM.net
2 |
3 | package net.fs.cap;
4 |
5 | import java.net.Inet4Address;
6 | import java.net.InetAddress;
7 | import java.util.ArrayList;
8 | import java.util.HashMap;
9 | import java.util.HashSet;
10 | import java.util.Random;
11 |
12 | import net.fs.utils.MLog;
13 |
14 | import org.pcap4j.core.NotOpenException;
15 | import org.pcap4j.core.PcapHandle;
16 | import org.pcap4j.core.PcapNativeException;
17 | import org.pcap4j.packet.EthernetPacket.EthernetHeader;
18 | import org.pcap4j.packet.IpV4Packet.IpV4Header;
19 | import org.pcap4j.packet.Packet;
20 | import org.pcap4j.packet.TcpPacket;
21 | import org.pcap4j.packet.TcpPacket.TcpHeader;
22 | import org.pcap4j.util.MacAddress;
23 |
24 |
25 | public class TCPTun {
26 |
27 | HashMap sendedTable_server=new HashMap ();
28 | HashMap sendedTable_history_server=new HashMap ();
29 |
30 | int clientSequence=Integer.MIN_VALUE;
31 |
32 | static Random random=new Random();
33 |
34 | PcapHandle sendHandle;
35 |
36 | HashSet selfAckTable=new HashSet();
37 |
38 | HashMap sendrecordTable=new HashMap();
39 |
40 | MacAddress dstMacaAddress;
41 |
42 | int sequenceNum=-1;
43 |
44 | Thread sendThread;
45 |
46 | boolean sended=false;
47 |
48 | Packet basePacket_server;
49 |
50 | short baseIdent=100;
51 |
52 | IPacket dst_readed_packet,last_send_packet;
53 |
54 | int presend_server;
55 |
56 | ArrayList packetList=new ArrayList();
57 |
58 | HashMap packetTable_l=new HashMap();
59 |
60 | HashMap packetTable=new HashMap();
61 |
62 | ArrayList unacked_list=new ArrayList();
63 |
64 | Object syn_packetList=new Object();
65 |
66 | int max_client_ack=Integer.MIN_VALUE;
67 |
68 | int sendIndex=0;
69 |
70 | long lasSetDelayTime=0;
71 |
72 | long lastDelay=300;
73 |
74 | Object syn_delay=new Object();
75 |
76 | Thread resendScanThread;
77 |
78 | boolean connectReady=false;
79 |
80 | boolean preDataReady=false;
81 |
82 | CapEnv capEnv;
83 |
84 | public Inet4Address remoteAddress;
85 | public short remotePort;
86 | int remoteStartSequence;
87 | int remoteSequence;
88 | int remoteIdent;
89 | int remoteSequence_max;
90 |
91 | Inet4Address localAddress;
92 | short localPort;
93 | int localStartSequence=random.nextInt();
94 | int localSequence;
95 | int localIdent=random.nextInt(Short.MAX_VALUE-100);
96 |
97 | Object syn_send_data=new Object();
98 |
99 | long lastSendAckTime;
100 |
101 | long lastReceiveDataTime;
102 |
103 | long createTime=System.currentTimeMillis();;
104 |
105 | String key;
106 |
107 | Object syn_ident=new Object();
108 |
109 | //客户端发起
110 | TCPTun(CapEnv capEnv,
111 | Inet4Address serverAddress,short serverPort,
112 | MacAddress srcAddress_mac,MacAddress dstAddrress_mac){
113 | this.capEnv=capEnv;
114 | sendHandle=capEnv.sendHandle;
115 | this.remoteAddress=serverAddress;
116 | this.remotePort=serverPort;
117 | localAddress=capEnv.local_ipv4;
118 | localPort=(short)(random.nextInt(64*1024-1-10000)+10000);
119 | Packet syncPacket=null;
120 | try {
121 | syncPacket = PacketUtils.createSync(srcAddress_mac, dstAddrress_mac, localAddress, localPort,serverAddress, serverPort, localStartSequence,getIdent());
122 | try {
123 | sendHandle.sendPacket(syncPacket);
124 | localSequence=localStartSequence+1;
125 | } catch (Exception e) {
126 | e.printStackTrace();
127 | }
128 | } catch (Exception e1) {
129 | e1.printStackTrace();
130 | }
131 | //MLog.println("发送第一次握手 "+" ident "+localIdent);
132 | MLog.println(""+syncPacket);
133 |
134 | }
135 |
136 | //服务端接收
137 | TCPTun(CapEnv capServerEnv,
138 | Inet4Address remoteAddress,short remotePort){
139 | this.capEnv=capServerEnv;
140 | this.remoteAddress=remoteAddress;
141 | this.remotePort=remotePort;
142 | sendHandle=capEnv.sendHandle;
143 | localPort=capServerEnv.listenPort;
144 | localAddress=capEnv.local_ipv4;
145 | }
146 |
147 | void init_client(Inet4Address clientAddress,int clientPort,
148 | Inet4Address serverAddress,int serverPort,
149 | int client_start_sequence){
150 |
151 | }
152 |
153 | void init_server(Inet4Address clientAddress,int clientPort,
154 | Inet4Address serverAddress,int serverPort,
155 | int client_start_sequence,int server_start_sequence){
156 |
157 | }
158 |
159 | public void process_server(final Packet packet,EthernetHeader ethernetHeader,IpV4Header ipV4Header,TcpPacket tcpPacket,boolean client){
160 | TcpHeader tcpHeader=tcpPacket.getHeader();
161 |
162 | if(!preDataReady){
163 | if(!connectReady){
164 | //第一次握手
165 | dstMacaAddress=ethernetHeader.getSrcAddr();
166 | if(tcpHeader.getSyn()&&!tcpHeader.getAck()){
167 | remoteStartSequence=tcpHeader.getSequenceNumber();
168 | remoteSequence=remoteStartSequence+1;
169 | remoteSequence_max=remoteSequence;
170 | //MLog.println("接收第一次握手 "+remoteAddress.getHostAddress()+":"+remotePort+"->"+localAddress.getHostAddress()+":"+localPort+" ident "+ipV4Header.getIdentification());
171 | MLog.println(""+packet);
172 | Packet responePacket=PacketUtils.createSyncAck(
173 | capEnv.local_mac,
174 | capEnv.gateway_mac,
175 | localAddress,(short)localPort,
176 | ipV4Header.getSrcAddr(),tcpHeader.getSrcPort().value(),
177 | tcpHeader.getSequenceNumber()+1,localStartSequence,(short)0
178 | );
179 | try {
180 | sendHandle.sendPacket(responePacket);
181 | } catch (Exception e) {
182 | e.printStackTrace();
183 | }
184 | localSequence=localStartSequence+1;
185 | //MLog.println("发送第二次握手 "+capEnv.local_mac+"->"+capEnv.gateway_mac+" "+localAddress+"->"+" ident "+0);
186 |
187 | MLog.println(""+responePacket);
188 | }
189 |
190 | if(!tcpHeader.getSyn()&&tcpHeader.getAck()){
191 | if(tcpPacket.getPayload()==null){
192 | //第三次握手,客户端确认
193 | if(tcpHeader.getAcknowledgmentNumber()==localSequence){
194 | //MLog.println("接收第三次握手 "+" ident "+ipV4Header.getIdentification());
195 | MLog.println(packet+"");
196 | Thread t1=new Thread(){
197 | public void run(){
198 | //startSend(basePacket_server,syc_sequence_client+1);
199 | }
200 | };
201 | //t1.start();
202 | connectReady=true;
203 | }
204 | }
205 | //MLog.println("客户端响应preview\n "+packet);
206 | //MLog.println("request "+tcp.ack());
207 | sendedTable_server.remove(tcpHeader.getAcknowledgmentNumber());
208 | boolean selfAck=selfAckTable.contains(ipV4Header.getIdentification());
209 | //MLog.println("客户端确认 "+"selfack "+selfAck+" id "+ipV4Header.getIdentification()+" ack_sequence "+tcpHeader.getAcknowledgmentNumberAsLong()+" "+sendedTable_server.size()+"ppppppp "+tcpHeader);
210 | }
211 |
212 | }else {
213 | if(tcpPacket.getPayload()!=null){
214 | preDataReady=true;
215 | onReceiveDataPacket( tcpPacket, tcpHeader, ipV4Header );
216 | byte[] sim=getSimResponeHead();
217 | sendData(sim);
218 | }
219 | }
220 | }else {
221 | if(tcpPacket.getPayload()!=null){
222 | onReceiveDataPacket( tcpPacket, tcpHeader, ipV4Header );
223 | TunData td=new TunData();
224 | td.tun=this;
225 | td.data=tcpPacket.getPayload().getRawData();
226 | capEnv.vDatagramSocket.onReceinveFromTun(td);
227 | }
228 | }
229 | if(tcpHeader.getRst()){
230 | MLog.println("reset packet "+ipV4Header.getIdentification()+" "+tcpHeader.getSequenceNumber()+" "+remoteAddress.getHostAddress()+":"+remotePort+"->"+localAddress.getHostAddress()+":"+localPort+" "+" ident "+ipV4Header.getIdentification());
231 | }
232 |
233 | }
234 |
235 | public void process_client(CapEnv capEnv,final Packet packet,EthernetHeader ethernetHeader,IpV4Header ipV4Header,TcpPacket tcpPacket,boolean client){
236 |
237 | TcpHeader tcpHeader=tcpPacket.getHeader();
238 | byte[] payload=null;
239 | if(tcpPacket.getPayload()!=null){
240 | payload=tcpPacket.getPayload().getRawData();
241 | }
242 |
243 | if(!preDataReady){
244 | if(!connectReady){
245 | if(tcpHeader.getAck()&&tcpHeader.getSyn()){
246 | if(tcpHeader.getAcknowledgmentNumber()==(localStartSequence+1)){
247 | MLog.println("接收第二次握手 "+" ident "+ipV4Header.getIdentification());
248 | MLog.println(""+packet);
249 | remoteStartSequence=tcpHeader.getSequenceNumber();
250 | remoteSequence=remoteStartSequence+1;
251 | remoteSequence_max=remoteSequence;
252 | Packet p3=PacketUtils.createAck(capEnv.local_mac, capEnv.gateway_mac, capEnv.local_ipv4, localPort, remoteAddress, remotePort, remoteSequence , localSequence,getIdent());
253 | try {
254 | sendHandle.sendPacket(p3);
255 | MLog.println("发送第三次握手 "+" ident "+localIdent);
256 | MLog.println(""+p3);
257 | connectReady=true;
258 |
259 | byte[] sim=getSimRequestHead(remotePort);
260 | sendData(sim);
261 | MLog.println("发送请求 "+" ident "+localIdent);
262 | } catch (PcapNativeException e) {
263 | e.printStackTrace();
264 | } catch (NotOpenException e) {
265 | e.printStackTrace();
266 | }
267 | }
268 | }
269 | }else {
270 | if(tcpPacket.getPayload()!=null){
271 | preDataReady=true;
272 | onReceiveDataPacket( tcpPacket, tcpHeader, ipV4Header );
273 | MLog.println("接收响应 "+" ident "+ipV4Header.getIdentification());
274 | }
275 | }
276 |
277 | }else {
278 | if(tcpPacket.getPayload()!=null){
279 | //MLog.println("客户端正式接收数据 "+capClientEnv.vDatagramSocket);
280 | onReceiveDataPacket( tcpPacket, tcpHeader, ipV4Header );
281 | TunData td=new TunData();
282 | td.tun=this;
283 | td.data=tcpPacket.getPayload().getRawData();
284 | capEnv.vDatagramSocket.
285 | onReceinveFromTun(td);
286 | }
287 | }
288 | if(tcpHeader.getRst()){
289 | MLog.println("reset packet "+ipV4Header.getIdentification()+" "+tcpHeader.getSequenceNumber()+" "+remoteAddress.getHostAddress()+":"+remotePort+"->"+localAddress.getHostAddress()+":"+localPort);
290 | }
291 |
292 | }
293 |
294 | void onReceiveDataPacket(TcpPacket tcpPacket,TcpHeader tcpHeader,IpV4Header ipV4Header ){
295 | if(System.currentTimeMillis()-lastSendAckTime>1000){
296 | int rs=tcpHeader.getSequenceNumber()+tcpPacket.getPayload().getRawData().length;
297 | if(rs>remoteSequence_max){
298 | remoteSequence_max=rs;
299 | }
300 | Packet ackPacket=PacketUtils.createAck(
301 | capEnv.local_mac,
302 | capEnv.gateway_mac,
303 | localAddress,(short)localPort,
304 | ipV4Header.getSrcAddr(),tcpHeader.getSrcPort().value(),
305 | remoteSequence_max, localSequence,getIdent());
306 | try {
307 | sendHandle.sendPacket(ackPacket);
308 | } catch (Exception e) {
309 | e.printStackTrace();
310 |
311 | }
312 | lastSendAckTime=System.currentTimeMillis();
313 | lastReceiveDataTime=System.currentTimeMillis();
314 | }
315 | }
316 |
317 | void sendData(byte[] data){
318 | Packet dataPacket=PacketUtils.createDataPacket(capEnv.local_mac,
319 | capEnv.gateway_mac,
320 | localAddress,localPort,
321 | remoteAddress,remotePort,
322 | localSequence,remoteSequence_max, data, (short) getIdent());
323 | synchronized (syn_send_data) {
324 | try {
325 | sendHandle.sendPacket(dataPacket);
326 | localSequence+=data.length;
327 | } catch (Exception e) {
328 | e.printStackTrace();
329 | }
330 | }
331 |
332 | }
333 |
334 | short getIdent(){
335 | synchronized (syn_ident) {
336 | localIdent++;
337 | if(localIdent>=Short.MAX_VALUE){
338 | localIdent=0;
339 | }
340 | }
341 | return (short) localIdent;
342 | }
343 |
344 | public static byte[] getSimResponeHead(){
345 | StringBuffer sb=new StringBuffer();
346 |
347 | sb.append("HTTP/1.1 200 OK"+"\r\n");
348 | sb.append("Server: Apache/2.2.15 (CentOS)"+"\r\n");
349 | sb.append("Accept-Ranges: bytes"+"\r\n");
350 | sb.append("Content-Length: "+(Math.abs(random.nextInt()))+"\r\n");
351 | sb.append("Connection: Keep-Alive"+"\r\n");
352 | sb.append("Content-Type: application/octet-stream"+"\r\n");
353 | sb.append("\r\n");
354 |
355 | String simRequest=sb.toString();
356 | byte[] simData=simRequest.getBytes();
357 | return simData;
358 | }
359 |
360 | public static byte[] getSimRequestHead(int port){
361 | StringBuffer sb=new StringBuffer();
362 | String domainName=getRandomString(5+random.nextInt(10))+".com";
363 | sb.append("GET /"+getRandomString(8+random.nextInt(10))+"."+getRandomString(2+random.nextInt(5))+" HTTP/1.1"+"\r\n");
364 | sb.append("Accept: application/x-ms-application, image/jpeg, application/xaml+xml, image/gif, image/pjpeg, application/x-ms-xbap, */*"+"\r\n");
365 | sb.append("Accept-Language: zh-CN"+"\r\n");
366 | sb.append("Accept-Encoding: gzip, deflate"+"\r\n");
367 | sb.append("User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:36.0) Gecko/20100101 Firefox/36.0"+"\r\n");
368 | sb.append("Host: "+domainName+"\r\n");
369 | sb.append("Connection: Keep-Alive"+"\r\n");
370 | sb.append("\r\n");
371 | String simRequest=sb.toString();
372 | byte[] simData=simRequest.getBytes();
373 | return simData;
374 | }
375 |
376 | public static String getRandomString(int length) { //length表示生成字符串的长度
377 | String base = "abcdefghkmnopqrstuvwxyz";
378 | Random random = new Random();
379 | StringBuffer sb = new StringBuffer();
380 | for (int i = 0; i < length; i++) {
381 | int number = random.nextInt(base.length());
382 | sb.append(base.charAt(number));
383 | }
384 | return sb.toString();
385 | }
386 |
387 | public InetAddress getSourcrAddress() {
388 | return localAddress;
389 | }
390 |
391 | public int getSourcePort() {
392 | return localPort;
393 | }
394 |
395 | public void setSourcePort(short sourcePort) {
396 | this.localPort = sourcePort;
397 | }
398 |
399 | public boolean isConnectReady() {
400 | return connectReady;
401 | }
402 |
403 | public void setConnectReady(boolean connectReady) {
404 | this.connectReady = connectReady;
405 | }
406 |
407 | public String getKey() {
408 | return key;
409 | }
410 |
411 | public void setKey(String key) {
412 | this.key = key;
413 | }
414 |
415 | }
416 |
--------------------------------------------------------------------------------
/src/net/fs/cap/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/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/client/AddMapFrame.java:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2015 D1SM.net
2 |
3 | package net.fs.client;
4 |
5 | import java.awt.Dialog;
6 | import java.awt.Dimension;
7 | import java.awt.Insets;
8 | import java.awt.event.ActionEvent;
9 | import java.awt.event.ActionListener;
10 |
11 | import javax.swing.BorderFactory;
12 | import javax.swing.JButton;
13 | import javax.swing.JDialog;
14 | import javax.swing.JFrame;
15 | import javax.swing.JLabel;
16 | import javax.swing.JOptionPane;
17 | import javax.swing.JPanel;
18 | import javax.swing.JTextField;
19 | import javax.swing.SwingUtilities;
20 |
21 | import net.fs.rudp.Route;
22 | import net.miginfocom.swing.MigLayout;
23 |
24 | public class AddMapFrame extends JDialog{
25 |
26 | private static final long serialVersionUID = -3248779355079724594L;
27 |
28 | ClientUI ui;
29 |
30 | JTextField portTextField, text_port,nameTextField;
31 |
32 | int downloadSpeed,uploadSpeed;
33 |
34 | MapRule maprule_origin;
35 |
36 | boolean edit=false;
37 |
38 | AddMapFrame(final ClientUI ui,JFrame parent,final MapRule maprule_origin,final boolean edit){
39 | super(parent,Dialog.ModalityType.APPLICATION_MODAL);
40 | this.ui=ui;
41 | this.edit=edit;
42 | this.maprule_origin=maprule_origin;
43 | setTitle("增加映射");
44 | //setSize(size);
45 | if(edit){
46 | setTitle("编辑映射");
47 | }
48 |
49 | JPanel panel=(JPanel) getContentPane();
50 | panel.setLayout(new MigLayout("alignx center,aligny center,insets 10 10 10 10"));
51 |
52 |
53 | String text=""
54 | + "单位Mb ( 1Mb=128KB,10Mb=1280KB )
"
55 | + ""+"请正确输入,该值会直接影响加速效果.";
56 |
57 | JPanel p3=new JPanel();
58 | panel.add(p3,"wrap");
59 | p3.setBorder(BorderFactory.createEtchedBorder());
60 | p3.setLayout(new MigLayout("inset 5 5 5 5"));
61 |
62 | p3.add(new JLabel("名称:"));
63 | nameTextField=new JTextField();
64 | p3.add(nameTextField,"width :100: ,wrap");
65 |
66 | p3.add(new JLabel("加速端口:"));
67 | portTextField=new JTextField("");
68 | p3.add(portTextField,"width :50:,wrap");
69 | portTextField.setToolTipText("需要加速的端口号");
70 |
71 | p3.add(new JLabel("本地端口: "));
72 | text_port=new JTextField();
73 | p3.add(text_port,"width :50: ,wrap");
74 |
75 | JPanel p6=new JPanel();
76 | panel.add(p6,"align center,wrap");
77 | p6.setLayout(new MigLayout("align center"));
78 |
79 | JButton button_ok=createButton("确定");
80 | p6.add(button_ok);
81 | button_ok.addActionListener(new ActionListener() {
82 |
83 | @Override
84 | public void actionPerformed(ActionEvent e) {
85 | try {
86 | checkName(nameTextField.getText());
87 | checkPort(text_port.getText());
88 | checkPort(portTextField.getText());
89 | String name=nameTextField.getText();
90 | int listen_port=Integer.parseInt(text_port.getText());
91 | int dst_port=Integer.parseInt(portTextField.getText());
92 | MapRule mapRule_new=new MapRule();
93 | mapRule_new.setName(name);
94 | mapRule_new.listen_port=listen_port;
95 | mapRule_new.setDst_port(dst_port);
96 | if(!edit){
97 | ui.mapClient.portMapManager.addMapRule(mapRule_new);
98 | }else {
99 | ui.mapClient.portMapManager.updateMapRule(maprule_origin,mapRule_new);
100 | }
101 | ui.loadMapRule();
102 | ui.select(mapRule_new.name);
103 | setVisible(false);
104 | } catch (Exception e1) {
105 | //e2.printStackTrace();
106 | JOptionPane.showMessageDialog(ui.mainFrame, e1.getMessage(),"消息",JOptionPane.WARNING_MESSAGE);
107 | }
108 | }
109 | });
110 |
111 | p6.add(new JLabel(" "));
112 |
113 | JButton button_cancel=createButton("取消");
114 | p6.add(button_cancel);
115 | button_cancel.addActionListener(new ActionListener() {
116 |
117 | @Override
118 | public void actionPerformed(ActionEvent e) {
119 | setVisible(false);
120 | }
121 | });
122 |
123 |
124 | if(edit){
125 | nameTextField.setText(maprule_origin.name);
126 | text_port.setText(maprule_origin.listen_port+"");
127 | portTextField.setText(maprule_origin.dst_port+"");
128 | }
129 |
130 | pack();
131 | setLocationRelativeTo(parent);
132 | setVisible(true);
133 | }
134 |
135 | void checkName(String s) throws Exception{
136 | if(s.trim().equals("")){
137 | throw new Exception("请输入名称");
138 | }
139 | }
140 |
141 | void checkDstAddress(String s) throws Exception{
142 | if(s.trim().equals("")){
143 | throw new Exception("请输入目标地址");
144 | }
145 | }
146 |
147 | void checkPort(String s) throws Exception{
148 | int port=0;
149 | try {
150 | port=Integer.parseInt(s);
151 | } catch (Exception e1) {
152 | throw new Exception("请输入正确端口号");
153 | }
154 | if(port<1|port>256*256){
155 | throw new Exception("请输入正确端口号");
156 | }
157 | }
158 |
159 | JButton createButton(String name){
160 | JButton button=new JButton(name);
161 | button.setMargin(new Insets(0,5,0,5));
162 | button.setFocusPainted(false);
163 | return button;
164 | }
165 |
166 |
167 |
168 | }
169 |
--------------------------------------------------------------------------------
/src/net/fs/client/AlignCellRenderer.java:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2015 D1SM.net
2 |
3 | package net.fs.client;
4 |
5 | import javax.swing.table.DefaultTableCellRenderer;
6 |
7 | public class AlignCellRenderer extends DefaultTableCellRenderer{
8 | private static final long serialVersionUID = -6003599724059557606L;
9 |
10 | public AlignCellRenderer(int align){
11 | super();
12 | setHorizontalAlignment(align);
13 | }
14 |
15 | }
16 |
--------------------------------------------------------------------------------
/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 | public String getServerAddress() {
24 | return serverAddress;
25 | }
26 |
27 | public void setServerAddress(String serverAddress) {
28 | this.serverAddress = serverAddress;
29 | }
30 |
31 | public int getServerPort() {
32 | return serverPort;
33 | }
34 |
35 | public void setServerPort(int serverPort) {
36 | this.serverPort = serverPort;
37 | }
38 |
39 | public int getRemotePort() {
40 | return remotePort;
41 | }
42 |
43 | public void setRemotePort(int remotePort) {
44 | this.remotePort = remotePort;
45 | }
46 |
47 | public boolean isDirect_cn() {
48 | return direct_cn;
49 | }
50 |
51 | public void setDirect_cn(boolean direct_cn) {
52 | this.direct_cn = direct_cn;
53 | }
54 |
55 | public int getDownloadSpeed() {
56 | return downloadSpeed;
57 | }
58 |
59 | public void setDownloadSpeed(int downloadSpeed) {
60 | this.downloadSpeed = downloadSpeed;
61 | }
62 |
63 | public int getUploadSpeed() {
64 | return uploadSpeed;
65 | }
66 |
67 | public void setUploadSpeed(int uploadSpeed) {
68 | this.uploadSpeed = uploadSpeed;
69 | }
70 |
71 | public int getSocks5Port() {
72 | return socks5Port;
73 | }
74 |
75 | public void setSocks5Port(int socks5Port) {
76 | this.socks5Port = socks5Port;
77 | }
78 |
79 | public String getRemoteAddress() {
80 | return remoteAddress;
81 | }
82 |
83 | public void setRemoteAddress(String remoteAddress) {
84 | this.remoteAddress = remoteAddress;
85 | }
86 |
87 | public String getProtocal() {
88 | return protocal;
89 | }
90 |
91 | public void setProtocal(String protocal) {
92 | this.protocal = protocal;
93 | }
94 |
95 | }
96 |
--------------------------------------------------------------------------------
/src/net/fs/client/ClientNoUI.java:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2015 D1SM.net
2 |
3 | package net.fs.client;
4 |
5 |
6 | import java.io.IOException;
7 |
8 | import org.pcap4j.core.Pcaps;
9 |
10 | import net.fs.rudp.Route;
11 | import net.fs.utils.MLog;
12 |
13 |
14 | public class ClientNoUI extends ClientUI{
15 |
16 | @Override
17 | void run(){
18 | systemName=System.getProperty("os.name").toLowerCase();
19 | MLog.info("System: "+systemName+" "+System.getProperty("os.version"));
20 | ui=this;
21 |
22 | checkQuanxian();
23 | loadConfig();
24 |
25 | model=new MapRuleListModel();
26 | tcpMapRuleListTable=new MapRuleListTable(this,model);
27 |
28 |
29 |
30 | checkFireWallOn();
31 | if(!success_firewall_windows){
32 | MLog.info("启动windows防火墙失败,请先运行防火墙服务.");
33 | System.exit(0);
34 | }
35 | if(!success_firewall_osx){
36 | MLog.info("启动ipfw/pf防火墙失败,请先安装.");
37 | System.exit(0);
38 | }
39 |
40 | Thread thread=new Thread(){
41 | public void run(){
42 | try {
43 | Pcaps.findAllDevs();
44 | b1=true;
45 | } catch (Exception e3) {
46 | e3.printStackTrace();
47 |
48 | }
49 | }
50 | };
51 | thread.start();
52 | try {
53 | thread.join();
54 | } catch (InterruptedException e1) {
55 | e1.printStackTrace();
56 | }
57 | //JOptionPane.showMessageDialog(mainFrame,System.getProperty("os.name"));
58 | if(!b1){
59 | try {
60 | String msg="启动失败,请先安装libpcap";
61 | if(systemName.contains("windows")){
62 | msg="启动失败,请先安装winpcap";
63 | }
64 | MLog.info(msg);
65 | if(systemName.contains("windows")){
66 | try {
67 | Runtime.getRuntime().exec("winpcap_install.exe",null);
68 | } catch (IOException e) {
69 | e.printStackTrace();
70 | }
71 | }
72 | System.exit(0);
73 | } catch (Exception e2) {
74 | e2.printStackTrace();
75 | }
76 | }
77 |
78 |
79 | try {
80 | mapClient=new MapClient(this);
81 | } catch (final Exception e1) {
82 | e1.printStackTrace();
83 | capException=e1;
84 | //System.exit(0);;
85 | }
86 |
87 | try {
88 | if(!mapClient.route_tcp.capEnv.tcpEnable){
89 | MLog.info("无可用网络接口,只能使用udp协议.");
90 | }
91 | } catch (Exception e2) {
92 | e2.printStackTrace();
93 | }
94 |
95 | mapClient.setUi(this);
96 |
97 | mapClient.setMapServer(config.getServerAddress(), config.getServerPort(),config.getRemotePort() ,null,null,config.isDirect_cn(),config.getProtocal().equals("tcp"),
98 | null);
99 |
100 |
101 |
102 | setSpeed(config.getDownloadSpeed(),config.getUploadSpeed());
103 |
104 | loadMapRule();
105 |
106 | if(config.getDownloadSpeed()==0||config.getUploadSpeed()==0){
107 | new SpeedSetFrame(ui,mainFrame);
108 | }
109 |
110 | }
111 |
112 | @Override
113 | public void setMessage(String message){}
114 |
115 | @Override
116 | void setSpeed(int downloadSpeed,int uploadSpeed){
117 | config.setDownloadSpeed(downloadSpeed);
118 | config.setUploadSpeed(uploadSpeed);
119 | Route.localDownloadSpeed=downloadSpeed;
120 | Route.localUploadSpeed=config.uploadSpeed;
121 | }
122 | }
123 |
124 |
--------------------------------------------------------------------------------
/src/net/fs/client/ClientStartNoUI.java:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2015 D1SM.net
2 |
3 | package net.fs.client;
4 |
5 | public class ClientStartNoUI {
6 |
7 | public static void main(String[] args) {
8 | new ClientNoUI();
9 | }
10 |
11 | }
12 |
--------------------------------------------------------------------------------
/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 | void setMessage(String message);
9 |
10 | void updateUISpeed(int connNum, int downSpeed, int upSpeed);
11 |
12 | boolean login();
13 |
14 | boolean updateNode(boolean testSpeed);
15 |
16 | boolean isOsx_fw_pf();
17 |
18 | boolean isOsx_fw_ipfw();
19 |
20 | }
21 |
--------------------------------------------------------------------------------
/src/net/fs/client/FSClient.java:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2015 D1SM.net
2 |
3 | package net.fs.client;
4 |
5 | public class FSClient {
6 |
7 | public static void main(String[] args) {
8 | //new ClientUI().run();
9 | new ClientNoUI().run();
10 | }
11 |
12 | }
13 |
--------------------------------------------------------------------------------
/src/net/fs/client/MapClient.java:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2015 D1SM.net
2 |
3 | package net.fs.client;
4 |
5 | import java.io.BufferedReader;
6 | import java.io.File;
7 | import java.io.FileOutputStream;
8 | import java.io.IOException;
9 | import java.io.InputStream;
10 | import java.io.InputStreamReader;
11 | import java.net.InetAddress;
12 | import java.net.ServerSocket;
13 | import java.net.Socket;
14 | import java.security.NoSuchAlgorithmException;
15 | import java.util.ArrayList;
16 | import java.util.HashSet;
17 | import java.util.Random;
18 |
19 | import javax.crypto.KeyGenerator;
20 | import javax.crypto.SecretKey;
21 |
22 | import net.fs.rudp.ClientProcessorInterface;
23 | import net.fs.rudp.ConnectionProcessor;
24 | import net.fs.rudp.RUDPConfig;
25 | import net.fs.rudp.Route;
26 | import net.fs.rudp.TrafficEvent;
27 | import net.fs.rudp.Trafficlistener;
28 | import net.fs.utils.MLog;
29 | import net.fs.utils.NetStatus;
30 |
31 | public class MapClient implements Trafficlistener{
32 |
33 | ConnectionProcessor imTunnelProcessor;
34 |
35 | Route route_udp,route_tcp;
36 |
37 | short routePort=45;
38 |
39 | ClientUII ui;
40 |
41 | String serverAddress="";
42 |
43 | InetAddress address=null;
44 |
45 | int serverPort=130;
46 |
47 | NetStatus netStatus;
48 |
49 | long lastTrafficTime;
50 |
51 | int downloadSum=0;
52 |
53 | int uploadSum=0;
54 |
55 | Thread clientUISpeedUpdateThread;
56 |
57 | int connNum=0;
58 |
59 | HashSet processTable=new HashSet();
60 |
61 | Object syn_process=new Object();
62 |
63 | static MapClient mapClient;
64 |
65 | PortMapManager portMapManager;
66 |
67 | public String mapdstAddress;
68 |
69 | public int mapdstPort;
70 |
71 | static int monPort=25874;
72 |
73 | String systemName=System.getProperty("os.name").toLowerCase();
74 |
75 | boolean useTcp=true;
76 |
77 | long clientId;
78 |
79 | Random ran=new Random();
80 |
81 | MapClient(ClientUI ui) throws Exception {
82 | this.ui=ui;
83 | mapClient=this;
84 | try {
85 | final ServerSocket socket=new ServerSocket(monPort);
86 | new Thread(){
87 | public void run(){
88 | try {
89 | socket.accept();
90 | } catch (IOException e) {
91 | e.printStackTrace();
92 | System.exit(0);
93 | }
94 | }
95 | }.start();
96 | } catch (Exception e) {
97 | //e.printStackTrace();
98 | //System.exit(0);
99 | }
100 | try {
101 | route_tcp = new Route(null,routePort,Route.mode_client,true);
102 | } catch (Exception e1) {
103 | //e1.printStackTrace();
104 | throw e1;
105 | }
106 | try {
107 | route_udp = new Route(null,routePort,Route.mode_client,false);
108 | } catch (Exception e1) {
109 | //e1.printStackTrace();
110 | throw e1;
111 | }
112 | netStatus=new NetStatus();
113 |
114 | portMapManager=new PortMapManager(this);
115 |
116 | clientUISpeedUpdateThread=new Thread(){
117 | public void run(){
118 | while(true){
119 | try {
120 | Thread.sleep(500);
121 | } catch (InterruptedException e1) {
122 | e1.printStackTrace();
123 | }
124 | updateUISpeed();
125 | }
126 | }
127 | };
128 | clientUISpeedUpdateThread.start();
129 |
130 | Route.addTrafficlistener(this);
131 |
132 | }
133 |
134 | public static MapClient get(){
135 | return mapClient;
136 | }
137 |
138 | private void updateUISpeed(){
139 | if(ui!=null){
140 | ui.updateUISpeed(connNum,netStatus.getDownSpeed(),netStatus.getUpSpeed());
141 | }
142 | }
143 |
144 | public void setMapServer(String serverAddress,int serverPort,int remotePort,String passwordMd5,String password_proxy_Md5,boolean direct_cn,boolean tcp,
145 | String password){
146 | if(this.serverAddress==null
147 | ||!this.serverAddress.equals(serverAddress)
148 | ||this.serverPort!=serverPort){
149 |
150 | if(route_tcp.lastClientControl!=null){
151 | route_tcp.lastClientControl.close();
152 | }
153 |
154 | if(route_udp.lastClientControl!=null){
155 | route_udp.lastClientControl.close();
156 | }
157 |
158 | cleanRule();
159 | if(serverAddress!=null&&!serverAddress.equals("")){
160 | setFireWallRule(serverAddress,serverPort);
161 | }
162 |
163 | }
164 | this.serverAddress=serverAddress;
165 | this.serverPort=serverPort;
166 | address=null;
167 | useTcp=tcp;
168 | resetConnection();
169 | }
170 |
171 |
172 | void setFireWallRule(String serverAddress,int serverPort){
173 | String ip;
174 | try {
175 | ip = InetAddress.getByName(serverAddress).getHostAddress();
176 | if(systemName.contains("mac os")){
177 | if(ui.isOsx_fw_pf ()){
178 | String tempPath="./pf.conf";
179 | File f=new File(tempPath);
180 | File d=f.getParentFile();
181 | if(!d.exists()){
182 | d.mkdirs();
183 | }
184 | if(f.exists()){
185 | f.delete();
186 | }
187 | //必须换行结束
188 | String content="block drop quick proto tcp from any to "+ip+" port = "+serverPort+"\n";
189 | saveFile(content.getBytes(), tempPath);
190 |
191 | String cmd1="pfctl -d";
192 | runCommand(cmd1);
193 |
194 | String cmd2="pfctl -Rf "+f.getAbsolutePath();
195 | runCommand(cmd2);
196 |
197 | String cmd3="pfctl -e";
198 | runCommand(cmd3);
199 |
200 | //f.delete();
201 | }else if(ui.isOsx_fw_ipfw()){
202 | String cmd2="sudo ipfw add 5050 deny tcp from any to "+ip+" "+serverAddress+" out";
203 | runCommand(cmd2);
204 | }
205 | }else if(systemName.contains("linux")){
206 | String cmd2="iptables -t filter -A OUTPUT -d "+ip+" -p tcp --dport "+serverPort+" -j DROP -m comment --comment tcptun_fs ";
207 | runCommand(cmd2);
208 | }else if (systemName.contains("windows")) {
209 | try {
210 | if(systemName.contains("xp")||systemName.contains("2003")){
211 | String cmd_add1="ipseccmd -w REG -p \"tcptun_fs\" -r \"Block TCP/"+serverPort+"\" -f 0/255.255.255.255="+ip+"/255.255.255.255:"+serverPort+":tcp -n BLOCK -x ";
212 | final Process p2 = Runtime.getRuntime().exec(cmd_add1,null);
213 | p2.waitFor();
214 | }else {
215 | String cmd_add1="netsh advfirewall firewall add rule name=tcptun_fs protocol=TCP dir=out remoteport="+serverPort+" remoteip="+ip+" action=block ";
216 | final Process p2 = Runtime.getRuntime().exec(cmd_add1,null);
217 | p2.waitFor();
218 | String cmd_add2="netsh advfirewall firewall add rule name=tcptun_fs protocol=TCP dir=in remoteport="+serverPort+" remoteip="+ip+" action=block ";
219 | Process p3 = Runtime.getRuntime().exec(cmd_add2,null);
220 | p3.waitFor();
221 | }
222 | } catch (Exception e1) {
223 | e1.printStackTrace();
224 | }
225 | }
226 | } catch (Exception e) {
227 | e.printStackTrace();
228 | }
229 |
230 | }
231 |
232 | void saveFile(byte[] data,String path) throws Exception{
233 | FileOutputStream fos=null;
234 | try {
235 | fos=new FileOutputStream(path);
236 | fos.write(data);
237 | } catch (Exception e) {
238 | throw e;
239 | } finally {
240 | if(fos!=null){
241 | fos.close();
242 | }
243 | }
244 | }
245 |
246 | void cleanRule(){
247 | if(systemName.contains("mac os")){
248 | cleanTcpTunRule_osx();
249 | }else if(systemName.contains("linux")){
250 | cleanTcpTunRule_linux();
251 | }else {
252 | try {
253 | if(systemName.contains("xp")||systemName.contains("2003")){
254 | String cmd_delete="ipseccmd -p \"tcptun_fs\" -w reg -y";
255 | final Process p1 = Runtime.getRuntime().exec(cmd_delete,null);
256 | p1.waitFor();
257 | }else {
258 | String cmd_delete="netsh advfirewall firewall delete rule name=tcptun_fs ";
259 | final Process p1 = Runtime.getRuntime().exec(cmd_delete,null);
260 | p1.waitFor();
261 | }
262 |
263 | } catch (Exception e) {
264 | e.printStackTrace();
265 | }
266 | }
267 | }
268 |
269 | void cleanTcpTunRule_osx(){
270 | String cmd2="sudo ipfw delete 5050";
271 | runCommand(cmd2);
272 | }
273 |
274 |
275 | void cleanTcpTunRule_linux(){
276 | while(true){
277 | int row=getRow_linux();
278 | if(row>0){
279 | //MLog.println("删除行 "+row);
280 | String cmd="iptables -D OUTPUT "+row;
281 | runCommand(cmd);
282 | }else {
283 | break;
284 | }
285 | }
286 | }
287 |
288 | int getRow_linux(){
289 | int row_delect=-1;
290 | String cme_list_rule="iptables -L -n --line-number";
291 | //String [] cmd={"netsh","advfirewall set allprofiles state on"};
292 | Thread errorReadThread=null;
293 | try {
294 | final Process p = Runtime.getRuntime().exec(cme_list_rule,null);
295 |
296 | errorReadThread=new Thread(){
297 | public void run(){
298 | InputStream is=p.getErrorStream();
299 | BufferedReader localBufferedReader = new BufferedReader(new InputStreamReader(is));
300 | while (true){
301 | String line;
302 | try {
303 | line = localBufferedReader.readLine();
304 | if (line == null){
305 | break;
306 | }else{
307 | //System.out.println("erroraaa "+line);
308 | }
309 | } catch (IOException e) {
310 | e.printStackTrace();
311 | //error();
312 | break;
313 | }
314 | }
315 | }
316 | };
317 | errorReadThread.start();
318 |
319 |
320 |
321 | InputStream is=p.getInputStream();
322 | BufferedReader localBufferedReader = new BufferedReader(new InputStreamReader(is));
323 | while (true){
324 | String line;
325 | try {
326 | line = localBufferedReader.readLine();
327 | // System.out.println("standaaa "+line);
328 | if (line == null){
329 | break;
330 | }else{
331 | if(line.contains("tcptun_fs")){
332 | int index=line.indexOf(" ");
333 | if(index>0){
334 | String n=line.substring(0, index);
335 | try {
336 | if(row_delect<0){
337 | //System.out.println("standaaabbb "+line);
338 | row_delect=Integer.parseInt(n);
339 | }
340 | } catch (Exception e) {
341 |
342 | }
343 | }
344 | };
345 | }
346 | } catch (IOException e) {
347 | e.printStackTrace();
348 | break;
349 | }
350 | }
351 |
352 |
353 | errorReadThread.join();
354 | p.waitFor();
355 | } catch (Exception e) {
356 | e.printStackTrace();
357 | //error();
358 | }
359 | return row_delect;
360 | }
361 |
362 | void resetConnection(){
363 | synchronized (syn_process) {
364 |
365 | }
366 | }
367 |
368 | public void onProcessClose(ClientProcessorInterface process){
369 | synchronized (syn_process) {
370 | processTable.remove(process);
371 | }
372 | }
373 |
374 | synchronized public void closeAndTryConnect_Login(boolean testSpeed){
375 | close();
376 | boolean loginOK=ui.login();
377 | if(loginOK){
378 | ui.updateNode(testSpeed);
379 | //testPool();
380 | }
381 | }
382 |
383 | synchronized public void closeAndTryConnect(){
384 | close();
385 | //testPool();
386 | }
387 |
388 | public void close(){
389 | //closeAllProxyRequest();
390 | //poolManage.close();
391 | //CSocketPool.closeAll();
392 | }
393 |
394 | public void trafficDownload(TrafficEvent event) {
395 | ////#MLog.println("下载 "+event.getTraffic());
396 | netStatus.addDownload(event.getTraffic());
397 | lastTrafficTime=System.currentTimeMillis();
398 | downloadSum+=event.getTraffic();
399 | }
400 |
401 | public void trafficUpload(TrafficEvent event) {
402 | ////#MLog.println("上传 "+event.getTraffic());
403 | netStatus.addUpload(event.getTraffic());
404 | lastTrafficTime=System.currentTimeMillis();
405 | uploadSum+=event.getTraffic();
406 | }
407 |
408 | static void runCommand(String command){
409 | Thread standReadThread=null;
410 | Thread errorReadThread=null;
411 | try {
412 | final Process p = Runtime.getRuntime().exec(command,null);
413 | standReadThread=new Thread(){
414 | public void run(){
415 | InputStream is=p.getInputStream();
416 | BufferedReader localBufferedReader = new BufferedReader(new InputStreamReader(is));
417 | while (true){
418 | String line;
419 | try {
420 | line = localBufferedReader.readLine();
421 | //System.out.println("stand "+line);
422 | if (line == null){
423 | break;
424 | }
425 | } catch (IOException e) {
426 | e.printStackTrace();
427 | break;
428 | }
429 | }
430 | }
431 | };
432 | standReadThread.start();
433 |
434 | errorReadThread=new Thread(){
435 | public void run(){
436 | InputStream is=p.getErrorStream();
437 | BufferedReader localBufferedReader = new BufferedReader(new InputStreamReader(is));
438 | while (true){
439 | String line;
440 | try {
441 | line = localBufferedReader.readLine();
442 | if (line == null){
443 | break;
444 | }else{
445 | //System.out.println("error "+line);
446 | }
447 | } catch (IOException e) {
448 | e.printStackTrace();
449 | //error();
450 | break;
451 | }
452 | }
453 | }
454 | };
455 | errorReadThread.start();
456 | standReadThread.join();
457 | errorReadThread.join();
458 | p.waitFor();
459 | } catch (Exception e) {
460 | e.printStackTrace();
461 | //error();
462 | }
463 | }
464 |
465 | public boolean isUseTcp() {
466 | return useTcp;
467 | }
468 |
469 | public void setUseTcp(boolean useTcp) {
470 | this.useTcp = useTcp;
471 | }
472 |
473 | public ClientUII getUi() {
474 | return ui;
475 | }
476 |
477 | public void setUi(ClientUII ui) {
478 | this.ui = ui;
479 | }
480 |
481 | }
482 |
--------------------------------------------------------------------------------
/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 |
9 | public class MapRule implements Serializable{
10 |
11 | int listen_port;
12 |
13 | int dst_port;
14 |
15 | String name;
16 |
17 | boolean using=false;
18 |
19 | ServerSocket serverSocket;
20 |
21 | public int getListen_port() {
22 | return listen_port;
23 | }
24 |
25 | public void setListen_port(int listen_port) {
26 | this.listen_port = listen_port;
27 | }
28 |
29 | public int getDst_port() {
30 | return dst_port;
31 | }
32 |
33 | public void setDst_port(int dst_port) {
34 | this.dst_port = dst_port;
35 | }
36 |
37 | public String getName() {
38 | return name;
39 | }
40 |
41 | public void setName(String name) {
42 | this.name = name;
43 | }
44 |
45 | }
46 |
--------------------------------------------------------------------------------
/src/net/fs/client/MapRuleListModel.java:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2015 D1SM.net
2 |
3 | package net.fs.client;
4 |
5 | import java.util.ArrayList;
6 | import java.util.List;
7 | import java.util.ResourceBundle;
8 |
9 | import javax.swing.table.AbstractTableModel;
10 |
11 |
12 | public class MapRuleListModel extends AbstractTableModel{
13 |
14 | private static final long serialVersionUID = 2267856423317178816L;
15 |
16 | private List mapRuleList;
17 |
18 | String titles[] ;
19 |
20 | Class> types[] = new Class[] {String.class, String.class, String.class,String.class, String.class, String.class};
21 |
22 | MapRuleListModel(){
23 | mapRuleList=new ArrayList ();
24 | titles = new String[] {""};
25 | }
26 |
27 | public void setMapRuleList(List list){
28 | mapRuleList.clear();
29 | if(list!=null){
30 | mapRuleList.addAll(list);
31 | }
32 | fireTableDataChanged();
33 | }
34 |
35 | public int getMapRuleIndex(String name){
36 | int index=-1;
37 | int i=0;
38 | for(MapRule r:mapRuleList){
39 | if(name.equals(r.getName())){
40 | index=i;
41 | break;
42 | }
43 | i++;
44 | }
45 | return index;
46 | }
47 |
48 | List getMapRuleList(){
49 | return mapRuleList;
50 | }
51 |
52 | public MapRule getMapRuleAt(int row){
53 | if(row>-1&row getColumnClass(int c) {
82 | return types[c];
83 | }
84 |
85 |
86 | public boolean isCellEditable(int row, int col) {
87 | boolean b=false;
88 | if(col==0){
89 | b=true;
90 | }
91 | return false;
92 | }
93 | }
94 |
--------------------------------------------------------------------------------
/src/net/fs/client/MapRuleListTable.java:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2015 D1SM.net
2 |
3 | package net.fs.client;
4 |
5 | import java.awt.event.MouseEvent;
6 | import java.awt.event.MouseListener;
7 | import java.util.List;
8 |
9 | import javax.swing.JTable;
10 | import javax.swing.ListSelectionModel;
11 | import javax.swing.SwingUtilities;
12 | import javax.swing.event.ListSelectionEvent;
13 | import javax.swing.event.ListSelectionListener;
14 |
15 | public class MapRuleListTable extends JTable{
16 |
17 | private static final long serialVersionUID = -547936371303904463L;
18 |
19 | MapRuleListModel model;
20 |
21 | MapRuleListTable table;
22 |
23 | ClientUI ui;
24 |
25 | MapRuleListTable(ClientUI ui,final MapRuleListModel model){
26 | super();
27 | this.model=model;
28 | this.ui=ui;
29 | table=this;
30 | setModel(model);
31 |
32 | setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
33 | setRowSorter(null);
34 |
35 | getColumnModel().getColumn(0).setMinWidth(30);
36 |
37 | MapRuleRender rr=new MapRuleRender();
38 | getColumnModel().getColumn(0).setCellRenderer(rr);
39 | setRowHeight(50);
40 |
41 | new Thread(){
42 | public void run() {
43 | while(true){
44 | try {
45 | Thread.sleep(1000);
46 | refresh();
47 | } catch (InterruptedException e) {
48 | e.printStackTrace();
49 | }
50 | }
51 | }
52 | }.start();
53 |
54 | addMouseListener(new MouseListener() {
55 |
56 | @Override
57 | public void mouseReleased(MouseEvent e) {}
58 |
59 | @Override
60 | public void mousePressed(MouseEvent e) {
61 | if(e.getButton()==MouseEvent.BUTTON3&&e.getClickCount()==1){
62 | int index=rowAtPoint(e.getPoint());
63 | int modelIndex=convertRowIndexToModel(index);
64 | getSelectionModel().setSelectionInterval(modelIndex, modelIndex);
65 | }
66 | }
67 |
68 | @Override
69 | public void mouseExited(MouseEvent e) {}
70 |
71 | @Override
72 | public void mouseEntered(MouseEvent e) {}
73 |
74 | @Override
75 | public void mouseClicked(MouseEvent e) {
76 | if(e.getButton()==MouseEvent.BUTTON1&&e.getClickCount()==2){
77 | editRule();
78 | }
79 | }
80 | });
81 |
82 | }
83 |
84 | void editRule(){
85 | int index=getSelectedRow();
86 | int modelIndex=convertRowIndexToModel(index);
87 | MapRule mapRule=getModel().getMapRuleAt(modelIndex);
88 | AddMapFrame sf=new AddMapFrame(ui,ui.mainFrame,mapRule,true);
89 | //sf.setVisible(true);
90 | }
91 |
92 | void refresh(){
93 | SwingUtilities.invokeLater(new Runnable() {
94 |
95 | @Override
96 | public void run() {
97 | updateUI();
98 | }
99 | });
100 | }
101 |
102 | public void setMapRuleList(List list){
103 | model.setMapRuleList(list);
104 | }
105 |
106 | public MapRuleListModel getModel() {
107 | return model;
108 | }
109 |
110 | public void setModel(MapRuleListModel model) {
111 | super.setModel(model);
112 | this.model = model;
113 | }
114 |
115 | }
116 |
--------------------------------------------------------------------------------
/src/net/fs/client/MapRuleRender.java:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2015 D1SM.net
2 |
3 | package net.fs.client;
4 |
5 | import java.awt.Color;
6 | import java.awt.Component;
7 |
8 | import javax.swing.JLabel;
9 | import javax.swing.JPanel;
10 | import javax.swing.JTable;
11 | import javax.swing.table.TableCellRenderer;
12 |
13 |
14 | import net.miginfocom.swing.MigLayout;
15 | import sun.swing.DefaultLookup;
16 |
17 | public class MapRuleRender extends JLabel implements TableCellRenderer {
18 |
19 | private static final long serialVersionUID = -3260748459008436510L;
20 |
21 | JPanel pleft,pright,p1;
22 |
23 | JLabel label_wan_address;
24 | JLabel label2;
25 |
26 | MapRule rule;
27 |
28 | {
29 | setOpaque(true);
30 | setLayout(new MigLayout("insets 8 10 0 0"));
31 | label_wan_address=new JLabel();
32 | add(label_wan_address,"width :500:,wrap");
33 | label_wan_address.setBackground(new Color(0f,0f,0f,0f));
34 | label_wan_address.setOpaque(true);
35 | label2=new JLabel();
36 | add(label2,"width :500:,wrap");
37 | label2.setBackground(new Color(0f,0f,0f,0f));
38 | label2.setOpaque(true);
39 | }
40 |
41 |
42 | void update(MapRule rule,JTable table,int row){
43 | this.rule=rule;
44 | int rowHeight=50;
45 | int h=table.getRowHeight(row);
46 | if(h!=rowHeight){
47 | table.setRowHeight(row, rowHeight);
48 | }
49 | String name=rule.getName();
50 | if(name==null){
51 | name="无";
52 | }else if(name.trim().equals("")){
53 | name="无";
54 | }
55 | label_wan_address.setText("名称: "+rule.name+" 加速端口: "+rule.dst_port);
56 | label2.setText("本地端口: "+rule.getListen_port());
57 |
58 | }
59 |
60 | @Override
61 | public Component getTableCellRendererComponent(JTable table, Object value,
62 | boolean isSelected, boolean hasFocus, int row, int column) {
63 | Color fg = null;
64 | Color bg = null;
65 | JTable.DropLocation dropLocation = table.getDropLocation();
66 | if (dropLocation != null
67 | && !dropLocation.isInsertRow()
68 | && !dropLocation.isInsertColumn()
69 | && dropLocation.getRow() == row
70 | && dropLocation.getColumn() == column) {
71 |
72 | fg = DefaultLookup.getColor(this, ui, "Table.dropCellForeground");
73 | bg = DefaultLookup.getColor(this, ui, "Table.dropCellBackground");
74 | isSelected = true;
75 | }
76 | if (isSelected) {
77 | setBackground(DefaultLookup.getColor(this, ui, "Table.dropCellBackground"));
78 | } else {
79 | setBackground( DefaultLookup.getColor(this, ui, "Table.alternateRowColor"));
80 | }
81 | MapRule rule=(MapRule)value;
82 | update(rule,table,row);
83 | return this;
84 | }
85 |
86 | }
87 |
--------------------------------------------------------------------------------
/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 |
33 | public void pipe(InputStream is,UDPOutputStream tos,int initSpeed,final Pipe p2) throws Exception{
34 |
35 | int len=0;
36 | byte[] buf=new byte[100*1024];
37 | boolean sendeda=false;
38 | while((len=is.read(buf))>0){
39 | readed=true;
40 | if(!sendeda){
41 | sendeda=true;
42 | }
43 | tos.write(buf, 0, len);
44 | }
45 | }
46 |
47 |
48 |
49 | void sendSleep(long startTime,int speed,int length){
50 | long needTime=(long) (1000f*length/speed);
51 | long usedTime=System.currentTimeMillis()-startTime;
52 | if(usedTime0){
69 | if(!sendedb){
70 | pv=buf;
71 | pvl=len;
72 | sendedb=true;
73 | }
74 | n++;
75 | long needTime=1000*len/maxSpeed;
76 | long startTime=System.currentTimeMillis();
77 | os.write(buf, 0, len);
78 | if(!sended){
79 | sended=true;
80 | }
81 | long usedTime=System.currentTimeMillis()-startTime;
82 | if(usedTime 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/client/PortMapProcess.java:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2015 D1SM.net
2 |
3 | package net.fs.client;
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.Random;
10 |
11 | import net.fs.rudp.ClientProcessorInterface;
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 |
18 | import com.alibaba.fastjson.JSONObject;
19 |
20 | public class PortMapProcess implements ClientProcessorInterface{
21 |
22 | Random ran=new Random();
23 |
24 | UDPInputStream tis;
25 |
26 | UDPOutputStream tos;
27 |
28 | String serverAddress="";
29 |
30 | int serverPort;
31 |
32 | ConnectionUDP conn;
33 |
34 | MapClient mapClient;
35 |
36 | public Socket srcSocket,dstSocket;
37 |
38 | String password_proxy_md5;
39 |
40 | DataInputStream srcIs=null;
41 | DataOutputStream srcOs=null;
42 |
43 | boolean closed=false;
44 | boolean success=false;
45 |
46 | public PortMapProcess(MapClient mapClient,Route route,final Socket srcSocket,String serverAddress2,int serverPort2,String password_proxy_md5,
47 | String dstAddress,int dstPort){
48 | this.mapClient=mapClient;
49 | this.serverAddress=serverAddress2;
50 | this.serverPort=serverPort2;
51 |
52 | this.srcSocket=srcSocket;
53 | this.password_proxy_md5=password_proxy_md5;
54 |
55 | try {
56 | srcIs = new DataInputStream(srcSocket.getInputStream());
57 | srcOs=new DataOutputStream(srcSocket.getOutputStream());
58 | conn = route.getConnection(serverAddress, serverPort,null);
59 | tis=conn.uis;
60 | tos=conn.uos;
61 |
62 | JSONObject requestJson=new JSONObject();
63 | requestJson.put("dst_address", dstAddress);
64 | requestJson.put("dst_port", dstPort);
65 | requestJson.put("password_proxy_md5", password_proxy_md5);
66 | byte[] requestData=requestJson.toJSONString().getBytes("utf-8");
67 | tos.write(requestData, 0, requestData.length);
68 |
69 |
70 | final Pipe p1=new Pipe();
71 | final Pipe p2=new Pipe();
72 |
73 |
74 | byte[] responeData=tis.read2();
75 |
76 | String hs=new String(responeData,"utf-8");
77 | JSONObject responeJSon=JSONObject.parseObject(hs);
78 | int code=responeJSon.getIntValue("code");
79 | String message=responeJSon.getString("message");
80 | String uimessage="";
81 | if(code==Constant.code_success){
82 |
83 | Route.es.execute(new Runnable() {
84 |
85 | @Override
86 | public void run() {
87 | try {
88 | p2.pipe(tis, srcOs,1024*1024*1024,null);
89 | }catch (Exception e) {
90 | e.printStackTrace();
91 | }finally{
92 | close();
93 | }
94 | }
95 |
96 | });
97 |
98 | Route.es.execute(new Runnable() {
99 |
100 | @Override
101 | public void run() {
102 | try {
103 | p1.pipe(srcIs, tos,200*1024,p2);
104 | } catch (Exception e) {
105 | //e.printStackTrace();
106 | }finally{
107 | close();
108 | }
109 | }
110 |
111 | });
112 | success=true;
113 | uimessage=("连接服务器成功");
114 | }else {
115 | close();
116 | uimessage="连接服务器失败,"+message;
117 | }
118 | if(ClientUI.ui!=null){
119 | ClientUI.ui.setMessage(uimessage);
120 | }
121 | } catch (Exception e1) {
122 | e1.printStackTrace();
123 | }
124 |
125 | }
126 |
127 | void close(){
128 | if(!closed){
129 | closed=true;
130 | if(srcIs!=null){
131 | try {
132 | srcIs.close();
133 | } catch (IOException e) {
134 | e.printStackTrace();
135 | }
136 | }
137 | if(srcOs!=null){
138 | try {
139 | srcOs.close();
140 | } catch (IOException e) {
141 | e.printStackTrace();
142 | }
143 | }
144 | if(tos!=null){
145 | tos.closeStream_Local();
146 | }
147 | if(tis!=null){
148 | tis.closeStream_Local();
149 | }
150 | if(conn!=null){
151 | conn.close_local();
152 | }
153 | if(srcSocket!=null){
154 | try {
155 | srcSocket.close();
156 | } catch (IOException e) {
157 | e.printStackTrace();
158 | }
159 | }
160 | mapClient.onProcessClose(this);
161 |
162 | }
163 | }
164 |
165 | @Override
166 | public void onMapClientClose() {
167 | try {
168 | srcSocket.close();
169 | } catch (IOException e) {
170 | e.printStackTrace();
171 | }
172 | }
173 | }
174 |
--------------------------------------------------------------------------------
/src/net/fs/client/SpeedSetFrame.java:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2015 D1SM.net
2 |
3 | package net.fs.client;
4 |
5 | import java.awt.Dialog;
6 | import java.awt.Dimension;
7 | import java.awt.Insets;
8 | import java.awt.event.ActionEvent;
9 | import java.awt.event.ActionListener;
10 |
11 | import javax.swing.BorderFactory;
12 | import javax.swing.JButton;
13 | import javax.swing.JDialog;
14 | import javax.swing.JFrame;
15 | import javax.swing.JLabel;
16 | import javax.swing.JOptionPane;
17 | import javax.swing.JPanel;
18 | import javax.swing.JTextField;
19 | import javax.swing.SwingUtilities;
20 |
21 | import net.fs.rudp.Route;
22 | import net.miginfocom.swing.MigLayout;
23 |
24 | public class SpeedSetFrame extends JDialog{
25 |
26 | private static final long serialVersionUID = -3248779355079724594L;
27 |
28 | ClientUI ui;
29 |
30 | JTextField text_ds,text_us;
31 |
32 | int downloadSpeed,uploadSpeed;
33 |
34 | SpeedSetFrame(final ClientUI ui,JFrame parent){
35 | super(parent,Dialog.ModalityType.APPLICATION_MODAL);
36 | this.ui=ui;
37 | setTitle("设置带宽");
38 |
39 | JPanel panel=(JPanel) getContentPane();
40 | panel.setLayout(new MigLayout("alignx center,aligny center,insets 10 10 10 10"));
41 |
42 |
43 | panel.add(new JLabel("单位Mb ( 1Mb=128KB,10Mb=1280KB )"),"height ::,wrap");
44 | panel.add(new JLabel("请正确输入,该值会直接影响加速效果."),"height ::,wrap");
45 |
46 | JPanel p5=new JPanel();
47 | panel.add(p5,"wrap");
48 | p5.setLayout(new MigLayout(""));
49 | p5.add(new JLabel("下载带宽:"));
50 | text_ds=new JTextField("");
51 | p5.add(text_ds,"width 50::");
52 | p5.add(new JLabel("Mb"));
53 |
54 | p5.add(new JLabel(" "));
55 |
56 | p5.add(new JLabel("上传带宽:"));
57 | text_us=new JTextField("");
58 | p5.add(text_us,"width 50::");
59 | //text_us.setEditable(false);
60 | p5.add(new JLabel("Mb"));
61 |
62 | JPanel p6=new JPanel();
63 | panel.add(p6,"align center,wrap");
64 | p6.setLayout(new MigLayout("align center"));
65 |
66 | JButton button_ok=createButton("确定");
67 | p6.add(button_ok);
68 | button_ok.addActionListener(new ActionListener() {
69 |
70 | @Override
71 | public void actionPerformed(ActionEvent e) {
72 | String us=text_ds.getText().trim();
73 | String ds=text_us.getText().trim();
74 | try {
75 | int d=(int) (Float.parseFloat(us)*1024*1024/8/1.1);
76 | int u=(int) (Float.parseFloat(ds)*1024*1024/8/1.1);
77 | ui.setSpeed(d, u);
78 | setVisible(false);
79 | } catch (Exception e2) {
80 | //e2.printStackTrace();
81 | JOptionPane.showMessageDialog(ui.mainFrame, "输入错误!");
82 | }
83 |
84 | }
85 | });
86 |
87 | p6.add(new JLabel(" "));
88 |
89 | JButton button_cancel=createButton("取消");
90 | p6.add(button_cancel);
91 | button_cancel.addActionListener(new ActionListener() {
92 |
93 | @Override
94 | public void actionPerformed(ActionEvent e) {
95 | setVisible(false);
96 | }
97 | });
98 |
99 | pack();
100 | setLocationRelativeTo(parent);
101 | setVisible(true);
102 | }
103 |
104 | JButton createButton(String name){
105 | JButton button=new JButton(name);
106 | button.setMargin(new Insets(0,5,0,5));
107 | button.setFocusPainted(false);
108 | return button;
109 | }
110 |
111 |
112 |
113 | }
114 |
--------------------------------------------------------------------------------
/src/net/fs/client/TextComponentPopupMenu.java:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2015 D1SM.net
2 |
3 | package net.fs.client;
4 |
5 | import java.awt.Component;
6 | import java.awt.event.ActionEvent;
7 | import java.awt.event.ActionListener;
8 | import java.awt.event.MouseEvent;
9 | import java.awt.event.MouseListener;
10 |
11 | import javax.swing.JMenuItem;
12 | import javax.swing.JPasswordField;
13 | import javax.swing.JPopupMenu;
14 | import javax.swing.JTextField;
15 | import javax.swing.text.BadLocationException;
16 | import javax.swing.text.Document;
17 | import javax.swing.text.JTextComponent;
18 | import javax.swing.text.Position;
19 |
20 | public class TextComponentPopupMenu extends JPopupMenu implements
21 | MouseListener, ActionListener {
22 |
23 | private static final long serialVersionUID = 117096441855319758L;
24 | private static TextComponentPopupMenu sharedInstance = null;
25 |
26 | public static void installToComponent(JTextComponent c) {
27 | if (c instanceof JTextField && !(c instanceof JPasswordField)) {
28 | c.addMouseListener(TextComponentPopupMenu.getSharedInstance());
29 | }
30 | }
31 |
32 | public static void uninstallFromComponent(JTextComponent c) {
33 | if (c instanceof JTextField && !(c instanceof JPasswordField)) {
34 | c.removeMouseListener(getSharedInstance());
35 | }
36 | }
37 |
38 | JMenuItem cutItem, copyItem, pasteItem, deleteItem, selectAllItem;
39 |
40 | public TextComponentPopupMenu() {
41 | add(cutItem = new JMenuItem("剪切"));
42 | add(copyItem = new JMenuItem("复制"));
43 | add(pasteItem = new JMenuItem("粘贴"));
44 | add(deleteItem = new JMenuItem("删除"));
45 | addSeparator();
46 | add(selectAllItem = new JMenuItem("全选"));
47 |
48 | cutItem.setMnemonic('T');
49 | copyItem.setMnemonic('C');
50 | pasteItem.setMnemonic('P');
51 | deleteItem.setMnemonic('D');
52 | selectAllItem.setMnemonic('A');
53 |
54 | cutItem.addActionListener(this);
55 | copyItem.addActionListener(this);
56 | pasteItem.addActionListener(this);
57 | deleteItem.addActionListener(this);
58 | selectAllItem.addActionListener(this);
59 | }
60 |
61 | static TextComponentPopupMenu getSharedInstance() {
62 | if (sharedInstance == null) {
63 | sharedInstance = new TextComponentPopupMenu();
64 | }
65 | return sharedInstance;
66 | }
67 |
68 | public void mouseReleased(MouseEvent e) {
69 | if (e.isPopupTrigger() && e.getSource() instanceof JTextField) {
70 | JTextField textfield = (JTextField) e.getSource();
71 | if (Boolean.TRUE.equals(textfield
72 | .getClientProperty("DisablePopupMenu"))) {
73 | return;
74 | }
75 | textfield.requestFocusInWindow();
76 | show(textfield, e.getX(), e.getY());
77 | }
78 | }
79 |
80 | public void mouseClicked(MouseEvent e) {
81 | }
82 |
83 | public void mousePressed(MouseEvent e) {
84 | }
85 |
86 | public void mouseEntered(MouseEvent e) {
87 | }
88 |
89 | public void mouseExited(MouseEvent e) {
90 | }
91 |
92 | public void show(Component invoker, int x, int y) {
93 | JTextComponent tc = (JTextComponent) invoker;
94 | String sel = tc.getSelectedText();
95 |
96 | boolean selected = sel != null && !sel.equals("");
97 | boolean enableAndEditable = tc.isEnabled() && tc.isEditable();
98 |
99 | cutItem.setEnabled(selected && enableAndEditable);
100 | copyItem.setEnabled(selected && tc.isEnabled());
101 | deleteItem.setEnabled(selected && enableAndEditable);
102 | pasteItem.setEnabled(enableAndEditable);
103 | selectAllItem.setEnabled(tc.isEnabled());
104 |
105 | super.show(invoker, x, y);
106 | }
107 |
108 | public void actionPerformed(ActionEvent e) {
109 | JTextComponent tc = (JTextComponent) getInvoker();
110 |
111 | String sel = tc.getSelectedText();
112 |
113 | if (e.getSource() == cutItem) {
114 | tc.cut();
115 | } else if (e.getSource() == copyItem) {
116 | tc.copy();
117 | } else if (e.getSource() == pasteItem) {
118 | tc.paste();
119 | } else if (e.getSource() == selectAllItem) {
120 | tc.selectAll();
121 | } else if (e.getSource() == deleteItem) {
122 | Document doc = tc.getDocument();
123 | int start = tc.getSelectionStart();
124 | int end = tc.getSelectionEnd();
125 |
126 | try {
127 | Position p0 = doc.createPosition(start);
128 | Position p1 = doc.createPosition(end);
129 |
130 | if ((p0 != null) && (p1 != null)
131 | && (p0.getOffset() != p1.getOffset())) {
132 | doc.remove(p0.getOffset(), p1.getOffset() - p0.getOffset());
133 | }
134 | } catch (BadLocationException be) {
135 | }
136 | }
137 | }
138 | }
--------------------------------------------------------------------------------
/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/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 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/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/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/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/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/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/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/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 |
--------------------------------------------------------------------------------
/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 | }
--------------------------------------------------------------------------------
/src/net/fs/rudp/MapSocketPorcessor.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.Random;
11 | import java.util.concurrent.ExecutorService;
12 | import java.util.concurrent.Executors;
13 |
14 | import net.fs.utils.MLog;
15 |
16 |
17 | public class MapSocketPorcessor implements PipeListener{
18 |
19 |
20 | Socket srcSocket;
21 | Socket dstSocket;
22 |
23 | public DataInputStream srcIs;
24 | public DataOutputStream dstOs;
25 | public DataInputStream dstIs;
26 | public DataOutputStream srcOs;
27 |
28 | Object srcReadOb=new Object();
29 | Object dstReadOb=new Object();
30 | Object dstWriteOb=new Object();
31 | Object srcWriteOb=new Object();
32 |
33 | ArrayList 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/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 |
--------------------------------------------------------------------------------
/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/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/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/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/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/ResendManage.java:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2015 D1SM.net
2 |
3 | package net.fs.rudp;
4 |
5 | import java.util.HashMap;
6 | import java.util.concurrent.LinkedBlockingQueue;
7 |
8 |
9 |
10 | public class ResendManage implements Runnable{
11 |
12 | boolean haveTask=false;
13 | Object signalOb=new Object();
14 | Thread mainThread;
15 | long vTime=0;
16 | long lastReSendTime;
17 |
18 | LinkedBlockingQueue 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() 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