├── pom.xml
└── src
└── main
└── java
└── net
└── fs
├── cap
├── CapEnv.java
├── CapServer.java
├── CustomTcpSackOption.java
├── IPacket.java
├── PacketUtils.java
├── SendRecord.java
├── TCPTun.java
├── TunData.java
├── TunManager.java
└── VDatagramSocket.java
├── client
├── Client.java
├── ClientConfig.java
├── FSMain.java
├── LogFrame.java
├── MapClient.java
├── MapRule.java
├── MapRuleListModel.java
├── Pipe.java
├── PortMapManager.java
└── PortMapProcess.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
├── LogListener.java
├── LogOutputStream.java
├── MLog.java
├── MessageCheck.java
├── NetStatus.java
└── Tools.java
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
20 |
21 |
24 | 4.0.0
25 |
26 | me.sundp
27 | parent
28 | 1.0
29 |
30 | me.sundp
31 | finalspeed
32 | 1.0
33 |
34 |
35 | org.pcap4j
36 | pcap4j-packetfactory-static
37 | 1.6.2
38 |
39 |
40 | org.pcap4j
41 | pcap4j-core
42 | 1.6.2
43 |
44 |
45 | com.alibaba
46 | fastjson
47 | 1.2.83
48 |
49 |
50 | net.java.dev.jna
51 | jna
52 | 4.2.2
53 |
54 |
55 |
56 |
57 |
58 | org.apache.maven.plugins
59 | maven-shade-plugin
60 | 2.3
61 |
62 |
63 | package
64 |
65 | shade
66 |
67 |
68 |
69 |
71 | net.fs.client.FSMain
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 | org.apache.maven.plugins
80 | maven-compiler-plugin
81 | 3.1
82 |
83 | 1.6
84 | 1.6
85 |
86 |
87 |
88 |
89 |
--------------------------------------------------------------------------------
/src/main/java/net/fs/cap/CapServer.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed to the Apache Software Foundation (ASF) under one
3 | * or more contributor license agreements. See the NOTICE file
4 | * distributed with this work for additional information
5 | * regarding copyright ownership. The ASF licenses this file
6 | * to you under the Apache License, Version 2.0 (the
7 | * "License"); you may not use this file except in compliance
8 | * with the License. You may obtain a copy of the License at
9 | *
10 | * http://www.apache.org/licenses/LICENSE-2.0
11 | *
12 | * Unless required by applicable law or agreed to in writing,
13 | * software distributed under the License is distributed on an
14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 | * KIND, either express or implied. See the License for the
16 | * specific language governing permissions and limitations
17 | * under the License.
18 | */
19 |
20 | package net.fs.cap;
21 |
22 |
23 | public class CapServer {
24 |
25 | CapServer(){
26 | CapEnv capEnv=null;
27 | try {
28 | capEnv=new CapEnv(false,true);
29 | capEnv.init();
30 | } catch (Exception e) {
31 | e.printStackTrace();
32 | }
33 | }
34 |
35 | }
36 |
--------------------------------------------------------------------------------
/src/main/java/net/fs/cap/CustomTcpSackOption.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed to the Apache Software Foundation (ASF) under one
3 | * or more contributor license agreements. See the NOTICE file
4 | * distributed with this work for additional information
5 | * regarding copyright ownership. The ASF licenses this file
6 | * to you under the Apache License, Version 2.0 (the
7 | * "License"); you may not use this file except in compliance
8 | * with the License. You may obtain a copy of the License at
9 | *
10 | * http://www.apache.org/licenses/LICENSE-2.0
11 | *
12 | * Unless required by applicable law or agreed to in writing,
13 | * software distributed under the License is distributed on an
14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 | * KIND, either express or implied. See the License for the
16 | * specific language governing permissions and limitations
17 | * under the License.
18 | */
19 |
20 | package net.fs.cap;
21 |
22 | import org.pcap4j.packet.IllegalRawDataException;
23 | import org.pcap4j.packet.LengthBuilder;
24 | import org.pcap4j.packet.TcpPacket.TcpOption;
25 | import org.pcap4j.packet.namednumber.TcpOptionKind;
26 | import org.pcap4j.util.ByteArrays;
27 |
28 | import java.io.Serializable;
29 | import java.util.ArrayList;
30 | import java.util.List;
31 |
32 | import static org.pcap4j.util.ByteArrays.INT_SIZE_IN_BYTES;
33 |
34 | /**
35 | * @author Kaito Yamada
36 | * @since pcap4j 1.2.0
37 | */
38 | public final class CustomTcpSackOption implements TcpOption {
39 |
40 | /*
41 | * http://tools.ietf.org/html/rfc2018
42 | *
43 | * +--------+--------+
44 | * | Kind=5 | Length |
45 | * +--------+--------+--------+--------+
46 | * | Left Edge of 1st Block |
47 | * +--------+--------+--------+--------+
48 | * | Right Edge of 1st Block |
49 | * +--------+--------+--------+--------+
50 | * | |
51 | * / . . . /
52 | * | |
53 | * +--------+--------+--------+--------+
54 | * | Left Edge of nth Block |
55 | * +--------+--------+--------+--------+
56 | * | Right Edge of nth Block |
57 | * +--------+--------+--------+--------+
58 | */
59 |
60 | /**
61 | *
62 | */
63 | private static final long serialVersionUID = -3308738405807657257L;
64 |
65 | private final TcpOptionKind kind = TcpOptionKind.SACK;
66 | private final byte length;
67 | private final List sacks = new ArrayList();
68 |
69 | /**
70 | * A static factory method.
71 | * This method validates the arguments by {@link ByteArrays#validateBounds(byte[], int, int)},
72 | * which may throw exceptions undocumented here.
73 | *
74 | * @param rawData rawData
75 | * @param offset offset
76 | * @param length length
77 | * @return a new TcpSackOption object.
78 | * @throws IllegalRawDataException if parsing the raw data fails.
79 | */
80 | public static CustomTcpSackOption newInstance(
81 | byte[] rawData, int offset, int length
82 | ) throws IllegalRawDataException {
83 | ByteArrays.validateBounds(rawData, offset, length);
84 | return new CustomTcpSackOption(rawData, offset, length);
85 | }
86 |
87 | private CustomTcpSackOption(byte[] rawData, int offset, int length) throws IllegalRawDataException {
88 | if (length < 2) {
89 | StringBuilder sb = new StringBuilder(50);
90 | sb.append("The raw data length must be more than 1. 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 | if (rawData[offset] != kind.value()) {
99 | StringBuilder sb = new StringBuilder(100);
100 | sb.append("The kind must be: ")
101 | .append(kind.valueAsString())
102 | .append(" rawData: ")
103 | .append(ByteArrays.toHexString(rawData, " "))
104 | .append(", offset: ")
105 | .append(offset)
106 | .append(", length: ")
107 | .append(length);
108 | throw new IllegalRawDataException(sb.toString());
109 | }
110 |
111 | this.length = rawData[1 + offset];
112 | int lengthFieldAsInt = getLengthAsInt();
113 | if (lengthFieldAsInt < 2) {
114 | throw new IllegalRawDataException(
115 | "The value of length field must be more than 1 but: " + lengthFieldAsInt
116 | );
117 | }
118 |
119 | if ((lengthFieldAsInt - 2) % (INT_SIZE_IN_BYTES * 2) != 0) {
120 | StringBuilder sb = new StringBuilder(100);
121 | sb.append(
122 | "The value of length field must be an integer multiple of 8 octets long but: "
123 | )
124 | .append(lengthFieldAsInt);
125 | throw new IllegalRawDataException(sb.toString());
126 | }
127 | if (length < lengthFieldAsInt) {
128 | StringBuilder sb = new StringBuilder(100);
129 | sb.append("rawData is too short. length field: ")
130 | .append(lengthFieldAsInt)
131 | .append(", rawData: ")
132 | .append(ByteArrays.toHexString(rawData, " "))
133 | .append(", offset: ")
134 | .append(offset)
135 | .append(", length: ")
136 | .append(length);
137 | throw new IllegalRawDataException(sb.toString());
138 | }
139 |
140 | for (int i = 2; i < lengthFieldAsInt; i += INT_SIZE_IN_BYTES * 2) {
141 | sacks.add(
142 | new Sack(
143 | ByteArrays.getInt(rawData, i + offset),
144 | ByteArrays.getInt(rawData, i + INT_SIZE_IN_BYTES + offset)
145 | )
146 | );
147 | }
148 | }
149 |
150 | private CustomTcpSackOption(Builder builder) {
151 | if (
152 | builder == null
153 | || builder.sacks == null
154 | ) {
155 | StringBuilder sb = new StringBuilder();
156 | sb.append("builder: ").append(builder)
157 | .append(" builder.sacks: ").append(builder.sacks);
158 | throw new NullPointerException(sb.toString());
159 | }
160 |
161 | this.sacks.addAll(builder.sacks);
162 |
163 | if (builder.correctLengthAtBuild) {
164 | this.length = (byte)length();
165 | }
166 | else {
167 | this.length = builder.length;
168 | }
169 | }
170 |
171 | @Override
172 | public TcpOptionKind getKind() {
173 | return kind;
174 | }
175 |
176 | /**
177 | *
178 | * @return length
179 | */
180 | public byte getLength() { return length; }
181 |
182 | /**
183 | *
184 | * @return length
185 | */
186 | public int getLengthAsInt() { return 0xFF & length; }
187 |
188 | @Override
189 | public int length() {
190 | return sacks.size() * INT_SIZE_IN_BYTES * 2 + 2;
191 | }
192 |
193 | @Override
194 | public byte[] getRawData() {
195 | byte[] rawData = new byte[length()];
196 | rawData[0] = kind.value();
197 | rawData[1] = length;
198 |
199 | int offset = 2;
200 | for (Sack sack: sacks) {
201 | System.arraycopy(
202 | ByteArrays.toByteArray(sack.leftEdge), 0,
203 | rawData, offset, INT_SIZE_IN_BYTES
204 | );
205 | System.arraycopy(
206 | ByteArrays.toByteArray(sack.rightEdge), 0,
207 | rawData, offset + INT_SIZE_IN_BYTES, INT_SIZE_IN_BYTES
208 | );
209 | offset += INT_SIZE_IN_BYTES * 2;
210 | }
211 |
212 | return rawData;
213 | }
214 |
215 | /**
216 | *
217 | * @return a new Builder object populated with this object's fields.
218 | */
219 | public Builder getBuilder() {
220 | return new Builder(this);
221 | }
222 |
223 | @Override
224 | public String toString() {
225 | StringBuilder sb = new StringBuilder();
226 | sb.append("[Kind: ")
227 | .append(kind);
228 | sb.append("] [Length: ")
229 | .append(getLengthAsInt())
230 | .append(" bytes]");
231 | for (Sack sack: sacks) {
232 | sb.append(" [LE: ")
233 | .append(sack.getLeftEdgeAsLong())
234 | .append(" RE: ")
235 | .append(sack.getRightEdgeAsLong())
236 | .append("]");
237 | }
238 | return sb.toString();
239 | }
240 |
241 | @Override
242 | public boolean equals(Object obj) {
243 | if (obj == null) { return false; }
244 | if (obj == this) { return true; }
245 | if (!this.getClass().isInstance(obj)) { return false; }
246 |
247 | CustomTcpSackOption other = (CustomTcpSackOption)obj;
248 | return
249 | length == other.length
250 | && sacks.equals(other.sacks);
251 | }
252 |
253 | public List getSacks() {
254 | return sacks;
255 | }
256 |
257 | @Override
258 | public int hashCode() {
259 | int result = 17;
260 | result = 31 * result + length;
261 | result = 31 * result + sacks.hashCode();
262 | return result;
263 | }
264 |
265 | /**
266 | * @author Kaito Yamada
267 | * @since pcap4j 1.2.0
268 | */
269 | public static final class Builder
270 | implements LengthBuilder {
271 |
272 | private byte length;
273 | private boolean correctLengthAtBuild;
274 | private List sacks;
275 |
276 | /**
277 | *
278 | */
279 | public Builder() {}
280 |
281 | private Builder(CustomTcpSackOption option) {
282 | this.length = option.length;
283 | }
284 |
285 | /**
286 | * @param length length
287 | * @return this Builder object for method chaining.
288 | */
289 | public Builder length(byte length) {
290 | this.length = length;
291 | return this;
292 | }
293 |
294 | /**
295 | * @param sacks sacks
296 | * @return this Builder object for method chaining.
297 | */
298 | public Builder sacks(List sacks) {
299 | this.sacks = sacks;
300 | return this;
301 | }
302 |
303 | @Override
304 | public Builder correctLengthAtBuild(boolean correctLengthAtBuild) {
305 | this.correctLengthAtBuild = correctLengthAtBuild;
306 | return this;
307 | }
308 |
309 | @Override
310 | public CustomTcpSackOption build() {
311 | return new CustomTcpSackOption(this);
312 | }
313 |
314 | }
315 |
316 | /**
317 | * @author Kaito Yamada
318 | * @since pcap4j 1.2.0
319 | */
320 | public static final class Sack implements Serializable {
321 |
322 | /**
323 | *
324 | */
325 | private static final long serialVersionUID = 1218420566089129438L;
326 |
327 | private final int leftEdge;
328 | private final int rightEdge;
329 |
330 | /**
331 | * @param leftEdge leftEdge
332 | * @param rightEdge rightEdge
333 | */
334 | public Sack(int leftEdge, int rightEdge) {
335 | this.leftEdge = leftEdge;
336 | this.rightEdge = rightEdge;
337 | }
338 |
339 | /**
340 | * @return leftEdge
341 | */
342 | public int getLeftEdge() {
343 | return leftEdge;
344 | }
345 |
346 | /**
347 | * @return leftEdge
348 | */
349 | public long getLeftEdgeAsLong() {
350 | return 0xFFFFFFFFL & leftEdge;
351 | }
352 |
353 | /**
354 | * @return rightEdge
355 | */
356 | public int getRightEdge() {
357 | return rightEdge;
358 | }
359 |
360 | /**
361 | * @return rightEdge
362 | */
363 | public long getRightEdgeAsLong() {
364 | return 0xFFFFFFFFL & rightEdge;
365 | }
366 |
367 | @Override
368 | public boolean equals(Object obj) {
369 | if (obj == null) { return false; }
370 | if (obj == this) { return true; }
371 | if (!this.getClass().isInstance(obj)) { return false; }
372 |
373 | Sack other = (Sack)obj;
374 | return
375 | leftEdge == other.leftEdge
376 | && rightEdge == other.rightEdge;
377 | }
378 |
379 | @Override
380 | public int hashCode() {
381 | int result = 17;
382 | result = 31 * result + leftEdge;
383 | result = 31 * result + rightEdge;
384 | return result;
385 | }
386 |
387 | }
388 |
389 | }
390 |
--------------------------------------------------------------------------------
/src/main/java/net/fs/cap/IPacket.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed to the Apache Software Foundation (ASF) under one
3 | * or more contributor license agreements. See the NOTICE file
4 | * distributed with this work for additional information
5 | * regarding copyright ownership. The ASF licenses this file
6 | * to you under the Apache License, Version 2.0 (the
7 | * "License"); you may not use this file except in compliance
8 | * with the License. You may obtain a copy of the License at
9 | *
10 | * http://www.apache.org/licenses/LICENSE-2.0
11 | *
12 | * Unless required by applicable law or agreed to in writing,
13 | * software distributed under the License is distributed on an
14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 | * KIND, either express or implied. See the License for the
16 | * specific language governing permissions and limitations
17 | * under the License.
18 | */
19 |
20 | package net.fs.cap;
21 |
22 | import org.pcap4j.packet.Packet;
23 |
24 | public class IPacket {
25 |
26 | int index;
27 |
28 | int sequence;
29 |
30 | int legth;
31 |
32 | Packet packet;
33 |
34 | long firstSendTime;
35 |
36 | long sendTime;
37 |
38 | long reSendCount;
39 |
40 | }
41 |
--------------------------------------------------------------------------------
/src/main/java/net/fs/cap/PacketUtils.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed to the Apache Software Foundation (ASF) under one
3 | * or more contributor license agreements. See the NOTICE file
4 | * distributed with this work for additional information
5 | * regarding copyright ownership. The ASF licenses this file
6 | * to you under the Apache License, Version 2.0 (the
7 | * "License"); you may not use this file except in compliance
8 | * with the License. You may obtain a copy of the License at
9 | *
10 | * http://www.apache.org/licenses/LICENSE-2.0
11 | *
12 | * Unless required by applicable law or agreed to in writing,
13 | * software distributed under the License is distributed on an
14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 | * KIND, either express or implied. See the License for the
16 | * specific language governing permissions and limitations
17 | * under the License.
18 | */
19 |
20 | package net.fs.cap;
21 |
22 | import net.fs.utils.ByteShortConvert;
23 |
24 | import org.pcap4j.packet.EthernetPacket;
25 | import org.pcap4j.packet.IpV4Packet;
26 | import org.pcap4j.packet.IpV4Rfc1349Tos;
27 | import org.pcap4j.packet.Packet;
28 | import org.pcap4j.packet.TcpMaximumSegmentSizeOption;
29 | import org.pcap4j.packet.TcpNoOperationOption;
30 | import org.pcap4j.packet.TcpPacket;
31 | import org.pcap4j.packet.TcpPacket.TcpOption;
32 | import org.pcap4j.packet.TcpSackPermittedOption;
33 | import org.pcap4j.packet.TcpWindowScaleOption;
34 | import org.pcap4j.packet.UnknownPacket;
35 | import org.pcap4j.packet.namednumber.EtherType;
36 | import org.pcap4j.packet.namednumber.IpNumber;
37 | import org.pcap4j.packet.namednumber.IpVersion;
38 | import org.pcap4j.packet.namednumber.TcpPort;
39 | import org.pcap4j.util.MacAddress;
40 |
41 | import java.net.Inet4Address;
42 | import java.util.ArrayList;
43 | import java.util.List;
44 |
45 | public class PacketUtils {
46 |
47 | static byte ttl=64;
48 |
49 | static short mtu=1440;
50 |
51 | static byte shiftCount=6;
52 |
53 | static short window=(short) (64*1024-1);
54 |
55 | public static boolean ppp=false;
56 |
57 | public static byte[] pppHead_static={0x11,0x00,0x44,0x44,0x00,0x44,0x00,0x21};
58 |
59 | private PacketUtils() {
60 | }
61 |
62 |
63 | public static Packet buildIpV4(
64 | MacAddress srcAddress_mac,
65 | MacAddress dstAddrress_mac,
66 | IpV4Packet.Builder builder_ipv4){
67 |
68 | org.pcap4j.packet.Packet.Builder builder=null;
69 | EtherType etherType=null;
70 | Packet p=null;
71 | if(ppp){
72 | etherType=EtherType.PPPOE_SESSION_STAGE;
73 |
74 | UnknownPacket.Builder pppBuilder=new UnknownPacket.Builder();
75 | byte[] ipData=builder_ipv4.build().getRawData();
76 |
77 | byte[] lenb=new byte[2];
78 | ByteShortConvert.toByteArray((short) (ipData.length+2), lenb, 0);
79 |
80 | byte[] pppHead=new byte[8];
81 | System.arraycopy(pppHead_static, 0, pppHead, 0, pppHead.length);
82 | System.arraycopy(lenb, 0, pppHead, 4, 2);
83 |
84 | byte[] newData=new byte[pppHead.length+ipData.length];
85 | System.arraycopy(pppHead, 0, newData, 0, pppHead.length);
86 | System.arraycopy(ipData, 0, newData, 8, ipData.length);
87 | pppBuilder.rawData(newData);
88 |
89 | builder=pppBuilder;
90 | }else {
91 | etherType=EtherType.IPV4;
92 | builder=builder_ipv4;
93 | }
94 |
95 | EthernetPacket.Builder etherBuilder = new EthernetPacket.Builder();
96 | etherBuilder.dstAddr(dstAddrress_mac)
97 | .srcAddr(srcAddress_mac)
98 | .type(etherType)
99 | .payloadBuilder(builder)
100 | .paddingAtBuild(true);
101 |
102 | p = etherBuilder.build();
103 |
104 | return p;
105 | }
106 |
107 | static Packet createDataPacket(
108 | MacAddress srcAddress_mac,
109 | MacAddress dstAddrress_mac,
110 | Inet4Address srcAddress,short srcPort,
111 | Inet4Address dstAddress,short dstPort,
112 | int sequence,int ack, byte[] data,short ident){
113 | Packet p=null;
114 |
115 | TcpPacket.Builder builder_tcp=new TcpPacket.Builder();
116 | builder_tcp.payloadBuilder(new UnknownPacket.Builder().rawData(data));
117 | builder_tcp.correctChecksumAtBuild(true);
118 | builder_tcp.correctLengthAtBuild(true);
119 | builder_tcp.paddingAtBuild(true);
120 | builder_tcp.ack(true);
121 | builder_tcp.acknowledgmentNumber(ack);
122 | //builder_tcp.checksum(tcpHeader.getChecksum());
123 | //builder_tcp.dataOffset((byte)8);
124 | builder_tcp.dstAddr(dstAddress);
125 | builder_tcp.dstPort(new TcpPort( dstPort,""));
126 | builder_tcp.fin(false);
127 | //builder_tcp.options(tcpHeader.getOptions());
128 | //builder_tcp.padding(tcpHeader.getPadding());
129 | builder_tcp.psh(false);
130 | builder_tcp.reserved((byte) 0);
131 | builder_tcp.rst(false);
132 | builder_tcp.sequenceNumber(sequence);
133 | builder_tcp.srcAddr(srcAddress);
134 | builder_tcp.srcPort(new TcpPort( srcPort,""));
135 | builder_tcp.syn(false);
136 | builder_tcp.urg(false);
137 | //builder_tcp.urgentPointer(tcpHeader.getUrgentPointer());
138 | builder_tcp.window( window);
139 |
140 | IpV4Packet.Builder builder_ipv4=new IpV4Packet.Builder();
141 | builder_ipv4.correctChecksumAtBuild(true);
142 | builder_ipv4.correctLengthAtBuild(true);
143 | builder_ipv4.dontFragmentFlag(true);
144 | builder_ipv4.paddingAtBuild(true);
145 | builder_ipv4.dstAddr(dstAddress);
146 | builder_ipv4.fragmentOffset( (short)0);
147 | //builder_ipv4.headerChecksum(ipV4Header.getHeaderChecksum());
148 | //short identification= Math.abs(random.nextInt(Short.MAX_VALUE));
149 | //identification=ident;
150 | builder_ipv4.identification(ident);
151 | builder_ipv4.ihl((byte) 5);
152 | builder_ipv4.moreFragmentFlag(false);
153 | //builder_ipv4.options(ipV4Header.getOptions());
154 | //builder_ipv4.padding(ipV4Header.getPadding());
155 |
156 | builder_ipv4.protocol(IpNumber.TCP);
157 | //builder_ipv4.reservedFlag(ipV4Header.getReservedFlag());
158 | builder_ipv4.srcAddr(srcAddress);
159 | builder_ipv4.tos(IpV4Rfc1349Tos.newInstance((byte) 0));
160 | //builder_ipv4.totalLength( 52);
161 | builder_ipv4.ttl(ttl);
162 | builder_ipv4.version(IpVersion.IPV4);
163 | builder_ipv4.payloadBuilder(builder_tcp);
164 |
165 | p = buildIpV4(srcAddress_mac,dstAddrress_mac,builder_ipv4);
166 |
167 | return p;
168 | }
169 |
170 | static Packet createAck(
171 | MacAddress srcAddress_mac,
172 | MacAddress dstAddrress_mac,
173 | Inet4Address srcAddress,short srcPort,
174 | Inet4Address dstAddress,short dstPort,
175 | int ack_sequence,int sequence,short ident){
176 |
177 | TcpPacket.Builder builder_tcp=new TcpPacket.Builder();
178 | //builder_tcp.payloadBuilder(new UnknownPacket.Builder().rawData(new byte[0]));
179 | builder_tcp.correctChecksumAtBuild(true);
180 | builder_tcp.correctLengthAtBuild(true);
181 | builder_tcp.paddingAtBuild(true);
182 | builder_tcp.ack(true);
183 | builder_tcp.acknowledgmentNumber(ack_sequence);
184 | //builder_tcp.checksum(tcpHeader.getChecksum());
185 | //builder_tcp.dataOffset((byte) 8);
186 | builder_tcp.dstAddr(dstAddress);
187 | builder_tcp.dstPort(new TcpPort( dstPort,""));
188 | //builder_tcp.fin(tcpHeader.getFin());
189 |
190 | builder_tcp.psh(false);
191 | builder_tcp.reserved((byte) 0);
192 | builder_tcp.rst(false);
193 | builder_tcp.sequenceNumber(sequence);
194 | builder_tcp.srcAddr(srcAddress);
195 | builder_tcp.srcPort(new TcpPort( srcPort,""));
196 | builder_tcp.syn(false);
197 | builder_tcp.urg(false);
198 | //builder_tcp.urgentPointer(tcpHeader.getUrgentPointer());
199 | builder_tcp.window( window);
200 |
201 | IpV4Packet.Builder builder_ipv4=new IpV4Packet.Builder();
202 | builder_ipv4.correctChecksumAtBuild(true);
203 | builder_ipv4.correctLengthAtBuild(true);
204 | builder_ipv4.paddingAtBuild(true);
205 | builder_ipv4.dstAddr(dstAddress);
206 | builder_ipv4.dontFragmentFlag(true);
207 | builder_ipv4.fragmentOffset( (short) 0);
208 | //builder_ipv4.headerChecksum(ipV4Header.getHeaderChecksum());
209 | //short identification= Math.abs(random.nextInt(Short.MAX_VALUE));
210 | builder_ipv4.identification(ident);
211 | builder_ipv4.ihl((byte) 5);
212 | //builder_ipv4.moreFragmentFlag(ipV4Header.getMoreFragmentFlag());
213 | //builder_ipv4.options(ipV4Header.getOptions());
214 | //builder_ipv4.padding(ipV4Header.getPadding());
215 |
216 | builder_ipv4.protocol(IpNumber.TCP);
217 | // builder_ipv4.reservedFlag(ipV4Header.getReservedFlag());
218 | builder_ipv4.srcAddr(srcAddress);
219 | builder_ipv4.tos(IpV4Rfc1349Tos.newInstance((byte) 0));
220 | //builder_ipv4.totalLength( 52);
221 | builder_ipv4.ttl(ttl);
222 | builder_ipv4.version(IpVersion.IPV4);
223 | builder_ipv4.payloadBuilder(builder_tcp);
224 | //
225 |
226 | Packet p = buildIpV4(srcAddress_mac,dstAddrress_mac,builder_ipv4);
227 | //System.out.println("自定义确认 "+" identification "+identification+" ack_sequence "+ack_sequence+" # "+tcpPacket.getHeader());
228 | return p;
229 |
230 | }
231 |
232 |
233 | static Packet createSyncAck(
234 | MacAddress srcAddress_mac,
235 | MacAddress dstAddrress_mac,
236 | Inet4Address srcAddress,short srcPort,
237 | Inet4Address dstAddress,short dstPort,
238 | int ack_sequence,int sequence,short ident){
239 |
240 | TcpPacket.Builder builder_tcp=new TcpPacket.Builder();
241 | //builder_tcp.payloadBuilder(new UnknownPacket.Builder().rawData(new byte[0]));
242 | builder_tcp.correctChecksumAtBuild(true);
243 | builder_tcp.correctLengthAtBuild(true);
244 | builder_tcp.paddingAtBuild(true);
245 | builder_tcp.ack(true);
246 | builder_tcp.acknowledgmentNumber(ack_sequence);
247 | //builder_tcp.checksum(tcpHeader.getChecksum());
248 | //builder_tcp.dataOffset((byte) 8);
249 | builder_tcp.dstAddr(dstAddress);
250 | builder_tcp.dstPort(new TcpPort(dstPort,""));
251 | //builder_tcp.fin(tcpHeader.getFin());
252 |
253 |
254 | List tcp_options=new ArrayList();
255 |
256 | TcpNoOperationOption nop=TcpNoOperationOption.getInstance();
257 |
258 | TcpMaximumSegmentSizeOption seg_option=new TcpMaximumSegmentSizeOption.Builder().maxSegSize(mtu).correctLengthAtBuild(true).build();
259 | tcp_options.add(seg_option);
260 |
261 | tcp_options.add(nop);
262 | tcp_options.add(nop);
263 |
264 | TcpSackPermittedOption sack_permit_option=TcpSackPermittedOption.getInstance();
265 | tcp_options.add(sack_permit_option);
266 |
267 | tcp_options.add(nop);
268 |
269 | TcpWindowScaleOption win_option=new TcpWindowScaleOption.Builder().shiftCount(shiftCount).correctLengthAtBuild(true).build();
270 | tcp_options.add(win_option);
271 |
272 | builder_tcp.options(tcp_options);
273 |
274 | //builder_tcp.padding(tcpHeader.getPadding());
275 | builder_tcp.psh(false);
276 | builder_tcp.reserved((byte) 0);
277 | builder_tcp.rst(false);
278 | builder_tcp.sequenceNumber(sequence);
279 | builder_tcp.srcAddr(srcAddress);
280 | builder_tcp.srcPort(new TcpPort(srcPort,""));
281 | builder_tcp.syn(true);
282 | builder_tcp.urg(false);
283 | //builder_tcp.urgentPointer(tcpHeader.getUrgentPointer());
284 | builder_tcp.window( window);
285 |
286 | IpV4Packet.Builder builder_ipv4=new IpV4Packet.Builder();
287 | builder_ipv4.correctChecksumAtBuild(true);
288 | builder_ipv4.correctLengthAtBuild(true);
289 | builder_ipv4.paddingAtBuild(true);
290 | builder_ipv4.dstAddr(dstAddress);
291 | builder_ipv4.dontFragmentFlag(true);
292 | builder_ipv4.fragmentOffset((short)0);
293 | //builder_ipv4.headerChecksum(ipV4Header.getHeaderChecksum());
294 | // short identification= Math.abs(random.nextInt(Short.MAX_VALUE));
295 | builder_ipv4.identification(ident);
296 | builder_ipv4.ihl((byte) 5);
297 | //builder_ipv4.moreFragmentFlag(ipV4Header.getMoreFragmentFlag());
298 | //builder_ipv4.options(ipV4Header.getOptions());
299 | //builder_ipv4.padding(ipV4Header.getPadding());
300 |
301 | builder_ipv4.protocol(IpNumber.TCP);
302 | // builder_ipv4.reservedFlag(ipV4Header.getReservedFlag());
303 | builder_ipv4.srcAddr(srcAddress);
304 | builder_ipv4.tos(IpV4Rfc1349Tos.newInstance((byte) 0));
305 | //builder_ipv4.totalLength( 52);
306 | builder_ipv4.ttl(ttl);
307 | builder_ipv4.version(IpVersion.IPV4);
308 | builder_ipv4.payloadBuilder(builder_tcp);
309 | //
310 | Packet p = buildIpV4(srcAddress_mac,dstAddrress_mac,builder_ipv4);
311 | //System.out.println("自定义确认 "+" identification "+identification+" ack_sequence "+ack_sequence+" # "+tcpPacket.getHeader());
312 | return p;
313 |
314 | }
315 |
316 | static Packet createSync(
317 | MacAddress srcAddress_mac,
318 | MacAddress dstAddrress_mac,
319 | Inet4Address srcAddress,short srcPort,
320 | Inet4Address dstAddress,short dstPort,
321 | int sequence,short ident){
322 | TcpPacket.Builder builder_tcp=new TcpPacket.Builder();
323 | //builder_tcp.payloadBuilder(new UnknownPacket.Builder().rawData(new byte[0]));
324 | builder_tcp.correctChecksumAtBuild(true);
325 | builder_tcp.correctLengthAtBuild(true);
326 | builder_tcp.paddingAtBuild(true);
327 | //builder_tcp.ack(true);
328 | //builder_tcp.acknowledgmentNumber(ack_sequence);
329 | //builder_tcp.checksum(tcpHeader.getChecksum());
330 | //builder_tcp.dataOffset((byte) 8);
331 | builder_tcp.dstAddr(dstAddress);
332 | builder_tcp.dstPort(new TcpPort( dstPort,""));
333 | //builder_tcp.fin(tcpHeader.getFin());
334 |
335 | TcpNoOperationOption nop=TcpNoOperationOption.getInstance();
336 |
337 | List tcp_options=new ArrayList();
338 |
339 | TcpMaximumSegmentSizeOption seg_option=new TcpMaximumSegmentSizeOption.Builder().maxSegSize(mtu).correctLengthAtBuild(true).build();
340 | tcp_options.add(seg_option);
341 |
342 | tcp_options.add(nop);
343 |
344 | TcpWindowScaleOption win_option=new TcpWindowScaleOption.Builder().shiftCount((byte)6).correctLengthAtBuild(true).build();
345 | tcp_options.add(win_option);
346 |
347 | tcp_options.add(nop);
348 | tcp_options.add(nop);
349 |
350 | TcpSackPermittedOption sack_permit_option=TcpSackPermittedOption.getInstance();
351 | tcp_options.add(sack_permit_option);
352 |
353 | builder_tcp.options(tcp_options);
354 |
355 | //builder_tcp.padding(tcpHeader.getPadding());
356 | builder_tcp.psh(false);
357 | builder_tcp.reserved((byte) 0);
358 | builder_tcp.rst(false);
359 | builder_tcp.sequenceNumber(sequence);
360 | builder_tcp.srcAddr(srcAddress);
361 | builder_tcp.srcPort(new TcpPort( srcPort,""));
362 | builder_tcp.syn(true);
363 | builder_tcp.urg(false);
364 | //builder_tcp.urgentPointer(tcpHeader.getUrgentPointer());
365 | builder_tcp.window( window);
366 |
367 | IpV4Packet.Builder builder_ipv4=new IpV4Packet.Builder();
368 | builder_ipv4.correctChecksumAtBuild(true);
369 | builder_ipv4.correctLengthAtBuild(true);
370 | builder_ipv4.paddingAtBuild(true);
371 | builder_ipv4.dstAddr(dstAddress);
372 | builder_ipv4.dontFragmentFlag(true);
373 | builder_ipv4.fragmentOffset((short)0);
374 | //builder_ipv4.headerChecksum(ipV4Header.getHeaderChecksum());
375 | //short identification= Math.abs(random.nextInt(Short.MAX_VALUE));
376 | builder_ipv4.identification(ident);
377 | builder_ipv4.ihl((byte) 5);
378 | //builder_ipv4.moreFragmentFlag(ipV4Header.getMoreFragmentFlag());
379 | //builder_ipv4.options(ipV4Header.getOptions());
380 | //builder_ipv4.padding(ipV4Header.getPadding());
381 |
382 | builder_ipv4.protocol(IpNumber.TCP);
383 | // builder_ipv4.reservedFlag(ipV4Header.getReservedFlag());
384 | builder_ipv4.srcAddr(srcAddress);
385 | builder_ipv4.tos(IpV4Rfc1349Tos.newInstance((byte) 0));
386 | //builder_ipv4.totalLength( 52);
387 | builder_ipv4.ttl(ttl);
388 | builder_ipv4.version(IpVersion.IPV4);
389 | builder_ipv4.payloadBuilder(builder_tcp);
390 | //
391 | Packet p = buildIpV4(srcAddress_mac,dstAddrress_mac,builder_ipv4);
392 | // IpV4Packet p4=builder_ipv4.build();
393 | // TcpPacket tcpPacket=builder_tcp.build();
394 | //selfAckTable.add(identification);
395 | //System.out.println("自定义确认 "+" identification "+identification+" ack_sequence "+ack_sequence+" # "+tcpPacket.getHeader());
396 | return p;
397 |
398 | }
399 |
400 | }
401 |
--------------------------------------------------------------------------------
/src/main/java/net/fs/cap/SendRecord.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed to the Apache Software Foundation (ASF) under one
3 | * or more contributor license agreements. See the NOTICE file
4 | * distributed with this work for additional information
5 | * regarding copyright ownership. The ASF licenses this file
6 | * to you under the Apache License, Version 2.0 (the
7 | * "License"); you may not use this file except in compliance
8 | * with the License. You may obtain a copy of the License at
9 | *
10 | * http://www.apache.org/licenses/LICENSE-2.0
11 | *
12 | * Unless required by applicable law or agreed to in writing,
13 | * software distributed under the License is distributed on an
14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 | * KIND, either express or implied. See the License for the
16 | * specific language governing permissions and limitations
17 | * under the License.
18 | */
19 |
20 | package net.fs.cap;
21 |
22 | public class SendRecord {
23 |
24 | int sendCount;
25 |
26 | }
27 |
--------------------------------------------------------------------------------
/src/main/java/net/fs/cap/TCPTun.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed to the Apache Software Foundation (ASF) under one
3 | * or more contributor license agreements. See the NOTICE file
4 | * distributed with this work for additional information
5 | * regarding copyright ownership. The ASF licenses this file
6 | * to you under the Apache License, Version 2.0 (the
7 | * "License"); you may not use this file except in compliance
8 | * with the License. You may obtain a copy of the License at
9 | *
10 | * http://www.apache.org/licenses/LICENSE-2.0
11 | *
12 | * Unless required by applicable law or agreed to in writing,
13 | * software distributed under the License is distributed on an
14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 | * KIND, either express or implied. See the License for the
16 | * specific language governing permissions and limitations
17 | * under the License.
18 | */
19 |
20 | package net.fs.cap;
21 |
22 | import net.fs.utils.MLog;
23 |
24 | import org.pcap4j.core.NotOpenException;
25 | import org.pcap4j.core.PcapHandle;
26 | import org.pcap4j.core.PcapNativeException;
27 | import org.pcap4j.packet.EthernetPacket.EthernetHeader;
28 | import org.pcap4j.packet.IpV4Packet.IpV4Header;
29 | import org.pcap4j.packet.Packet;
30 | import org.pcap4j.packet.TcpPacket;
31 | import org.pcap4j.packet.TcpPacket.TcpHeader;
32 | import org.pcap4j.util.MacAddress;
33 |
34 | import java.net.Inet4Address;
35 | import java.net.InetAddress;
36 | import java.util.ArrayList;
37 | import java.util.HashMap;
38 | import java.util.HashSet;
39 | import java.util.Map;
40 | import java.util.Random;
41 | import java.util.Set;
42 |
43 |
44 | public class TCPTun {
45 |
46 | Map sendedTable_server=new HashMap ();
47 | HashMap sendedTable_history_server=new HashMap ();
48 |
49 | int clientSequence=Integer.MIN_VALUE;
50 |
51 | static Random random=new Random();
52 |
53 | PcapHandle sendHandle;
54 |
55 | Set selfAckTable=new HashSet();
56 |
57 | HashMap sendrecordTable=new HashMap();
58 |
59 | MacAddress dstMacaAddress;
60 |
61 | int sequenceNum=-1;
62 |
63 | Thread sendThread;
64 |
65 | boolean sended=false;
66 |
67 | Packet basePacket_server;
68 |
69 | short baseIdent=100;
70 |
71 | IPacket dst_readed_packet,last_send_packet;
72 |
73 | int presend_server;
74 |
75 | ArrayList packetList=new ArrayList();
76 |
77 | HashMap packetTable_l=new HashMap();
78 |
79 | HashMap packetTable=new HashMap();
80 |
81 | ArrayList unacked_list=new ArrayList();
82 |
83 | Object syn_packetList=new Object();
84 |
85 | int max_client_ack=Integer.MIN_VALUE;
86 |
87 | int sendIndex=0;
88 |
89 | long lasSetDelayTime=0;
90 |
91 | long lastDelay=300;
92 |
93 | Object syn_delay=new Object();
94 |
95 | Thread resendScanThread;
96 |
97 | boolean connectReady=false;
98 |
99 | boolean preDataReady=false;
100 |
101 | CapEnv capEnv;
102 |
103 | public Inet4Address remoteAddress;
104 | public short remotePort;
105 | int remoteStartSequence;
106 | int remoteSequence;
107 | int remoteIdent;
108 | int remoteSequence_max;
109 |
110 | Inet4Address localAddress;
111 | short localPort;
112 | int localStartSequence=random.nextInt();
113 | int localSequence;
114 | int localIdent=random.nextInt(Short.MAX_VALUE-100);
115 |
116 | Object syn_send_data=new Object();
117 |
118 | long lastSendAckTime;
119 |
120 | long lastReceiveDataTime;
121 |
122 | long createTime=System.currentTimeMillis();;
123 |
124 | String key;
125 |
126 | Object syn_ident=new Object();
127 |
128 | //客户端发起
129 | TCPTun(CapEnv capEnv,
130 | Inet4Address serverAddress,short serverPort,
131 | MacAddress srcAddress_mac,MacAddress dstAddrress_mac){
132 | this.capEnv=capEnv;
133 | sendHandle=capEnv.sendHandle;
134 | this.remoteAddress=serverAddress;
135 | this.remotePort=serverPort;
136 | localAddress=capEnv.local_ipv4;
137 | localPort=(short)(random.nextInt(64*1024-1-10000)+10000);
138 | Packet syncPacket=null;
139 | try {
140 | syncPacket = PacketUtils.createSync(srcAddress_mac, dstAddrress_mac, localAddress, localPort,serverAddress, serverPort, localStartSequence,getIdent());
141 | try {
142 | sendHandle.sendPacket(syncPacket);
143 | localSequence=localStartSequence+1;
144 | } catch (Exception e) {
145 | e.printStackTrace();
146 | }
147 | } catch (Exception e1) {
148 | e1.printStackTrace();
149 | }
150 | MLog.println("发送第一次握手 "+" ident "+localIdent);
151 | MLog.println(""+syncPacket);
152 |
153 | }
154 |
155 | //服务端接收
156 | TCPTun(CapEnv capServerEnv,
157 | Inet4Address remoteAddress,short remotePort){
158 | this.capEnv=capServerEnv;
159 | this.remoteAddress=remoteAddress;
160 | this.remotePort=remotePort;
161 | sendHandle=capEnv.sendHandle;
162 | localPort=capServerEnv.listenPort;
163 | localAddress=capEnv.local_ipv4;
164 | }
165 |
166 | void init_client(Inet4Address clientAddress,int clientPort,
167 | Inet4Address serverAddress,int serverPort,
168 | int client_start_sequence){
169 |
170 | }
171 |
172 | void init_server(Inet4Address clientAddress,int clientPort,
173 | Inet4Address serverAddress,int serverPort,
174 | int client_start_sequence,int server_start_sequence){
175 |
176 | }
177 |
178 | public void process_server(final Packet packet,EthernetHeader ethernetHeader,IpV4Header ipV4Header,TcpPacket tcpPacket,boolean client){
179 | TcpHeader tcpHeader=tcpPacket.getHeader();
180 |
181 | if(!preDataReady){
182 | if(!connectReady){
183 | //第一次握手
184 | dstMacaAddress=ethernetHeader.getSrcAddr();
185 | if(tcpHeader.getSyn()&&!tcpHeader.getAck()){
186 | remoteStartSequence=tcpHeader.getSequenceNumber();
187 | remoteSequence=remoteStartSequence+1;
188 | remoteSequence_max=remoteSequence;
189 | MLog.println("接收第一次握手 "+remoteAddress.getHostAddress()+":"+remotePort+"->"+localAddress.getHostAddress()+":"+localPort+" ident "+ipV4Header.getIdentification());
190 | MLog.println(""+packet);
191 | Packet responePacket=PacketUtils.createSyncAck(
192 | capEnv.local_mac,
193 | capEnv.gateway_mac,
194 | localAddress,(short)localPort,
195 | ipV4Header.getSrcAddr(),tcpHeader.getSrcPort().value(),
196 | tcpHeader.getSequenceNumber()+1,localStartSequence,(short)0
197 | );
198 | try {
199 | sendHandle.sendPacket(responePacket);
200 | } catch (Exception e) {
201 | e.printStackTrace();
202 | }
203 | localSequence=localStartSequence+1;
204 | MLog.println("发送第二次握手 "+capEnv.local_mac+"->"+capEnv.gateway_mac+" "+localAddress+"->"+" ident "+0);
205 |
206 | MLog.println(""+responePacket);
207 | }
208 |
209 | if(!tcpHeader.getSyn()&&tcpHeader.getAck()){
210 | if(tcpPacket.getPayload()==null){
211 | //第三次握手,客户端确认
212 | if(tcpHeader.getAcknowledgmentNumber()==localSequence){
213 | MLog.println("接收第三次握手 "+" ident "+ipV4Header.getIdentification());
214 | MLog.println(packet+"");
215 | Thread t1=new Thread(){
216 | public void run(){
217 | //startSend(basePacket_server,syc_sequence_client+1);
218 | }
219 | };
220 | //t1.start();
221 | connectReady=true;
222 | }
223 | }
224 | //MLog.println("客户端响应preview\n "+packet);
225 | //MLog.println("request "+tcp.ack());
226 | sendedTable_server.remove(tcpHeader.getAcknowledgmentNumber());
227 | boolean selfAck=selfAckTable.contains(ipV4Header.getIdentification());
228 | //MLog.println("客户端确认 "+"selfack "+selfAck+" id "+ipV4Header.getIdentification()+" ack_sequence "+tcpHeader.getAcknowledgmentNumberAsLong()+" "+sendedTable_server.size()+"ppppppp "+tcpHeader);
229 | }
230 |
231 | }else {
232 | if(tcpPacket.getPayload()!=null){
233 | preDataReady=true;
234 | onReceiveDataPacket( tcpPacket, tcpHeader, ipV4Header );
235 | byte[] sim=getSimResponeHead();
236 | sendData(sim);
237 | }
238 | }
239 | }else {
240 | if(tcpPacket.getPayload()!=null){
241 | onReceiveDataPacket( tcpPacket, tcpHeader, ipV4Header );
242 | TunData td=new TunData();
243 | td.tun=this;
244 | td.data=tcpPacket.getPayload().getRawData();
245 | capEnv.vDatagramSocket.onReceinveFromTun(td);
246 | }
247 | }
248 | if(tcpHeader.getRst()){
249 | MLog.println("reset packet "+ipV4Header.getIdentification()+" "+tcpHeader.getSequenceNumber()+" "+remoteAddress.getHostAddress()+":"+remotePort+"->"+localAddress.getHostAddress()+":"+localPort+" "+" ident "+ipV4Header.getIdentification());
250 | }
251 |
252 | }
253 |
254 | public void process_client(CapEnv capEnv,final Packet packet,EthernetHeader ethernetHeader,IpV4Header ipV4Header,TcpPacket tcpPacket,boolean client){
255 |
256 | TcpHeader tcpHeader=tcpPacket.getHeader();
257 | byte[] payload=null;
258 | if(tcpPacket.getPayload()!=null){
259 | payload=tcpPacket.getPayload().getRawData();
260 | }
261 |
262 | if(!preDataReady){
263 | if(!connectReady){
264 | if(tcpHeader.getAck()&&tcpHeader.getSyn()){
265 | if(tcpHeader.getAcknowledgmentNumber()==(localStartSequence+1)){
266 | MLog.println("接收第二次握手 "+" ident "+ipV4Header.getIdentification());
267 | MLog.println(""+packet);
268 | remoteStartSequence=tcpHeader.getSequenceNumber();
269 | remoteSequence=remoteStartSequence+1;
270 | remoteSequence_max=remoteSequence;
271 | Packet p3=PacketUtils.createAck(capEnv.local_mac, capEnv.gateway_mac, capEnv.local_ipv4, localPort, remoteAddress, remotePort, remoteSequence , localSequence,getIdent());
272 | try {
273 | sendHandle.sendPacket(p3);
274 | MLog.println("发送第三次握手 "+" ident "+localIdent);
275 | MLog.println(""+p3);
276 | connectReady=true;
277 |
278 | byte[] sim=getSimRequestHead(remotePort);
279 | sendData(sim);
280 | MLog.println("发送请求 "+" ident "+localIdent);
281 | } catch (PcapNativeException e) {
282 | e.printStackTrace();
283 | } catch (NotOpenException e) {
284 | e.printStackTrace();
285 | }
286 | }
287 | }
288 | }else {
289 | if(tcpPacket.getPayload()!=null){
290 | preDataReady=true;
291 | onReceiveDataPacket( tcpPacket, tcpHeader, ipV4Header );
292 | MLog.println("接收响应 "+" ident "+ipV4Header.getIdentification());
293 | }
294 | }
295 |
296 | }else {
297 | if(tcpPacket.getPayload()!=null){
298 | //MLog.println("客户端正式接收数据 "+capClientEnv.vDatagramSocket);
299 | onReceiveDataPacket( tcpPacket, tcpHeader, ipV4Header );
300 | TunData td=new TunData();
301 | td.tun=this;
302 | td.data=tcpPacket.getPayload().getRawData();
303 | capEnv.vDatagramSocket.
304 | onReceinveFromTun(td);
305 | }
306 | }
307 | if(tcpHeader.getRst()){
308 | MLog.println("reset packet "+ipV4Header.getIdentification()+" "+tcpHeader.getSequenceNumber()+" "+remoteAddress.getHostAddress()+":"+remotePort+"->"+localAddress.getHostAddress()+":"+localPort);
309 | }
310 |
311 | }
312 |
313 | void onReceiveDataPacket(TcpPacket tcpPacket,TcpHeader tcpHeader,IpV4Header ipV4Header ){
314 | if(System.currentTimeMillis()-lastSendAckTime>1000){
315 | int rs=tcpHeader.getSequenceNumber()+tcpPacket.getPayload().getRawData().length;
316 | if(rs>remoteSequence_max){
317 | remoteSequence_max=rs;
318 | }
319 | Packet ackPacket=PacketUtils.createAck(
320 | capEnv.local_mac,
321 | capEnv.gateway_mac,
322 | localAddress,(short)localPort,
323 | ipV4Header.getSrcAddr(),tcpHeader.getSrcPort().value(),
324 | remoteSequence_max, localSequence,getIdent());
325 | try {
326 | sendHandle.sendPacket(ackPacket);
327 | } catch (Exception e) {
328 | e.printStackTrace();
329 |
330 | }
331 | lastSendAckTime=System.currentTimeMillis();
332 | lastReceiveDataTime=System.currentTimeMillis();
333 | }
334 | }
335 |
336 | void sendData(byte[] data){
337 | Packet dataPacket=PacketUtils.createDataPacket(capEnv.local_mac,
338 | capEnv.gateway_mac,
339 | localAddress,localPort,
340 | remoteAddress,remotePort,
341 | localSequence,remoteSequence_max, data, (short) getIdent());
342 | synchronized (syn_send_data) {
343 | try {
344 | sendHandle.sendPacket(dataPacket);
345 | localSequence+=data.length;
346 | } catch (Exception e) {
347 | e.printStackTrace();
348 | }
349 | }
350 |
351 | }
352 |
353 | short getIdent(){
354 | synchronized (syn_ident) {
355 | localIdent++;
356 | if(localIdent>=Short.MAX_VALUE){
357 | localIdent=0;
358 | }
359 | }
360 | return (short) localIdent;
361 | }
362 |
363 | public static byte[] getSimResponeHead(){
364 | StringBuilder sb=new StringBuilder();
365 |
366 | sb.append("HTTP/1.1 200 OK"+"\r\n");
367 | sb.append("Server: Apache/2.2.15 (CentOS)"+"\r\n");
368 | sb.append("Accept-Ranges: bytes"+"\r\n");
369 | sb.append("Content-Length: "+(Math.abs(random.nextInt()))+"\r\n");
370 | sb.append("Connection: Keep-Alive"+"\r\n");
371 | sb.append("Content-Type: application/octet-stream"+"\r\n");
372 | sb.append("\r\n");
373 |
374 | String simRequest=sb.toString();
375 | byte[] simData=simRequest.getBytes();
376 | return simData;
377 | }
378 |
379 | public static byte[] getSimRequestHead(int port){
380 | StringBuilder sb=new StringBuilder();
381 | String domainName=getRandomString(5+random.nextInt(10))+".com";
382 | sb.append("GET /"+getRandomString(8+random.nextInt(10))+"."+getRandomString(2+random.nextInt(5))+" HTTP/1.1"+"\r\n");
383 | sb.append("Accept: application/x-ms-application, image/jpeg, application/xaml+xml, image/gif, image/pjpeg, application/x-ms-xbap, */*"+"\r\n");
384 | sb.append("Accept-Language: zh-CN"+"\r\n");
385 | sb.append("Accept-Encoding: gzip, deflate"+"\r\n");
386 | sb.append("User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:36.0) Gecko/20100101 Firefox/36.0"+"\r\n");
387 | sb.append("Host: "+domainName+"\r\n");
388 | sb.append("Connection: Keep-Alive"+"\r\n");
389 | sb.append("\r\n");
390 | String simRequest=sb.toString();
391 | byte[] simData=simRequest.getBytes();
392 | return simData;
393 | }
394 |
395 | public static String getRandomString(int length) { //length表示生成字符串的长度
396 | String base = "abcdefghkmnopqrstuvwxyz";
397 | Random random = new Random();
398 | StringBuilder sb = new StringBuilder();
399 | for (int i = 0; i < length; i++) {
400 | int number = random.nextInt(base.length());
401 | sb.append(base.charAt(number));
402 | }
403 | return sb.toString();
404 | }
405 |
406 | public InetAddress getSourcrAddress() {
407 | return localAddress;
408 | }
409 |
410 | public int getSourcePort() {
411 | return localPort;
412 | }
413 |
414 | public void setSourcePort(short sourcePort) {
415 | this.localPort = sourcePort;
416 | }
417 |
418 | public boolean isConnectReady() {
419 | return connectReady;
420 | }
421 |
422 | public void setConnectReady(boolean connectReady) {
423 | this.connectReady = connectReady;
424 | }
425 |
426 | public String getKey() {
427 | return key;
428 | }
429 |
430 | public void setKey(String key) {
431 | this.key = key;
432 | }
433 |
434 | }
435 |
--------------------------------------------------------------------------------
/src/main/java/net/fs/cap/TunData.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed to the Apache Software Foundation (ASF) under one
3 | * or more contributor license agreements. See the NOTICE file
4 | * distributed with this work for additional information
5 | * regarding copyright ownership. The ASF licenses this file
6 | * to you under the Apache License, Version 2.0 (the
7 | * "License"); you may not use this file except in compliance
8 | * with the License. You may obtain a copy of the License at
9 | *
10 | * http://www.apache.org/licenses/LICENSE-2.0
11 | *
12 | * Unless required by applicable law or agreed to in writing,
13 | * software distributed under the License is distributed on an
14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 | * KIND, either express or implied. See the License for the
16 | * specific language governing permissions and limitations
17 | * under the License.
18 | */
19 |
20 | package net.fs.cap;
21 |
22 |
23 | public class TunData {
24 |
25 | TCPTun tun;
26 |
27 | byte[] data;
28 |
29 | }
30 |
--------------------------------------------------------------------------------
/src/main/java/net/fs/cap/TunManager.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed to the Apache Software Foundation (ASF) under one
3 | * or more contributor license agreements. See the NOTICE file
4 | * distributed with this work for additional information
5 | * regarding copyright ownership. The ASF licenses this file
6 | * to you under the Apache License, Version 2.0 (the
7 | * "License"); you may not use this file except in compliance
8 | * with the License. You may obtain a copy of the License at
9 | *
10 | * http://www.apache.org/licenses/LICENSE-2.0
11 | *
12 | * Unless required by applicable law or agreed to in writing,
13 | * software distributed under the License is distributed on an
14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 | * KIND, either express or implied. See the License for the
16 | * specific language governing permissions and limitations
17 | * under the License.
18 | */
19 |
20 | package net.fs.cap;
21 |
22 | import net.fs.rudp.CopiedIterator;
23 | import net.fs.utils.MLog;
24 |
25 | import java.util.HashMap;
26 | import java.util.Iterator;
27 | import java.util.Map;
28 |
29 | public class TunManager {
30 |
31 | Map connTable=new HashMap();
32 |
33 | static TunManager tunManager;
34 |
35 | {
36 | tunManager=this;
37 | }
38 |
39 | TCPTun defaultTcpTun;
40 |
41 | Thread scanThread;
42 |
43 | Object syn_scan=new Object();
44 |
45 | CapEnv capEnv;
46 |
47 | {
48 | scanThread=new Thread(){
49 | public void run(){
50 | while(true){
51 | try {
52 | Thread.sleep(1000);
53 | } catch (InterruptedException e) {
54 | e.printStackTrace();
55 | }
56 | scan();
57 | }
58 | }
59 | };
60 | scanThread.start();
61 | }
62 |
63 | TunManager(CapEnv capEnv){
64 | this.capEnv=capEnv;
65 | }
66 |
67 | void scan(){
68 | Iterator it=getConnTableIterator();
69 | while(it.hasNext()){
70 | String key=it.next();
71 | TCPTun tun=connTable.get(key);
72 | if(tun!=null){
73 | if(tun.preDataReady){
74 | //无数据超时
75 | long t=System.currentTimeMillis()-tun.lastReceiveDataTime;
76 | if(t>6000){
77 | connTable.remove(key);
78 | if(capEnv.client){
79 | defaultTcpTun=null;
80 | MLog.println("tcp隧道超时");
81 | }
82 | }
83 | }else{
84 | //连接中超时
85 | if(System.currentTimeMillis()-tun.createTime>5000){
86 | connTable.remove(key);
87 | }
88 | }
89 | }
90 | }
91 | }
92 |
93 | public void removeTun(TCPTun tun){
94 | connTable.remove(tun.key);
95 | }
96 |
97 | Iterator getConnTableIterator(){
98 | Iterator it=null;
99 | synchronized (syn_scan) {
100 | it=new CopiedIterator(connTable.keySet().iterator());
101 | }
102 | return it;
103 | }
104 |
105 | public static TunManager get(){
106 | return tunManager;
107 | }
108 |
109 | public TCPTun getTcpConnection_Client(String remoteAddress,short remotePort,short localPort){
110 | return connTable.get(remoteAddress+":"+remotePort+":"+localPort);
111 | }
112 |
113 | public void addConnection_Client(TCPTun conn) {
114 | synchronized (syn_scan) {
115 | String key=conn.remoteAddress.getHostAddress()+":"+conn.remotePort+":"+conn.localPort;
116 | //MLog.println("addConnection "+key);
117 | conn.setKey(key);
118 | connTable.put(key, conn);
119 | }
120 | }
121 |
122 | public TCPTun getTcpConnection_Server(String remoteAddress,short remotePort){
123 | return connTable.get(remoteAddress+":"+remotePort);
124 | }
125 |
126 | public void addConnection_Server(TCPTun conn) {
127 | synchronized (syn_scan) {
128 | String key=conn.remoteAddress.getHostAddress()+":"+conn.remotePort;
129 | //MLog.println("addConnection "+key);
130 | conn.setKey(key);
131 | connTable.put(key, conn);
132 | }
133 | }
134 |
135 | public TCPTun getDefaultTcpTun() {
136 | return defaultTcpTun;
137 | }
138 |
139 | public void setDefaultTcpTun(TCPTun defaultTcpTun) {
140 | this.defaultTcpTun = defaultTcpTun;
141 | }
142 |
143 | }
144 |
--------------------------------------------------------------------------------
/src/main/java/net/fs/cap/VDatagramSocket.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed to the Apache Software Foundation (ASF) under one
3 | * or more contributor license agreements. See the NOTICE file
4 | * distributed with this work for additional information
5 | * regarding copyright ownership. The ASF licenses this file
6 | * to you under the Apache License, Version 2.0 (the
7 | * "License"); you may not use this file except in compliance
8 | * with the License. You may obtain a copy of the License at
9 | *
10 | * http://www.apache.org/licenses/LICENSE-2.0
11 | *
12 | * Unless required by applicable law or agreed to in writing,
13 | * software distributed under the License is distributed on an
14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 | * KIND, either express or implied. See the License for the
16 | * specific language governing permissions and limitations
17 | * under the License.
18 | */
19 |
20 | package net.fs.cap;
21 |
22 | import net.fs.rudp.Route;
23 |
24 | import java.io.IOException;
25 | import java.net.DatagramPacket;
26 | import java.net.DatagramSocket;
27 | import java.net.InetAddress;
28 | import java.net.SocketException;
29 | import java.util.concurrent.LinkedBlockingQueue;
30 |
31 | public class VDatagramSocket extends DatagramSocket{
32 |
33 | boolean useTcpTun=true;
34 |
35 | boolean client=true;
36 |
37 | LinkedBlockingQueue packetList=new LinkedBlockingQueue ();
38 |
39 | CapEnv capEnv;
40 |
41 | int localPort;
42 |
43 | Object syn_tun=new Object();
44 |
45 | boolean tunConnecting=false;
46 |
47 | public VDatagramSocket() throws SocketException {
48 |
49 | }
50 |
51 | public VDatagramSocket(int port) throws SocketException {
52 | localPort=port;
53 | }
54 |
55 | public int getLocalPort() {
56 | return localPort;
57 | }
58 |
59 | public void send(DatagramPacket p) throws IOException {
60 | TCPTun tun=null;
61 | if(client){
62 | tun=capEnv.tcpManager.getDefaultTcpTun();
63 | if(tun!=null){
64 | if(!tun.remoteAddress.getHostAddress().equals(p.getAddress().getHostAddress())
65 | ||CapEnv.toUnsigned(tun.remotePort)!=p.getPort()){
66 | capEnv.tcpManager.removeTun(tun);
67 | capEnv.tcpManager.setDefaultTcpTun(null);
68 | }
69 | }else {
70 | tryConnectTun_Client(p.getAddress(),(short) p.getPort());
71 | tun=capEnv.tcpManager.getDefaultTcpTun();
72 | }
73 | }else {
74 | tun=capEnv.tcpManager.getTcpConnection_Server(p.getAddress().getHostAddress(), (short) p.getPort());
75 | }
76 | if(tun!=null){
77 | if(tun.preDataReady){
78 | tun.sendData(p.getData());
79 | }else{
80 | throw new IOException("隧道未连接!");
81 | }
82 | }else{
83 |
84 | throw new IOException("隧道不存在! "+" thread "+Route.es.getActiveCount()+" "+p.getAddress()+":"+p.getPort());
85 | }
86 | }
87 |
88 |
89 | void tryConnectTun_Client(InetAddress dstAddress,short dstPort){
90 | synchronized (syn_tun) {
91 | if(capEnv.tcpManager.getDefaultTcpTun()==null){
92 | if(tunConnecting){
93 | try {
94 | syn_tun.wait();
95 | } catch (InterruptedException e) {
96 | e.printStackTrace();
97 | }
98 | }else {
99 | tunConnecting=true;
100 | try {
101 | capEnv.createTcpTun_Client(dstAddress.getHostAddress(), dstPort);
102 | } catch (Exception e) {
103 | e.printStackTrace();
104 | }
105 | tunConnecting=false;
106 | }
107 | }
108 | }
109 | }
110 |
111 |
112 | public synchronized void receive(DatagramPacket p) throws IOException {
113 | TunData td=null;
114 | try {
115 | td=packetList.take();
116 | p.setData(td.data);
117 | p.setLength(td.data.length);
118 | p.setAddress(td.tun.remoteAddress);
119 | p.setPort(CapEnv.toUnsigned(td.tun.remotePort));
120 | } catch (InterruptedException e) {
121 | e.printStackTrace();
122 | }
123 | }
124 |
125 | void onReceinveFromTun(TunData td){
126 | packetList.add(td);
127 | }
128 |
129 | public boolean isClient() {
130 | return client;
131 | }
132 |
133 | public void setClient(boolean client) {
134 | this.client = client;
135 | }
136 |
137 | public CapEnv getCapEnv() {
138 | return capEnv;
139 | }
140 |
141 | public void setCapEnv(CapEnv capEnv) {
142 | this.capEnv = capEnv;
143 | capEnv.vDatagramSocket=this;
144 | }
145 |
146 | }
147 |
--------------------------------------------------------------------------------
/src/main/java/net/fs/client/Client.java:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2015 D1SM.net
2 |
3 | package net.fs.client;
4 |
5 | import java.io.DataInputStream;
6 | import java.io.File;
7 | import java.io.FileInputStream;
8 | import java.io.FileOutputStream;
9 | import java.io.IOException;
10 |
11 | import com.alibaba.fastjson.JSONObject;
12 | import net.fs.rudp.Route;
13 | import net.fs.utils.LogOutputStream;
14 | import net.fs.utils.MLog;
15 | import org.pcap4j.core.Pcaps;
16 |
17 | public class Client {
18 |
19 | MapClient mapClient;
20 |
21 | ClientConfig config = null;
22 |
23 | String configFilePath = "client_config.json";
24 |
25 | String domain = "";
26 |
27 | String homeUrl;
28 |
29 | public static Client ui;
30 |
31 | MapRuleListModel model;
32 |
33 | Exception capException = null;
34 | boolean b1 = false;
35 |
36 | String systemName = null;
37 |
38 | String updateUrl;
39 |
40 | boolean min=false;
41 |
42 | LogFrame logFrame;
43 |
44 | LogOutputStream los;
45 |
46 | boolean tcpEnable=true;
47 |
48 | {
49 | domain = "ip4a.com";
50 | homeUrl = "http://www.ip4a.com/?client_fs";
51 | updateUrl = "http://fs.d1sm.net/finalspeed/update.properties";
52 | }
53 |
54 | Client() {
55 | los=new LogOutputStream(System.out);
56 | System.setOut(los);
57 | System.setErr(los);
58 |
59 | systemName = System.getProperty("os.name").toLowerCase();
60 | MLog.info("System: " + systemName + " " + System.getProperty("os.version"));
61 | ui = this;
62 | loadConfig();
63 | Route.localDownloadSpeed=config.downloadSpeed;
64 | Route.localUploadSpeed=config.uploadSpeed;
65 | model = new MapRuleListModel();
66 |
67 | boolean tcpEnvSuccess=true;
68 |
69 | Thread thread = new Thread() {
70 | public void run() {
71 | try {
72 | Pcaps.findAllDevs();
73 | b1 = true;
74 | } catch (Exception e3) {
75 | e3.printStackTrace();
76 |
77 | }
78 | }
79 | };
80 | thread.start();
81 | try {
82 | thread.join();
83 | } catch (InterruptedException e1) {
84 | e1.printStackTrace();
85 | }
86 | if (!b1) {
87 | tcpEnvSuccess=false;
88 | String msg = "启动失败,请先安装libpcap,否则无法使用tcp协议";
89 | if (systemName.contains("windows")) {
90 | msg = "启动失败,请先安装winpcap,否则无法使用tcp协议";
91 | }
92 | MLog.println(msg);
93 | if (systemName.contains("windows")) {
94 | try {
95 | Process p = Runtime.getRuntime().exec("winpcap_install.exe", null);
96 | } catch (IOException e) {
97 | e.printStackTrace();
98 | }
99 | tcpEnable=false;
100 | //System.exit(0);
101 | }
102 | }
103 |
104 |
105 | try {
106 | mapClient = new MapClient(this,tcpEnvSuccess);
107 | } catch (final Exception e1) {
108 | e1.printStackTrace();
109 | capException = e1;
110 | }
111 |
112 | mapClient.setMapServer(config.getServerAddress(), config.getServerPort(), config.getRemotePort(), null, null, config.isDirect_cn(), config.getProtocal().equals("tcp"),
113 | null);
114 |
115 | }
116 |
117 | ClientConfig loadConfig() {
118 | ClientConfig cfg = new ClientConfig();
119 | if (!new File(configFilePath).exists()) {
120 | JSONObject json = new JSONObject();
121 | try {
122 | saveFile(json.toJSONString().getBytes(), configFilePath);
123 | } catch (Exception e) {
124 | e.printStackTrace();
125 | }
126 | }
127 | try {
128 | String content = readFileUtf8(configFilePath);
129 | JSONObject json = JSONObject.parseObject(content);
130 | cfg.setServerAddress(json.getString("server_address"));
131 | cfg.setServerPort(json.getIntValue("server_port"));
132 | cfg.setRemotePort(json.getIntValue("remote_port"));
133 | cfg.setRemoteAddress(json.getString("remote_address"));
134 | if (json.containsKey("direct_cn")) {
135 | cfg.setDirect_cn(json.getBooleanValue("direct_cn"));
136 | }
137 | cfg.setDownloadSpeed(json.getIntValue("download_speed"));
138 | cfg.setUploadSpeed(json.getIntValue("upload_speed"));
139 | if (json.containsKey("socks5_port")) {
140 | cfg.setSocks5Port(json.getIntValue("socks5_port"));
141 | }
142 | if (json.containsKey("protocal")) {
143 | cfg.setProtocal(json.getString("protocal"));
144 | }
145 | if (json.containsKey("auto_start")) {
146 | cfg.setAutoStart(json.getBooleanValue("auto_start"));
147 | }
148 | config = cfg;
149 | } catch (Exception e) {
150 | e.printStackTrace();
151 | }
152 | return cfg;
153 | }
154 |
155 |
156 | public static String readFileUtf8(String path) throws Exception {
157 | String str = null;
158 | FileInputStream fis = null;
159 | DataInputStream dis = null;
160 | try {
161 | File file = new File(path);
162 |
163 | int length = (int) file.length();
164 | byte[] data = new byte[length];
165 |
166 | fis = new FileInputStream(file);
167 | dis = new DataInputStream(fis);
168 | dis.readFully(data);
169 | str = new String(data, "utf-8");
170 |
171 | } catch (Exception e) {
172 | e.printStackTrace();
173 | throw e;
174 | } finally {
175 | if (fis != null) {
176 | try {
177 | fis.close();
178 | } catch (IOException e) {
179 | e.printStackTrace();
180 | }
181 | }
182 | if (dis != null) {
183 | try {
184 | dis.close();
185 | } catch (IOException e) {
186 | e.printStackTrace();
187 | }
188 | }
189 | }
190 |
191 | return str;
192 | }
193 |
194 | void saveFile(byte[] data, String path) throws Exception {
195 | FileOutputStream fos = null;
196 | try {
197 | fos = new FileOutputStream(path);
198 | fos.write(data);
199 | } catch (Exception e) {
200 | if (systemName.contains("windows")) {
201 | MLog.info("保存配置文件失败,请尝试以管理员身份运行! " + path);
202 | System.exit(0);
203 | }
204 | throw e;
205 | } finally {
206 | if (fos != null) {
207 | fos.close();
208 | }
209 | }
210 | }
211 |
212 | }
213 |
--------------------------------------------------------------------------------
/src/main/java/net/fs/client/ClientConfig.java:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2015 D1SM.net
2 |
3 | package net.fs.client;
4 |
5 | public class ClientConfig {
6 |
7 | String serverAddress="";
8 |
9 | int serverPort;
10 |
11 | int remotePort;
12 |
13 | int downloadSpeed,uploadSpeed;
14 |
15 | boolean direct_cn=true;
16 |
17 | int socks5Port=1083;
18 |
19 | String remoteAddress;
20 |
21 | String protocal="tcp";
22 |
23 | boolean autoStart=false;
24 |
25 | public String getServerAddress() {
26 | return serverAddress;
27 | }
28 |
29 | public void setServerAddress(String serverAddress) {
30 | this.serverAddress = serverAddress;
31 | }
32 |
33 | public int getServerPort() {
34 | return serverPort;
35 | }
36 |
37 | public void setServerPort(int serverPort) {
38 | this.serverPort = serverPort;
39 | }
40 |
41 | public int getRemotePort() {
42 | return remotePort;
43 | }
44 |
45 | public void setRemotePort(int remotePort) {
46 | this.remotePort = remotePort;
47 | }
48 |
49 | public boolean isDirect_cn() {
50 | return direct_cn;
51 | }
52 |
53 | public void setDirect_cn(boolean direct_cn) {
54 | this.direct_cn = direct_cn;
55 | }
56 |
57 | public int getDownloadSpeed() {
58 | return downloadSpeed;
59 | }
60 |
61 | public void setDownloadSpeed(int downloadSpeed) {
62 | this.downloadSpeed = downloadSpeed;
63 | }
64 |
65 | public int getUploadSpeed() {
66 | return uploadSpeed;
67 | }
68 |
69 | public void setUploadSpeed(int uploadSpeed) {
70 | this.uploadSpeed = uploadSpeed;
71 | }
72 |
73 | public int getSocks5Port() {
74 | return socks5Port;
75 | }
76 |
77 | public void setSocks5Port(int socks5Port) {
78 | this.socks5Port = socks5Port;
79 | }
80 |
81 | public String getRemoteAddress() {
82 | return remoteAddress;
83 | }
84 |
85 | public void setRemoteAddress(String remoteAddress) {
86 | this.remoteAddress = remoteAddress;
87 | }
88 |
89 | public String getProtocal() {
90 | return protocal;
91 | }
92 |
93 | public void setProtocal(String protocal) {
94 | this.protocal = protocal;
95 | }
96 |
97 | public boolean isAutoStart() {
98 | return autoStart;
99 | }
100 |
101 | public void setAutoStart(boolean autoStart) {
102 | this.autoStart = autoStart;
103 | }
104 |
105 | }
106 |
--------------------------------------------------------------------------------
/src/main/java/net/fs/client/FSMain.java:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2015 D1SM.net
2 | package net.fs.client;
3 |
4 | public class FSMain {
5 |
6 | public static void main(String[] args) {
7 | new Client();
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/src/main/java/net/fs/client/LogFrame.java:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2015 D1SM.net
2 | package net.fs.client;
3 |
4 | import java.awt.Insets;
5 | import java.awt.event.ActionEvent;
6 | import java.awt.event.ActionListener;
7 | import javax.swing.JButton;
8 | import javax.swing.JCheckBox;
9 | import javax.swing.JFrame;
10 | import javax.swing.JPanel;
11 | import javax.swing.JScrollBar;
12 | import javax.swing.JScrollPane;
13 | import javax.swing.JTextArea;
14 | import javax.swing.SwingUtilities;
15 | import javax.swing.text.BadLocationException;
16 |
17 | import net.fs.utils.LogListener;
18 | import net.fs.utils.LogOutputStream;
19 |
20 | public class LogFrame extends JFrame implements LogListener{
21 |
22 | private static final long serialVersionUID = 8642892909397273483L;
23 |
24 | Client ui;
25 |
26 | JTextArea logArea;
27 |
28 | JScrollPane scroll;
29 |
30 | boolean autoScroll=true;
31 |
32 | final int SCROLL_BUFFER_SIZE = 1000;
33 |
34 | LogFrame(Client ui){
35 | super("日志");
36 | this.ui=ui;
37 | JPanel panel=(JPanel) getContentPane();
38 |
39 |
40 | logArea=new JTextArea();
41 |
42 | scroll = new JScrollPane(logArea);
43 |
44 | panel.add(scroll,"width :10240:,height :10240: ,wrap");
45 |
46 | JPanel p3=new JPanel();
47 | panel.add(p3,"align center,wrap");
48 |
49 | final JCheckBox cb_lock=new JCheckBox("自动滚动",autoScroll);
50 | p3.add(cb_lock,"align center");
51 | cb_lock.addActionListener(new ActionListener(){
52 |
53 | @Override
54 | public void actionPerformed(ActionEvent e) {
55 | autoScroll=cb_lock.isSelected();
56 | }
57 |
58 | });
59 |
60 | JButton button_clear=createButton("清空");
61 | p3.add(button_clear);
62 | button_clear.addActionListener(new ActionListener() {
63 |
64 | @Override
65 | public void actionPerformed(ActionEvent e) {
66 | logArea.setText("");
67 | }
68 | });
69 |
70 | }
71 |
72 | public void trunkTextArea(JTextArea txtWin){
73 | int numLinesToTrunk = txtWin.getLineCount() - SCROLL_BUFFER_SIZE;
74 | if(numLinesToTrunk > 0)
75 | {
76 | try
77 | {
78 | int posOfLastLineToTrunk = txtWin.getLineEndOffset(numLinesToTrunk - 1);
79 | txtWin.replaceRange("",0,posOfLastLineToTrunk);
80 | }
81 | catch (BadLocationException ex) {
82 | ex.printStackTrace();
83 | }
84 | }
85 | }
86 |
87 | void showText(String text){
88 | logArea.append(text);
89 | trunkTextArea(logArea);
90 | if(autoScroll){
91 | JScrollBar vertical = scroll.getVerticalScrollBar();
92 | vertical.setValue(vertical.getMaximum() );
93 | }
94 | }
95 |
96 | @Override
97 | public void onAppendContent(LogOutputStream los,final String text) {
98 | SwingUtilities.invokeLater(new Runnable() {
99 |
100 | @Override
101 | public void run() {
102 | logArea.append(text);
103 | trunkTextArea(logArea);
104 | if(autoScroll){
105 | logArea.setCaretPosition(logArea.getDocument().getLength());
106 | // JScrollBar vertical = scroll.getVerticalScrollBar();
107 | // vertical.setValue(vertical.getMaximum() );
108 | }
109 | }
110 | });
111 |
112 | }
113 |
114 | JButton createButton(String name){
115 | JButton button=new JButton(name);
116 | button.setMargin(new Insets(0,5,0,5));
117 | button.setFocusPainted(false);
118 | return button;
119 | }
120 |
121 |
122 | }
123 |
--------------------------------------------------------------------------------
/src/main/java/net/fs/client/MapClient.java:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2015 D1SM.net
2 | package net.fs.client;
3 |
4 | import net.fs.rudp.ClientProcessorInterface;
5 | import net.fs.rudp.ConnectionProcessor;
6 | import net.fs.rudp.Route;
7 | import net.fs.rudp.TrafficEvent;
8 | import net.fs.rudp.Trafficlistener;
9 | import net.fs.utils.NetStatus;
10 |
11 | import java.io.BufferedReader;
12 | import java.io.FileOutputStream;
13 | import java.io.IOException;
14 | import java.io.InputStream;
15 | import java.io.InputStreamReader;
16 | import java.net.InetAddress;
17 | import java.net.ServerSocket;
18 | import java.util.HashSet;
19 | import java.util.Random;
20 | import java.util.Set;
21 |
22 | public class MapClient implements Trafficlistener{
23 |
24 | ConnectionProcessor imTunnelProcessor;
25 |
26 | Route route_udp,route_tcp;
27 |
28 | short routePort=45;
29 |
30 | //ClientUII ui;
31 |
32 | String serverAddress="";
33 |
34 | InetAddress address=null;
35 |
36 | int serverPort=130;
37 |
38 | NetStatus netStatus;
39 |
40 | long lastTrafficTime;
41 |
42 | int downloadSum=0;
43 |
44 | int uploadSum=0;
45 |
46 | Thread clientUISpeedUpdateThread;
47 |
48 | int connNum=0;
49 |
50 | Set processTable=new HashSet();
51 |
52 | Object syn_process=new Object();
53 |
54 | static MapClient mapClient;
55 |
56 | PortMapManager portMapManager;
57 |
58 | public String mapdstAddress;
59 |
60 | public int mapdstPort;
61 |
62 | static int monPort=25874;
63 |
64 | String systemName=System.getProperty("os.name").toLowerCase();
65 |
66 | boolean useTcp=true;
67 |
68 | long clientId;
69 |
70 | Random ran=new Random();
71 |
72 | boolean tcpEnable;
73 |
74 | MapClient(Client ui,boolean tcpEnvSuccess) throws Exception {
75 | //this.ui=ui;
76 | mapClient=this;
77 | try {
78 | final ServerSocket socket=new ServerSocket(monPort);
79 | new Thread(){
80 | public void run(){
81 | try {
82 | socket.accept();
83 | } catch (IOException e) {
84 | e.printStackTrace();
85 | System.exit(0);
86 | }
87 | }
88 | }.start();
89 | } catch (Exception e) {
90 | e.printStackTrace();
91 | System.exit(0);
92 | }
93 | try {
94 | route_tcp = new Route(null,routePort,Route.mode_client,true,tcpEnvSuccess);
95 | } catch (Exception e1) {
96 | //e1.printStackTrace();
97 | throw e1;
98 | }
99 | try {
100 | route_udp = new Route(null,routePort,Route.mode_client,false,tcpEnvSuccess);
101 | } catch (Exception e1) {
102 | //e1.printStackTrace();
103 | throw e1;
104 | }
105 | netStatus=new NetStatus();
106 |
107 | portMapManager=new PortMapManager(this);
108 |
109 | clientUISpeedUpdateThread = new Thread() {
110 | public void run() {
111 | while (true) {
112 | try {
113 | Thread.sleep(500);
114 | } catch (InterruptedException e1) {
115 | e1.printStackTrace();
116 | }
117 | updateUISpeed();
118 | }
119 | }
120 | };
121 | clientUISpeedUpdateThread.start();
122 | Route.addTrafficlistener(this);
123 |
124 | }
125 |
126 | public static MapClient get(){
127 | return mapClient;
128 | }
129 |
130 | private void updateUISpeed(){
131 | /*if(ui!=null){
132 | ui.updateUISpeed(connNum,netStatus.getDownSpeed(),netStatus.getUpSpeed());
133 | }*/
134 | }
135 |
136 | public void setMapServer(String serverAddress,int serverPort,int remotePort,String passwordMd5,String password_proxy_Md5,boolean direct_cn,boolean tcp,
137 | String password){
138 | if(this.serverAddress==null
139 | ||!this.serverAddress.equals(serverAddress)
140 | ||this.serverPort!=serverPort){
141 |
142 | if(route_tcp.lastClientControl!=null){
143 | route_tcp.lastClientControl.close();
144 | }
145 |
146 | if(route_udp.lastClientControl!=null){
147 | route_udp.lastClientControl.close();
148 | }
149 |
150 | cleanRule();
151 | if(serverAddress!=null&&!serverAddress.equals("")){
152 | setFireWallRule(serverAddress,serverPort);
153 | }
154 |
155 | }
156 | this.serverAddress=serverAddress;
157 | this.serverPort=serverPort;
158 | address=null;
159 | useTcp=tcp;
160 | resetConnection();
161 | }
162 |
163 |
164 | void setFireWallRule(String serverAddress,int serverPort){
165 | String ip;
166 | try {
167 | ip = InetAddress.getByName(serverAddress).getHostAddress();
168 | /*if(systemName.contains("mac os")){
169 | if(ui.isOsx_fw_pf ()){
170 | String tempPath="./pf.conf";
171 | File f=new File(tempPath);
172 | File d=f.getParentFile();
173 | if(!d.exists()){
174 | d.mkdirs();
175 | }
176 | if(f.exists()){
177 | f.delete();
178 | }
179 | //必须换行结束
180 | String content="block drop quick proto tcp from any to "+ip+" port = "+serverPort+"\n";
181 | saveFile(content.getBytes(), tempPath);
182 |
183 | String cmd1="pfctl -d";
184 | runCommand(cmd1);
185 |
186 | String cmd2="pfctl -Rf "+f.getAbsolutePath();
187 | runCommand(cmd2);
188 |
189 | String cmd3="pfctl -e";
190 | runCommand(cmd3);
191 |
192 | //f.delete();
193 | }else if(ui.isOsx_fw_ipfw()){
194 | String cmd2="sudo ipfw add 5050 deny tcp from any to "+ip+" "+serverAddress+" out";
195 | runCommand(cmd2);
196 | }
197 | }else */
198 | if(systemName.contains("linux")){
199 | String cmd2="iptables -t filter -A OUTPUT -d "+ip+" -p tcp --dport "+serverPort+" -j DROP -m comment --comment tcptun_fs ";
200 | runCommand(cmd2);
201 | }else if (systemName.contains("windows")) {
202 | try {
203 | if(systemName.contains("xp")||systemName.contains("2003")){
204 | 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 ";
205 | final Process p2 = Runtime.getRuntime().exec(cmd_add1,null);
206 | p2.waitFor();
207 | }else {
208 | String cmd_add1="netsh advfirewall firewall add rule name=tcptun_fs protocol=TCP dir=out remoteport="+serverPort+" remoteip="+ip+" action=block ";
209 | final Process p2 = Runtime.getRuntime().exec(cmd_add1,null);
210 | p2.waitFor();
211 | String cmd_add2="netsh advfirewall firewall add rule name=tcptun_fs protocol=TCP dir=in remoteport="+serverPort+" remoteip="+ip+" action=block ";
212 | Process p3 = Runtime.getRuntime().exec(cmd_add2,null);
213 | p3.waitFor();
214 | }
215 | } catch (Exception e1) {
216 | e1.printStackTrace();
217 | }
218 | }
219 | } catch (Exception e) {
220 | e.printStackTrace();
221 | }
222 |
223 | }
224 |
225 | void saveFile(byte[] data,String path) throws Exception{
226 | FileOutputStream fos=null;
227 | try {
228 | fos=new FileOutputStream(path);
229 | fos.write(data);
230 | } catch (Exception e) {
231 | throw e;
232 | } finally {
233 | if(fos!=null){
234 | fos.close();
235 | }
236 | }
237 | }
238 |
239 | void cleanRule(){
240 | if(systemName.contains("mac os")){
241 | cleanTcpTunRule_osx();
242 | }else if(systemName.contains("linux")){
243 | cleanTcpTunRule_linux();
244 | }else {
245 | try {
246 | if(systemName.contains("xp")||systemName.contains("2003")){
247 | String cmd_delete="ipseccmd -p \"tcptun_fs\" -w reg -y";
248 | final Process p1 = Runtime.getRuntime().exec(cmd_delete,null);
249 | p1.waitFor();
250 | }else {
251 | String cmd_delete="netsh advfirewall firewall delete rule name=tcptun_fs ";
252 | final Process p1 = Runtime.getRuntime().exec(cmd_delete,null);
253 | p1.waitFor();
254 | }
255 |
256 | } catch (Exception e) {
257 | e.printStackTrace();
258 | }
259 | }
260 | }
261 |
262 | void cleanTcpTunRule_osx(){
263 | String cmd2="sudo ipfw delete 5050";
264 | runCommand(cmd2);
265 | }
266 |
267 |
268 | void cleanTcpTunRule_linux(){
269 | while(true){
270 | int row=getRow_linux();
271 | if(row>0){
272 | //MLog.println("删除行 "+row);
273 | String cmd="iptables -D OUTPUT "+row;
274 | runCommand(cmd);
275 | }else {
276 | break;
277 | }
278 | }
279 | }
280 |
281 | int getRow_linux(){
282 | int row_delect=-1;
283 | String cme_list_rule="iptables -L -n --line-number";
284 | //String [] cmd={"netsh","advfirewall set allprofiles state on"};
285 | Thread errorReadThread=null;
286 | try {
287 | final Process p = Runtime.getRuntime().exec(cme_list_rule,null);
288 |
289 | errorReadThread=new Thread(){
290 | public void run(){
291 | InputStream is=p.getErrorStream();
292 | BufferedReader localBufferedReader = new BufferedReader(new InputStreamReader(is));
293 | while (true){
294 | String line;
295 | try {
296 | line = localBufferedReader.readLine();
297 | if (line == null){
298 | break;
299 | }else{
300 | //System.out.println("erroraaa "+line);
301 | }
302 | } catch (IOException e) {
303 | e.printStackTrace();
304 | //error();
305 | break;
306 | }
307 | }
308 | }
309 | };
310 | errorReadThread.start();
311 |
312 |
313 |
314 | InputStream is=p.getInputStream();
315 | BufferedReader localBufferedReader = new BufferedReader(new InputStreamReader(is));
316 | while (true){
317 | String line;
318 | try {
319 | line = localBufferedReader.readLine();
320 | // System.out.println("standaaa "+line);
321 | if (line == null){
322 | break;
323 | }else{
324 | if(line.contains("tcptun_fs")){
325 | int index=line.indexOf(" ");
326 | if(index>0){
327 | String n=line.substring(0, index);
328 | try {
329 | if(row_delect<0){
330 | //System.out.println("standaaabbb "+line);
331 | row_delect=Integer.parseInt(n);
332 | }
333 | } catch (Exception e) {
334 |
335 | }
336 | }
337 | };
338 | }
339 | } catch (IOException e) {
340 | e.printStackTrace();
341 | break;
342 | }
343 | }
344 |
345 |
346 | errorReadThread.join();
347 | p.waitFor();
348 | } catch (Exception e) {
349 | e.printStackTrace();
350 | //error();
351 | }
352 | return row_delect;
353 | }
354 |
355 | void resetConnection(){
356 | synchronized (syn_process) {
357 |
358 | }
359 | }
360 |
361 | public void onProcessClose(ClientProcessorInterface process){
362 | synchronized (syn_process) {
363 | processTable.remove(process);
364 | }
365 | }
366 |
367 | synchronized public void closeAndTryConnect_Login(boolean testSpeed){
368 | close();
369 | /*boolean loginOK=ui.login();
370 | if(loginOK){
371 | ui.updateNode(testSpeed);
372 | //testPool();
373 | }*/
374 | }
375 |
376 | synchronized public void closeAndTryConnect(){
377 | close();
378 | //testPool();
379 | }
380 |
381 | public void close(){
382 | //closeAllProxyRequest();
383 | //poolManage.close();
384 | //CSocketPool.closeAll();
385 | }
386 |
387 | public void trafficDownload(TrafficEvent event) {
388 | ////#MLog.println("下载 "+event.getTraffic());
389 | netStatus.addDownload(event.getTraffic());
390 | lastTrafficTime=System.currentTimeMillis();
391 | downloadSum+=event.getTraffic();
392 | }
393 |
394 | public void trafficUpload(TrafficEvent event) {
395 | ////#MLog.println("上传 "+event.getTraffic());
396 | netStatus.addUpload(event.getTraffic());
397 | lastTrafficTime=System.currentTimeMillis();
398 | uploadSum+=event.getTraffic();
399 | }
400 |
401 | static void runCommand(String command){
402 | Thread standReadThread=null;
403 | Thread errorReadThread=null;
404 | try {
405 | final Process p = Runtime.getRuntime().exec(command,null);
406 | standReadThread=new Thread(){
407 | public void run(){
408 | InputStream is=p.getInputStream();
409 | BufferedReader localBufferedReader = new BufferedReader(new InputStreamReader(is));
410 | while (true){
411 | String line;
412 | try {
413 | line = localBufferedReader.readLine();
414 | //System.out.println("stand "+line);
415 | if (line == null){
416 | break;
417 | }
418 | } catch (IOException e) {
419 | e.printStackTrace();
420 | break;
421 | }
422 | }
423 | }
424 | };
425 | standReadThread.start();
426 |
427 | errorReadThread=new Thread(){
428 | public void run(){
429 | InputStream is=p.getErrorStream();
430 | BufferedReader localBufferedReader = new BufferedReader(new InputStreamReader(is));
431 | while (true){
432 | String line;
433 | try {
434 | line = localBufferedReader.readLine();
435 | if (line == null){
436 | break;
437 | }else{
438 | //System.out.println("error "+line);
439 | }
440 | } catch (IOException e) {
441 | e.printStackTrace();
442 | //error();
443 | break;
444 | }
445 | }
446 | }
447 | };
448 | errorReadThread.start();
449 | standReadThread.join();
450 | errorReadThread.join();
451 | p.waitFor();
452 | } catch (Exception e) {
453 | e.printStackTrace();
454 | //error();
455 | }
456 | }
457 |
458 | public boolean isUseTcp() {
459 | return useTcp;
460 | }
461 |
462 | public void setUseTcp(boolean useTcp) {
463 | this.useTcp = useTcp;
464 | }
465 |
466 |
467 | }
468 |
--------------------------------------------------------------------------------
/src/main/java/net/fs/client/MapRule.java:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2015 D1SM.net
2 | package net.fs.client;
3 |
4 | import java.io.Serializable;
5 | import java.net.ServerSocket;
6 |
7 | public class MapRule implements Serializable{
8 |
9 | /**
10 | *
11 | */
12 | private static final long serialVersionUID = -3504577683070928480L;
13 |
14 | int listen_port;
15 |
16 | int dst_port;
17 |
18 | String name;
19 |
20 | boolean using=false;
21 |
22 | ServerSocket serverSocket;
23 |
24 | public int getListen_port() {
25 | return listen_port;
26 | }
27 |
28 | public void setListen_port(int listen_port) {
29 | this.listen_port = listen_port;
30 | }
31 |
32 | public int getDst_port() {
33 | return dst_port;
34 | }
35 |
36 | public void setDst_port(int dst_port) {
37 | this.dst_port = dst_port;
38 | }
39 |
40 | public String getName() {
41 | return name;
42 | }
43 |
44 | public void setName(String name) {
45 | this.name = name;
46 | }
47 |
48 | }
49 |
--------------------------------------------------------------------------------
/src/main/java/net/fs/client/MapRuleListModel.java:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2015 D1SM.net
2 | package net.fs.client;
3 |
4 | import java.util.ArrayList;
5 | import java.util.List;
6 |
7 | import javax.swing.table.AbstractTableModel;
8 |
9 |
10 | public class MapRuleListModel extends AbstractTableModel{
11 |
12 | private static final long serialVersionUID = 2267856423317178816L;
13 |
14 | private List mapRuleList;
15 |
16 | String titles[] ;
17 |
18 | Class> types[] = new Class[] {String.class, String.class, String.class,String.class, String.class, String.class};
19 |
20 | MapRuleListModel(){
21 | mapRuleList=new ArrayList ();
22 | titles = new String[] {""};
23 | }
24 |
25 | public void setMapRuleList(List list){
26 | mapRuleList.clear();
27 | if(list!=null){
28 | mapRuleList.addAll(list);
29 | }
30 | fireTableDataChanged();
31 | }
32 |
33 | public int getMapRuleIndex(String name){
34 | int index=-1;
35 | int i=0;
36 | for(MapRule r:mapRuleList){
37 | if(name.equals(r.getName())){
38 | index=i;
39 | break;
40 | }
41 | i++;
42 | }
43 | return index;
44 | }
45 |
46 | List getMapRuleList(){
47 | return mapRuleList;
48 | }
49 |
50 | public MapRule getMapRuleAt(int row){
51 | if(row>-1&row getColumnClass(int c) {
80 | return types[c];
81 | }
82 |
83 |
84 | public boolean isCellEditable(int row, int col) {
85 | boolean b=false;
86 | if(col==0){
87 | b=true;
88 | }
89 | return false;
90 | }
91 | }
92 |
--------------------------------------------------------------------------------
/src/main/java/net/fs/client/Pipe.java:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2015 D1SM.net
2 | package net.fs.client;
3 |
4 | import net.fs.rudp.ConnectionUDP;
5 | import net.fs.rudp.UDPInputStream;
6 | import net.fs.rudp.UDPOutputStream;
7 | import net.fs.utils.MLog;
8 |
9 | import java.io.InputStream;
10 | import java.io.OutputStream;
11 |
12 | public class Pipe {
13 |
14 |
15 | int lastTime=-1;
16 |
17 |
18 | boolean readed=false;
19 |
20 | public Pipe p2;
21 |
22 | byte[] pv;
23 |
24 | int pvl;
25 |
26 | int readedLength;
27 |
28 | String successMessage;
29 |
30 | int dstPort=-1;
31 |
32 | public void pipe(InputStream is,UDPOutputStream tos,int initSpeed,final Pipe p2) throws Exception{
33 |
34 | int len=0;
35 | byte[] buf=new byte[100*1024];
36 | boolean sendeda=false;
37 | while((len=is.read(buf))>0){
38 | readed=true;
39 | if(!sendeda){
40 | sendeda=true;
41 | }
42 | tos.write(buf, 0, len);
43 | }
44 | }
45 |
46 |
47 |
48 | void sendSleep(long startTime,int speed,int length){
49 | long needTime=(long) (1000f*length/speed);
50 | long usedTime=System.currentTimeMillis()-startTime;
51 | if(usedTime0){
69 | readedLength+=len;
70 | if(!sendedb){
71 | pv=buf;
72 | pvl=len;
73 | sendedb=true;
74 | }
75 | if(dstPort>0){
76 | if(Client.ui!=null){
77 | if(!msged){
78 | msged=true;
79 | String msg="端口"+dstPort+"连接成功";
80 | MLog.println(msg);
81 | }
82 |
83 | }
84 | }
85 | os.write(buf, 0, len);
86 | if(!sended){
87 | sended=true;
88 | }
89 | }
90 | }
91 |
92 |
93 |
94 | public int getReadedLength() {
95 | return readedLength;
96 | }
97 |
98 |
99 |
100 | public void setDstPort(int dstPort) {
101 | this.dstPort = dstPort;
102 | }
103 |
104 | }
105 |
--------------------------------------------------------------------------------
/src/main/java/net/fs/client/PortMapManager.java:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2015 D1SM.net
2 | package net.fs.client;
3 |
4 | import java.io.DataInputStream;
5 | import java.io.File;
6 | import java.io.FileInputStream;
7 | import java.io.FileOutputStream;
8 | import java.io.IOException;
9 | import java.io.UnsupportedEncodingException;
10 | import java.net.ServerSocket;
11 | import java.net.Socket;
12 | import java.util.ArrayList;
13 | import java.util.HashMap;
14 | import java.util.Map;
15 |
16 | import com.alibaba.fastjson.JSONArray;
17 | import com.alibaba.fastjson.JSONObject;
18 | import net.fs.rudp.Route;
19 |
20 | public class PortMapManager {
21 |
22 | MapClient mapClient;
23 |
24 | ArrayList mapList=new ArrayList();
25 |
26 | Map mapRuleTable=new HashMap();
27 |
28 | String configFilePath="port_map.json";
29 |
30 | PortMapManager(MapClient mapClient){
31 | this.mapClient=mapClient;
32 | //listenPort();
33 | loadMapRule();
34 | }
35 |
36 | void addMapRule(MapRule mapRule) throws Exception{
37 | if(getMapRule(mapRule.name)!=null){
38 | throw new Exception("映射 "+mapRule.name+" 已存在,请修改名称!");
39 | }
40 | ServerSocket serverSocket=null;
41 | try {
42 | serverSocket = new ServerSocket(mapRule.getListen_port());
43 | listen(serverSocket);
44 | mapList.add(mapRule);
45 | mapRuleTable.put(mapRule.listen_port, mapRule);
46 | saveMapRule();
47 | } catch (IOException e2) {
48 | //e2.printStackTrace();
49 | throw new Exception("端口 "+mapRule.getListen_port()+" 已经被占用!");
50 | }finally{
51 | if(serverSocket!=null){
52 | serverSocket.close();
53 | }
54 | }
55 | }
56 |
57 | void removeMapRule(String name){
58 | MapRule mapRule=getMapRule(name);
59 | if(mapRule!=null){
60 | mapList.remove(mapRule);
61 | mapRuleTable.remove(mapRule.listen_port);
62 | if(mapRule.serverSocket!=null){
63 | try {
64 | mapRule.serverSocket.close();
65 | } catch (IOException e) {
66 | e.printStackTrace();
67 | }
68 | }
69 | try {
70 | saveMapRule();
71 | } catch (Exception e) {
72 | e.printStackTrace();
73 | }
74 | }
75 | }
76 |
77 | void updateMapRule(MapRule mapRule_origin,MapRule mapRule_new) throws Exception{
78 | if(getMapRule(mapRule_new.name)!=null&&!mapRule_origin.name.equals(mapRule_new.name)){
79 | throw new Exception("映射 "+mapRule_new.name+" 已存在,请修改名称!");
80 | }
81 | ServerSocket serverSocket=null;
82 | if(mapRule_origin.listen_port!=mapRule_new.listen_port){
83 | try {
84 | serverSocket = new ServerSocket(mapRule_new.getListen_port());
85 | listen(serverSocket);
86 | mapRule_origin.using=false;
87 | if(mapRule_origin.serverSocket!=null){
88 | mapRule_origin.serverSocket.close();
89 | }
90 | mapRule_origin.serverSocket=serverSocket;
91 | mapRuleTable.remove(mapRule_origin.listen_port);
92 | mapRuleTable.put(mapRule_new.listen_port, mapRule_new);
93 | } catch (IOException e2) {
94 | //e2.printStackTrace();
95 | throw new Exception("端口 "+mapRule_new.getListen_port()+" 已经被占用!");
96 | }finally{
97 | // if(serverSocket!=null){
98 | // serverSocket.close();
99 | // }
100 | }
101 | }
102 | mapRule_origin.name=mapRule_new.name;
103 | mapRule_origin.listen_port=mapRule_new.listen_port;
104 | mapRule_origin.dst_port=mapRule_new.dst_port;
105 | saveMapRule();
106 |
107 | }
108 |
109 | void saveMapRule() throws Exception{
110 | JSONObject json=new JSONObject();
111 | JSONArray json_map_list=new JSONArray();
112 | json.put("map_list", json_map_list);
113 | if(mapList.size()==0){
114 |
115 | }
116 | for(MapRule r:mapList){
117 | JSONObject json_rule=new JSONObject();
118 | json_rule.put("name", r.name);
119 | json_rule.put("listen_port", r.listen_port);
120 | json_rule.put("dst_port", r.dst_port);
121 | json_map_list.add(json_rule);
122 | }
123 | try {
124 | saveFile(json.toJSONString().getBytes("utf-8"), configFilePath);
125 | } catch (UnsupportedEncodingException e) {
126 | e.printStackTrace();
127 | } catch (Exception e) {
128 | e.printStackTrace();
129 | throw new Exception("保存失败!");
130 | }
131 | }
132 |
133 | void loadMapRule(){
134 | String content;
135 | JSONObject json=null;
136 | try {
137 | content = readFileUtf8(configFilePath);
138 | json=JSONObject.parseObject(content);
139 | } catch (Exception e) {
140 | //e.printStackTrace();
141 | }
142 | if(json!=null&&json.containsKey("map_list")){
143 | JSONArray json_map_list=json.getJSONArray("map_list");
144 | for(int i=0;i getMapList() {
178 | return mapList;
179 | }
180 |
181 | public void setMapList(ArrayList mapList) {
182 | this.mapList = mapList;
183 | }
184 |
185 | void listen(final ServerSocket serverSocket){
186 | Route.es.execute(new Runnable() {
187 |
188 | @Override
189 | public void run() {
190 | while(true){
191 | try {
192 | final Socket socket=serverSocket.accept();
193 | Route.es.execute(new Runnable() {
194 |
195 | @Override
196 | public void run() {
197 | int listenPort=serverSocket.getLocalPort();
198 | MapRule mapRule=mapRuleTable.get(listenPort);
199 | if(mapRule!=null){
200 | Route route=null;
201 | if(mapClient.isUseTcp()){
202 | route=mapClient.route_tcp;
203 | }else {
204 | route=mapClient.route_udp;
205 | }
206 | PortMapProcess process=new PortMapProcess(mapClient,route, socket,mapClient.serverAddress,mapClient.serverPort,null,
207 | null,mapRule.dst_port);
208 | }
209 | }
210 |
211 | });
212 |
213 | } catch (IOException e) {
214 | e.printStackTrace();
215 | break;
216 | }
217 | }
218 | }
219 | });
220 | }
221 |
222 | void saveFile(byte[] data,String path) throws Exception{
223 | FileOutputStream fos=null;
224 | try {
225 | fos=new FileOutputStream(path);
226 | fos.write(data);
227 | } catch (Exception e) {
228 | throw e;
229 | } finally {
230 | if(fos!=null){
231 | fos.close();
232 | }
233 | }
234 | }
235 |
236 | public static String readFileUtf8(String path) throws Exception{
237 | String str=null;
238 | FileInputStream fis=null;
239 | DataInputStream dis=null;
240 | try {
241 | File file=new File(path);
242 |
243 | int length=(int) file.length();
244 | byte[] data=new byte[length];
245 |
246 | fis=new FileInputStream(file);
247 | dis=new DataInputStream(fis);
248 | dis.readFully(data);
249 | str=new String(data,"utf-8");
250 |
251 | } catch (Exception e) {
252 | //e.printStackTrace();
253 | throw e;
254 | }finally{
255 | if(fis!=null){
256 | try {
257 | fis.close();
258 | } catch (IOException e) {
259 | e.printStackTrace();
260 | }
261 | }
262 | if(dis!=null){
263 | try {
264 | dis.close();
265 | } catch (IOException e) {
266 | e.printStackTrace();
267 | }
268 | }
269 | }
270 |
271 | return str;
272 | }
273 | }
274 |
--------------------------------------------------------------------------------
/src/main/java/net/fs/client/PortMapProcess.java:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2015 D1SM.net
2 | package net.fs.client;
3 |
4 | import java.io.DataInputStream;
5 | import java.io.DataOutputStream;
6 | import java.io.IOException;
7 | import java.net.Socket;
8 | import java.util.Random;
9 |
10 | import com.alibaba.fastjson.JSONObject;
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 | import net.fs.utils.MLog;
18 |
19 | public class PortMapProcess implements ClientProcessorInterface{
20 |
21 | Random ran=new Random();
22 |
23 | UDPInputStream tis;
24 |
25 | UDPOutputStream tos;
26 |
27 | String serverAddress="";
28 |
29 | int serverPort;
30 |
31 | ConnectionUDP conn;
32 |
33 | MapClient mapClient;
34 |
35 | public Socket srcSocket,dstSocket;
36 |
37 | DataInputStream srcIs=null;
38 | DataOutputStream srcOs=null;
39 |
40 | boolean closed=false;
41 | boolean success=false;
42 |
43 | public PortMapProcess(MapClient mapClient,Route route,final Socket srcSocket,String serverAddress2,int serverPort2,String password_proxy_md5,
44 | String dstAddress,final int dstPort){
45 | this.mapClient=mapClient;
46 | this.serverAddress=serverAddress2;
47 | this.serverPort=serverPort2;
48 |
49 | this.srcSocket=srcSocket;
50 |
51 | try {
52 | srcIs = new DataInputStream(srcSocket.getInputStream());
53 | srcOs=new DataOutputStream(srcSocket.getOutputStream());
54 | conn = route.getConnection(serverAddress, serverPort,null);
55 | tis=conn.uis;
56 | tos=conn.uos;
57 |
58 | JSONObject requestJson=new JSONObject();
59 | requestJson.put("dst_address", dstAddress);
60 | requestJson.put("dst_port", dstPort);
61 | byte[] requestData=requestJson.toJSONString().getBytes("utf-8");
62 |
63 | tos.write(requestData, 0, requestData.length);
64 |
65 |
66 | final Pipe p1=new Pipe();
67 | final Pipe p2=new Pipe();
68 |
69 |
70 | byte[] responeData=tis.read2();
71 |
72 | String hs=new String(responeData,"utf-8");
73 | JSONObject responeJSon=JSONObject.parseObject(hs);
74 | int code=responeJSon.getIntValue("code");
75 | String message=responeJSon.getString("message");
76 | String uimessage="";
77 | if(code==Constant.CODE_SUCCESS){
78 |
79 | Route.es.execute(new Runnable() {
80 |
81 | @Override
82 | public void run() {
83 | long t=System.currentTimeMillis();
84 | p2.setDstPort(dstPort);
85 | try {
86 | p2.pipe(tis, srcOs,1024*1024*1024,null);
87 | }catch (Exception e) {
88 | e.printStackTrace();
89 | }finally{
90 | close();
91 | if(p2.getReadedLength()==0){
92 | //String msg="fs服务连接成功,加速端口"+dstPort+"连接失败1";
93 | String msg="端口"+dstPort+"无返回数据";
94 | MLog.println(msg);
95 | }
96 | }
97 | }
98 |
99 | });
100 |
101 | Route.es.execute(new Runnable() {
102 |
103 | @Override
104 | public void run() {
105 | try {
106 | p1.pipe(srcIs, tos,200*1024,p2);
107 | } catch (Exception e) {
108 | //e.printStackTrace();
109 | }finally{
110 | close();
111 | }
112 | }
113 |
114 | });
115 | success=true;
116 | uimessage=("fs服务连接成功");
117 | }else {
118 | close();
119 | uimessage="fs服务连接成功,端口"+dstPort+"连接失败2";
120 | MLog.println(uimessage);
121 | }
122 | } catch (Exception e1) {
123 | e1.printStackTrace();
124 | String msg="fs服务连接失败!";
125 | MLog.println(msg);
126 | }
127 |
128 | }
129 |
130 | void close(){
131 | if(!closed){
132 | closed=true;
133 | if(srcIs!=null){
134 | try {
135 | srcIs.close();
136 | } catch (IOException e) {
137 | e.printStackTrace();
138 | }
139 | }
140 | if(srcOs!=null){
141 | try {
142 | srcOs.close();
143 | } catch (IOException e) {
144 | e.printStackTrace();
145 | }
146 | }
147 | if(tos!=null){
148 | tos.closeStream_Local();
149 | }
150 | if(tis!=null){
151 | tis.closeStream_Local();
152 | }
153 | if(conn!=null){
154 | conn.close_local();
155 | }
156 | if(srcSocket!=null){
157 | try {
158 | srcSocket.close();
159 | } catch (IOException e) {
160 | e.printStackTrace();
161 | }
162 | }
163 | mapClient.onProcessClose(this);
164 |
165 | }
166 | }
167 |
168 | @Override
169 | public void onMapClientClose() {
170 | try {
171 | srcSocket.close();
172 | } catch (IOException e) {
173 | e.printStackTrace();
174 | }
175 | }
176 | }
177 |
--------------------------------------------------------------------------------
/src/main/java/net/fs/rudp/AckListManage.java:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2015 D1SM.net
2 | package net.fs.rudp;
3 |
4 | import java.util.HashMap;
5 | import java.util.Iterator;
6 | import java.util.Map;
7 |
8 | public class AckListManage implements Runnable{
9 | Thread mainThread;
10 | Map 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/main/java/net/fs/rudp/AckListTask.java:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2015 D1SM.net
2 | package net.fs.rudp;
3 |
4 | import java.util.ArrayList;
5 | import java.util.HashSet;
6 | import java.util.List;
7 | import java.util.Set;
8 |
9 | import net.fs.rudp.message.AckListMessage;
10 |
11 |
12 | public class AckListTask {
13 | ConnectionUDP conn;
14 | AckListMessage alm;
15 | int lastRead=0;
16 | ArrayList ackList;
17 | @SuppressWarnings("unchecked")
18 | Set 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,List 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 | Map 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 Map 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/main/java/net/fs/rudp/ClientManager.java:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2015 D1SM.net
2 | package net.fs.rudp;
3 |
4 | import java.net.InetAddress;
5 | import java.util.Date;
6 | import java.util.HashMap;
7 | import java.util.Iterator;
8 | import java.util.Map;
9 |
10 | import net.fs.utils.MLog;
11 |
12 |
13 | public class ClientManager {
14 |
15 | Map 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/main/java/net/fs/rudp/ClientProcessorInterface.java:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2015 D1SM.net
2 | package net.fs.rudp;
3 |
4 | public interface ClientProcessorInterface {
5 |
6 | public void onMapClientClose();
7 |
8 | }
9 |
--------------------------------------------------------------------------------
/src/main/java/net/fs/rudp/ConnInfo.java:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2015 D1SM.net
2 | package net.fs.rudp;
3 |
4 | import net.fs.rudp.StreamPipe.HttpHost;
5 |
6 | public class ConnInfo {
7 |
8 |
9 | String requestHost=null;
10 |
11 | String requestPath=null;
12 |
13 | boolean http=false;
14 |
15 | HttpHost host=null;
16 |
17 | public String getRequestHost() {
18 | return requestHost;
19 | }
20 |
21 | public void setRequestHost(String requestHost) {
22 | this.requestHost = requestHost;
23 | }
24 |
25 | public String getRequestPath() {
26 | return requestPath;
27 | }
28 |
29 | public void setRequestPath(String requestPath) {
30 | this.requestPath = requestPath;
31 | }
32 |
33 | public boolean isHttp() {
34 | return http;
35 | }
36 |
37 | public void setHttp(boolean http) {
38 | this.http = http;
39 | }
40 |
41 | public HttpHost getHost() {
42 | return host;
43 | }
44 |
45 | public void setHost(HttpHost host) {
46 | this.host = host;
47 | }
48 |
49 | }
50 |
--------------------------------------------------------------------------------
/src/main/java/net/fs/rudp/ConnectException.java:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2015 D1SM.net
2 | package net.fs.rudp;
3 |
4 | public class ConnectException extends Exception{
5 |
6 | private static final long serialVersionUID = 8735513900170495107L;
7 | String message;
8 | ConnectException(String message){
9 | this.message=message;
10 | }
11 | @Override
12 | public void printStackTrace(){
13 | //#MLog.println("连接异常 "+message);
14 | }
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/src/main/java/net/fs/rudp/ConnectionProcessor.java:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2015 D1SM.net
2 | package net.fs.rudp;
3 |
4 |
5 |
6 | public interface ConnectionProcessor {
7 | abstract void process(final ConnectionUDP conn);
8 | }
9 |
--------------------------------------------------------------------------------
/src/main/java/net/fs/rudp/ConnectionUDP.java:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2015 D1SM.net
2 | package net.fs.rudp;
3 | import java.net.DatagramPacket;
4 | import java.net.InetAddress;
5 | import java.util.Random;
6 | import java.util.concurrent.LinkedBlockingQueue;
7 |
8 | public class ConnectionUDP {
9 | public InetAddress dstIp;
10 | public int dstPort;
11 | public Sender sender;
12 | public Receiver receiver;
13 | public UDPOutputStream uos;
14 | public UDPInputStream uis;
15 | long connetionId;
16 | Route route;
17 | int mode;
18 | private boolean connected=true;
19 | long lastLiveTime=System.currentTimeMillis();
20 | long lastSendLiveTime=0;
21 |
22 | static Random ran=new Random();
23 |
24 | int connectId;
25 |
26 | ConnectionProcessor connectionProcessor;
27 |
28 | private LinkedBlockingQueue dpBuffer=new LinkedBlockingQueue();
29 |
30 | public ClientControl clientControl;
31 |
32 | public boolean localClosed=false,remoteClosed=false,destroied=false;
33 |
34 | public boolean stopnow=false;
35 |
36 | public ConnectionUDP(Route ro,InetAddress dstIp,int dstPort,int mode,int connectId,ClientControl clientControl) throws Exception {
37 | this.clientControl=clientControl;
38 | this.route=ro;
39 | this.dstIp=dstIp;
40 | this.dstPort=dstPort;
41 | this.mode=mode;
42 | if(mode==1){
43 | //MLog.println(" 发起连接RUDP "+dstIp+":"+dstPort+" connectId "+connectId);
44 | }else if(mode==2){
45 |
46 | //MLog.println(" 接受连接RUDP "+dstIp+":"+dstPort+" connectId "+connectId);
47 | }
48 | this.connectId=connectId;
49 | try {
50 | sender=new Sender(this);
51 | receiver=new Receiver(this);
52 | uos=new UDPOutputStream (this);
53 | uis=new UDPInputStream(this);
54 | if(mode==2){
55 | ro.createTunnelProcessor().process(this);
56 | }
57 | } catch (Exception e) {
58 | e.printStackTrace();
59 | connected=false;
60 | route.connTable.remove(connectId);
61 | e.printStackTrace();
62 | //#MLog.println(" 连接失败RUDP "+connectId);
63 | synchronized(this){
64 | notifyAll();
65 | }
66 | throw e;
67 | }
68 | //#MLog.println(" 连接成功RUDP "+connectId);
69 | synchronized(this){
70 | notifyAll();
71 | }
72 | }
73 |
74 | public DatagramPacket getPacket(int connectId) throws InterruptedException{
75 | DatagramPacket dp=(DatagramPacket)dpBuffer.take();
76 | return dp;
77 | }
78 |
79 | @Override
80 | public String toString(){
81 | return new String(dstIp+":"+dstPort);
82 | }
83 |
84 | public boolean isConnected(){
85 | return connected;
86 | }
87 |
88 | public void close_local(){
89 | if(!localClosed){
90 | localClosed=true;
91 | if(!stopnow){
92 | sender.sendCloseMessage_Conn();
93 | }
94 | destroy(false);
95 | }
96 | }
97 |
98 | public void close_remote() {
99 | if(!remoteClosed){
100 | remoteClosed=true;
101 | destroy(false);
102 | }
103 | }
104 |
105 | //完全关闭
106 | public void destroy(boolean force){
107 | if(!destroied){
108 | if((localClosed&&remoteClosed)||force){
109 | destroied=true;
110 | connected=false;
111 | uis.closeStream_Local();
112 | uos.closeStream_Local();
113 | sender.destroy();
114 | receiver.destroy();
115 | route.removeConnection(this);
116 | clientControl.removeConnection(this);
117 | }
118 | }
119 | }
120 |
121 | public void close_timeout(){
122 | ////#MLog.println("超时关闭RDP连接");
123 | }
124 |
125 | void live(){
126 | lastLiveTime=System.currentTimeMillis();
127 | }
128 | }
129 |
--------------------------------------------------------------------------------
/src/main/java/net/fs/rudp/Constant.java:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2015 D1SM.net
2 | package net.fs.rudp;
3 |
4 | public class Constant {
5 |
6 |
7 | public static final int CODE_SUCCESS =1;
8 |
9 | public static final int CODE_FAILED =0;
10 |
11 | public static final int CODE_NO_PORT =41;
12 |
13 | public static final int CODE_PASSWORD_ERROR =42;
14 |
15 | static final int PROTOCAL_PORTMAP =5755682;
16 |
17 | public static final int PROTOCAL_SOCKS_5_PROXY =544643;
18 |
19 | }
20 |
--------------------------------------------------------------------------------
/src/main/java/net/fs/rudp/CopiedIterator.java:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2015 D1SM.net
2 | package net.fs.rudp;
3 |
4 | import java.util.Iterator;
5 | import java.util.LinkedList;
6 |
7 | public class CopiedIterator implements Iterator {
8 | private Iterator iterator = null;
9 | public CopiedIterator(Iterator itr) {
10 | LinkedList list = new LinkedList( );
11 | while(itr.hasNext( )) {
12 | list.add(itr.next( ));
13 | }
14 | this.iterator = list.iterator( );
15 | }
16 | public boolean hasNext( ) {
17 | return this.iterator.hasNext( );
18 | }
19 | public void remove( ) {
20 | throw new UnsupportedOperationException("This is a read-only iterator.");
21 | }
22 | public Object next( ) {
23 | return this.iterator.next( );
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/src/main/java/net/fs/rudp/MapSocketPorcessor.java:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2015 D1SM.net
2 | package net.fs.rudp;
3 |
4 | import java.io.DataInputStream;
5 | import java.io.DataOutputStream;
6 | import java.io.IOException;
7 | import java.net.Socket;
8 | import java.util.ArrayList;
9 | import java.util.Random;
10 | import java.util.concurrent.ExecutorService;
11 | import java.util.concurrent.Executors;
12 |
13 |
14 | public class MapSocketPorcessor implements PipeListener{
15 |
16 |
17 | Socket srcSocket;
18 | Socket dstSocket;
19 |
20 | public DataInputStream srcIs;
21 | public DataOutputStream dstOs;
22 | public DataInputStream dstIs;
23 | public DataOutputStream srcOs;
24 |
25 | Object srcReadOb=new Object();
26 | Object dstReadOb=new Object();
27 | Object dstWriteOb=new Object();
28 | Object srcWriteOb=new Object();
29 |
30 | ArrayList srcReadBuffer=new ArrayList();
31 | ArrayList dstReadBuffer=new ArrayList();
32 |
33 | Thread srcReadThread;
34 | Thread dstWriteThread;
35 | Thread srcWriteThread;
36 | Thread dstReadThread;
37 | byte[] srcPreRead=new byte[0];
38 |
39 | int maxDstRead=1;
40 | int maxSrcRead=1;
41 |
42 | boolean isSuperSocket=false;
43 |
44 | boolean dstReadComplete=false;
45 |
46 | boolean srcReadComplete=false;
47 |
48 | boolean srcWriteComplete=false;
49 |
50 | boolean dstWriteComplete=false;
51 |
52 | boolean dstClosed=false;
53 |
54 | boolean srcClosed=false;
55 |
56 | String st=" ";
57 |
58 |
59 | String ss="";
60 |
61 | static int n=0;
62 |
63 | Random ran=new Random();
64 |
65 | long id;
66 |
67 | static int m=0,a,b;
68 |
69 | boolean closed=false;
70 |
71 | long lastActiveTime=System.currentTimeMillis();
72 |
73 | //static HashMap procTable=new HashMap();
74 |
75 | static ExecutorService es;
76 |
77 | MapSocketPorcessor mp;
78 |
79 | Socket socketA,socketB;
80 |
81 | int supserSocketId=-1;
82 |
83 | String requestHost=null;
84 |
85 | static {
86 | es=Executors.newCachedThreadPool();
87 | }
88 |
89 | public MapSocketPorcessor(){
90 |
91 | }
92 |
93 | public void setDstSocket(Socket dstSocket){
94 | this.dstSocket=dstSocket;
95 | }
96 |
97 | public void setId(long id){
98 | this.id=id;
99 | }
100 |
101 | public boolean isClosed(){
102 | return closed;
103 | }
104 |
105 | public long getLastActiveTime(){
106 | return lastActiveTime;
107 | }
108 |
109 | void active(){
110 | lastActiveTime=System.currentTimeMillis();
111 | }
112 |
113 | public long getId(){
114 | return id;
115 | }
116 |
117 | public void closeAll(){
118 | closeAll(true);
119 | }
120 |
121 | public void closeAll(boolean closeDst){
122 | //procTable.remove(id);
123 | //Log.println("closeAll AAAAAAAAA");
124 | if(!closed){
125 | //Log.println("closeAll BBBBBBBBBB");
126 | closed=true;
127 | //#MLog.println("MapSocketPorcessor Close");
128 | try {
129 | srcSocket.close();
130 | } catch (IOException e) {
131 | e.printStackTrace();
132 | }
133 | if(closeDst){
134 | try {
135 | dstSocket.close();
136 | } catch (IOException e) {
137 | e.printStackTrace();
138 | }
139 | }
140 | }
141 | }
142 |
143 | void tryClose(){
144 | closeAll();
145 | }
146 |
147 | public void start(){
148 | Runnable t=new Runnable(){
149 | public void run(){
150 | try {
151 | ConnInfo connInfo=new ConnInfo();
152 | StreamPipe p1=new StreamPipe(connInfo,srcIs,dstOs,10*1024,1000*1024);
153 | StreamPipe p2=new StreamPipe(connInfo,dstIs,srcOs,10*1024,1000*1024);
154 | p1.setType(StreamPipe.type_request);
155 | //p1.addListener(mp);
156 | //p2.addListener(mp);
157 | p1.setSocketA(socketA);
158 | p1.setSocketB(socketB);
159 | p2.setType(StreamPipe.type_respone);
160 | p2.setSocketA(socketA);
161 | p2.setSocketB(socketB);
162 | p1.setSupserSocketId(supserSocketId);
163 | p2.setSupserSocketId(supserSocketId);
164 | } catch (Exception e1) {
165 | e1.printStackTrace();
166 | }
167 | }
168 | };
169 | es.execute(t);
170 | }
171 |
172 | public void pipeClose() {
173 | //closeAll();
174 |
175 | }
176 |
177 | public Socket getSocketA() {
178 | return socketA;
179 | }
180 |
181 | public void setSocketA(Socket socketA) {
182 | this.socketA = socketA;
183 | }
184 |
185 | public Socket getSocketB() {
186 | return socketB;
187 | }
188 |
189 | public void setSocketB(Socket socketB) {
190 | this.socketB = socketB;
191 | }
192 |
193 | public int getSupserSocketId() {
194 | return supserSocketId;
195 | }
196 |
197 | public void setSupserSocketId(int supserSocketId) {
198 | this.supserSocketId = supserSocketId;
199 | }
200 |
201 | public String getRequestHost() {
202 | return requestHost;
203 | }
204 |
205 | public void setRequestHost(String requestHost) {
206 | this.requestHost = requestHost;
207 | }
208 |
209 | }
210 |
--------------------------------------------------------------------------------
/src/main/java/net/fs/rudp/MessageInterface.java:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2015 D1SM.net
2 | package net.fs.rudp;
3 |
4 | import java.net.DatagramPacket;
5 |
6 | public interface MessageInterface {
7 | public int getVer();
8 | public int getSType();
9 | public DatagramPacket getDatagramPacket();
10 | }
11 |
12 |
--------------------------------------------------------------------------------
/src/main/java/net/fs/rudp/PipeListener.java:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2015 D1SM.net
2 | package net.fs.rudp;
3 |
4 | public interface PipeListener {
5 |
6 | void pipeClose();
7 |
8 | }
9 |
--------------------------------------------------------------------------------
/src/main/java/net/fs/rudp/RUDPConfig.java:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2015 D1SM.net
2 | package net.fs.rudp;
3 |
4 | public class RUDPConfig {
5 |
6 | public static short protocal_ver=0;
7 |
8 | public static int packageSize=1000;
9 |
10 | public static boolean twice_udp=false;
11 |
12 | public static boolean twice_tcp=false;
13 |
14 | public static int maxWin = 5*1024;
15 |
16 | public static int ackListDelay = 5;
17 | public static int ackListSum = 300;
18 |
19 | public static boolean double_send_start = true;
20 |
21 | public static int reSendDelay_min = 100;
22 | public static float reSendDelay = 0.37f;
23 | public static int reSendTryTimes = 10;
24 |
25 | }
26 |
--------------------------------------------------------------------------------
/src/main/java/net/fs/rudp/ReceivePingException.java:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2015 D1SM.net
2 | package net.fs.rudp;
3 |
4 | public class ReceivePingException extends Exception{
5 | /**
6 | *
7 | */
8 | private static final long serialVersionUID = -5199731243611486228L;
9 | String message;
10 | ReceivePingException(String message){
11 | this.message=message;
12 | }
13 | @Override
14 | public void printStackTrace(){
15 | //#MLog.println("Ping寮傚父 "+message);
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/src/main/java/net/fs/rudp/Receiver.java:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2015 D1SM.net
2 | package net.fs.rudp;
3 |
4 | import java.net.DatagramPacket;
5 | import java.net.InetAddress;
6 | import java.util.ArrayList;
7 | import java.util.HashMap;
8 | import java.util.Map;
9 |
10 | import net.fs.rudp.message.AckListMessage;
11 | import net.fs.rudp.message.CloseMessage_Conn;
12 | import net.fs.rudp.message.CloseMessage_Stream;
13 | import net.fs.rudp.message.DataMessage;
14 | import net.fs.utils.MessageCheck;
15 |
16 |
17 | public class Receiver {
18 | ConnectionUDP conn;
19 | Sender sender;
20 | public InetAddress dstIp;
21 | public int dstPort;
22 | Map receiveTable=new HashMap();
23 | int lastRead=-1;
24 | int lastReceive=-1;
25 | Object availOb=new Object();
26 |
27 | boolean isReady=false;
28 | Object readyOb=new Object();
29 | byte[] b4=new byte[4];
30 | int lastRead1=0;
31 | int maxWinR=10;
32 | int lastRead2=-1;
33 | UDPInputStream uis;
34 |
35 | float availWin=RUDPConfig.maxWin;
36 |
37 | int currentRemoteTimeId;
38 |
39 | int closeOffset;
40 |
41 | boolean streamClose=false;
42 |
43 | boolean reveivedClose=false;
44 |
45 | static int m=0,x,x2,c;
46 |
47 | boolean b=false,b2;
48 |
49 | public int nw;
50 |
51 | long received;
52 |
53 | Receiver(ConnectionUDP conn){
54 | this.conn=conn;
55 | uis=new UDPInputStream(conn);
56 | this.sender=conn.sender;
57 | this.dstIp=conn.dstIp;
58 | this.dstPort=conn.dstPort;
59 | }
60 |
61 | //接收流数据
62 | public byte[] receive() throws ConnectException {
63 | DataMessage me=null;
64 | if(conn.isConnected()){
65 | me=receiveTable.get(lastRead+1);
66 | synchronized (availOb){
67 | if(me==null){
68 | //MLog.println("等待中 "+conn.connectId+" "+(lastRead+1));
69 |
70 | try {
71 | availOb.wait();
72 | } catch (InterruptedException e) {
73 | e.printStackTrace();
74 | }
75 | me=receiveTable.get(lastRead+1);
76 | //MLog.println("等待完成aaa "+conn.connectId+" "+(lastRead+1));
77 | }
78 | }
79 |
80 | }else{
81 | throw new ConnectException("连接未建立");
82 | }
83 |
84 | if(!streamClose){
85 | checkCloseOffset_Remote();
86 | if(me==null){
87 | throw new ConnectException("连接已断开ccccccc");
88 | }else {
89 | }
90 | conn.sender.sendLastReadDelay();
91 |
92 | lastRead++;
93 | synchronized (availOb){
94 | receiveTable.remove(me.getSequence());
95 | }
96 |
97 | received+=me.getData().length;
98 | //System.out.println("received "+received/1024/1024+"MB");
99 | return me.getData();
100 | }else{
101 | throw new ConnectException("连接已断开");
102 | }
103 | }
104 |
105 | public void onReceivePacket(DatagramPacket dp){
106 | DataMessage me;
107 | if(dp!=null){
108 | if(conn.isConnected()){
109 | int ver=MessageCheck.checkVer(dp);
110 | int sType=MessageCheck.checkSType(dp);
111 | if(ver==RUDPConfig.protocal_ver){
112 | conn.live();
113 | if(sType==net.fs.rudp.message.MessageType.S_TYPE_DATA_MESSAGE){
114 | me=new DataMessage(dp);
115 | int timeId=me.getTimeId();
116 | SendRecord record=conn.clientControl.sendRecordTable_remote.get(timeId);
117 | if(record==null){
118 | record=new SendRecord();
119 | record.setTimeId(timeId);
120 | conn.clientControl.sendRecordTable_remote.put(timeId, record);
121 | }
122 | record.addSended(me.getData().length);
123 |
124 | if(timeId>currentRemoteTimeId){
125 | currentRemoteTimeId=timeId;
126 | }
127 |
128 | int sequence=me.getSequence();
129 |
130 | conn.sender.sendAckDelay(me.getSequence());
131 | if(sequence>lastRead){
132 | synchronized (availOb){
133 | receiveTable.put(sequence, me);
134 | if(receiveTable.containsKey(lastRead+1)){
135 | availOb.notify();
136 | }
137 | }
138 | }
139 | }else if(sType==net.fs.rudp.message.MessageType.S_TYPE_ACK_LIST_MESSAGE){
140 | AckListMessage alm=new AckListMessage(dp);
141 | int lastRead3=alm.getLastRead();
142 | if(lastRead3>lastRead2){
143 | lastRead2=lastRead3;
144 | }
145 | ArrayList ackList=alm.getAckList();
146 |
147 | for(int i=0;irc1.getAckedSize()){
154 | rc1.setAckedSize(alm.getS1());
155 | }
156 | }
157 |
158 | SendRecord rc2=conn.clientControl.getSendRecord(alm.getR2());
159 | if(rc2!=null){
160 | if(alm.getS2()>rc2.getAckedSize()){
161 | rc2.setAckedSize(alm.getS2());
162 | }
163 | }
164 |
165 | SendRecord rc3=conn.clientControl.getSendRecord(alm.getR3());
166 | if(rc3!=null){
167 | if(alm.getS3()>rc3.getAckedSize()){
168 | rc3.setAckedSize(alm.getS3());
169 | }
170 | }
171 |
172 | if(checkWin()){
173 | conn.sender.play();
174 | }
175 | }else if(sType==net.fs.rudp.message.MessageType.S_TYPE_CLOSE_MESSAGE_STREAM){
176 | CloseMessage_Stream cm=new CloseMessage_Stream(dp);
177 | reveivedClose=true;
178 | int n=cm.getCloseOffset();
179 | closeStream_Remote(n);
180 | }else if(sType==net.fs.rudp.message.MessageType.S_TYPE_CLOSE_MESSAGE_CONN){
181 | CloseMessage_Conn cm2=new CloseMessage_Conn(dp);
182 | conn.close_remote();
183 | }else{
184 | ////#MLog.println("未处理数据包 "+sType);
185 | }
186 | }
187 |
188 | }
189 | }
190 |
191 | }
192 |
193 | public void destroy(){
194 | //#MLog.println("destroy destroy destroy");
195 | synchronized (availOb) {
196 | receiveTable.clear();
197 | }
198 | }
199 |
200 | boolean checkWin(){
201 | nw=conn.sender.sendOffset-lastRead2;
202 | boolean b=false;
203 | if(nw=closeOffset-1){
221 | streamClose=true;
222 | synchronized (availOb){
223 | availOb.notifyAll();
224 | }
225 | conn.sender.closeStream_Remote();
226 | }
227 | }
228 | }
229 | }
230 |
231 | void closeStream_Local(){
232 | if(!streamClose){
233 | c++;
234 | streamClose=true;
235 | synchronized (availOb){
236 | availOb.notifyAll();
237 | }
238 | conn.sender.closeStream_Local();
239 | }
240 | }
241 |
242 | public int getCurrentTimeId() {
243 | return currentRemoteTimeId;
244 | }
245 |
246 | public void setCurrentTimeId(int currentTimeId) {
247 | this.currentRemoteTimeId = currentTimeId;
248 | }
249 |
250 |
251 | public int getCloseOffset() {
252 | return closeOffset;
253 | }
254 |
255 |
256 | public void setCloseOffset(int closeOffset) {
257 | this.closeOffset = closeOffset;
258 | }
259 |
260 | }
261 |
--------------------------------------------------------------------------------
/src/main/java/net/fs/rudp/ResendItem.java:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2015 D1SM.net
2 | package net.fs.rudp;
3 |
4 | public class ResendItem {
5 |
6 | int count;
7 |
8 | ConnectionUDP conn;
9 |
10 | int sequence;
11 |
12 | long resendTime;
13 |
14 | ResendItem(ConnectionUDP conn,int sequence){
15 | this.conn=conn;
16 | this.sequence=sequence;
17 | }
18 |
19 | void addCount(){
20 | count++;
21 | }
22 |
23 | public int getCount() {
24 | return count;
25 | }
26 |
27 | public void setCount(int count) {
28 | this.count = count;
29 | }
30 |
31 | public ConnectionUDP getConn() {
32 | return conn;
33 | }
34 |
35 | public void setConn(ConnectionUDP conn) {
36 | this.conn = conn;
37 | }
38 |
39 | public int getSequence() {
40 | return sequence;
41 | }
42 |
43 | public void setSequence(int sequence) {
44 | this.sequence = sequence;
45 | }
46 |
47 | public long getResendTime() {
48 | return resendTime;
49 | }
50 |
51 | public void setResendTime(long resendTime) {
52 | this.resendTime = resendTime;
53 | }
54 |
55 | }
56 |
--------------------------------------------------------------------------------
/src/main/java/net/fs/rudp/ResendManage.java:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2015 D1SM.net
2 | package net.fs.rudp;
3 |
4 | import java.util.concurrent.LinkedBlockingQueue;
5 |
6 |
7 | public class ResendManage implements Runnable{
8 |
9 | boolean haveTask=false;
10 | Object signalOb=new Object();
11 | Thread mainThread;
12 | long vTime=0;
13 | long lastReSendTime;
14 |
15 | LinkedBlockingQueue taskList=new LinkedBlockingQueue();
16 |
17 | public ResendManage(){
18 | Route.es.execute(this);
19 | }
20 |
21 | public void addTask(final ConnectionUDP conn,final int sequence){
22 | ResendItem ri=new ResendItem(conn, sequence);
23 | ri.setResendTime(getNewResendTime(conn));
24 | taskList.add(ri);
25 | }
26 |
27 | long getNewResendTime(ConnectionUDP conn){
28 | int delayAdd=conn.clientControl.pingDelay+(int) ((float)conn.clientControl.pingDelay*RUDPConfig.reSendDelay);
29 | if(delayAdd0){
43 | Thread.sleep(sleepTime);
44 | }
45 | ri.addCount();
46 |
47 | if(ri.conn.sender.getDataMessage(ri.sequence)!=null){
48 |
49 | if(!ri.conn.stopnow){
50 | //多线程重发容易内存溢出
51 | // Route.es.execute(new Runnable() {
52 | //
53 | // @Override
54 | // public void run() {
55 | // ri.conn.sender.reSend(ri.sequence,ri.getCount());
56 | // }
57 | //
58 | // });
59 | ri.conn.sender.reSend(ri.sequence,ri.getCount());
60 | }
61 |
62 | }
63 | if(ri.getCount() connTable;
32 | Route route;
33 | Thread mainThread;
34 | Thread reveiveThread;
35 |
36 | public static ThreadPoolExecutor es;
37 |
38 | public AckListManage delayAckManage;
39 |
40 | Object syn_ds2Table=new Object();
41 |
42 | Object syn_tunTable=new Object();
43 |
44 | Random ran=new Random();
45 |
46 | public int localclientId=Math.abs(ran.nextInt());
47 |
48 | LinkedBlockingQueue packetBuffer=new LinkedBlockingQueue();
49 |
50 | public static int mode_server=2;
51 |
52 | public static int mode_client=1;
53 |
54 | public int mode=mode_client;//1客户端,2服务端
55 |
56 | String pocessName="";
57 |
58 | Set setedTable=new HashSet();
59 |
60 | static int vv;
61 |
62 | Set closedTable=new HashSet();
63 |
64 | public static int localDownloadSpeed,localUploadSpeed;
65 |
66 | ClientManager clientManager;
67 |
68 | HashSet pingTable=new HashSet();
69 |
70 | public CapEnv capEnv=null;
71 |
72 | public ClientControl lastClientControl;
73 |
74 | public boolean useTcpTun=true;
75 |
76 | public HashMap