├── 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 contentTable=new HashMap(); 77 | 78 | private static List listenerList=new Vector(); 79 | 80 | { 81 | 82 | delayAckManage = new AckListManage(); 83 | } 84 | 85 | static{ 86 | SynchronousQueue queue = new SynchronousQueue(); 87 | ThreadPoolExecutor executor = new ThreadPoolExecutor(100, Integer.MAX_VALUE, 10*1000, TimeUnit.MILLISECONDS, queue); 88 | es=executor; 89 | } 90 | 91 | public Route(String pocessName,short routePort,int mode2,boolean tcp,boolean tcpEnvSuccess) throws Exception{ 92 | 93 | this.mode=mode2; 94 | useTcpTun=tcp; 95 | this.pocessName=pocessName; 96 | if(useTcpTun){ 97 | if(mode==2){ 98 | //服务端 99 | VDatagramSocket d=new VDatagramSocket(routePort); 100 | d.setClient(false); 101 | try { 102 | capEnv=new CapEnv(false,tcpEnvSuccess); 103 | capEnv.setListenPort(routePort); 104 | capEnv.init(); 105 | } catch (Exception e) { 106 | //e.printStackTrace(); 107 | throw e; 108 | } 109 | d.setCapEnv(capEnv); 110 | 111 | ds=d; 112 | }else { 113 | //客户端 114 | VDatagramSocket d=new VDatagramSocket(); 115 | d.setClient(true); 116 | try { 117 | capEnv=new CapEnv(true,tcpEnvSuccess); 118 | capEnv.init(); 119 | } catch (Exception e) { 120 | //e.printStackTrace(); 121 | throw e; 122 | } 123 | d.setCapEnv(capEnv); 124 | 125 | ds=d; 126 | } 127 | }else { 128 | if(mode==2){ 129 | MLog.info("Listen udp port: "+CapEnv.toUnsigned(routePort)); 130 | ds=new DatagramSocket(CapEnv.toUnsigned(routePort)); 131 | }else { 132 | ds=new DatagramSocket(); 133 | } 134 | } 135 | 136 | connTable=new HashMap(); 137 | clientManager=new ClientManager(this); 138 | reveiveThread=new Thread(){ 139 | @Override 140 | public void run(){ 141 | while(true){ 142 | byte[] b=new byte[1500]; 143 | DatagramPacket dp=new DatagramPacket(b,b.length); 144 | try { 145 | ds.receive(dp); 146 | //MLog.println("接收 "+dp.getAddress()); 147 | packetBuffer.add(dp); 148 | } catch (IOException e) { 149 | e.printStackTrace(); 150 | try { 151 | Thread.sleep(1); 152 | } catch (InterruptedException e1) { 153 | e1.printStackTrace(); 154 | } 155 | continue; 156 | } 157 | } 158 | } 159 | }; 160 | reveiveThread.start(); 161 | 162 | mainThread=new Thread(){ 163 | public void run() { 164 | while(true){ 165 | DatagramPacket dp=null; 166 | try { 167 | dp = packetBuffer.take(); 168 | } catch (InterruptedException e1) { 169 | e1.printStackTrace(); 170 | } 171 | if(dp==null){ 172 | continue; 173 | } 174 | long t1=System.currentTimeMillis(); 175 | byte[] dpData=dp.getData(); 176 | 177 | int sType=0; 178 | if(dp.getData().length<4){ 179 | return; 180 | } 181 | sType=MessageCheck.checkSType(dp); 182 | //MLog.println("route receive MessageType111#"+sType+" "+dp.getAddress()+":"+dp.getPort()); 183 | if(dp!=null){ 184 | 185 | final int connectId=ByteIntConvert.toInt(dpData, 4); 186 | int remote_clientId=ByteIntConvert.toInt(dpData, 8); 187 | 188 | if(closedTable.contains(connectId)&&connectId!=0){ 189 | //#MLog.println("忽略已关闭连接包 "+connectId); 190 | continue; 191 | } 192 | 193 | if(sType==net.fs.rudp.message.MessageType.sType_PingMessage 194 | ||sType==net.fs.rudp.message.MessageType.sType_PingMessage2){ 195 | ClientControl clientControl=null; 196 | if(mode==2){ 197 | //发起 198 | clientControl=clientManager.getClientControl(remote_clientId,dp.getAddress(),dp.getPort()); 199 | }else if(mode==1){ 200 | //接收 201 | String key=dp.getAddress().getHostAddress()+":"+dp.getPort(); 202 | int sim_clientId=Math.abs(key.hashCode()); 203 | clientControl=clientManager.getClientControl(sim_clientId,dp.getAddress(),dp.getPort()); 204 | } 205 | clientControl.onReceivePacket(dp); 206 | }else { 207 | //发起 208 | if(mode==1){ 209 | if(!setedTable.contains(remote_clientId)){ 210 | String key=dp.getAddress().getHostAddress()+":"+dp.getPort(); 211 | int sim_clientId=Math.abs(key.hashCode()); 212 | ClientControl clientControl=clientManager.getClientControl(sim_clientId,dp.getAddress(),dp.getPort()); 213 | if(clientControl.getClientId_real()==-1){ 214 | clientControl.setClientId_real(remote_clientId); 215 | //#MLog.println("首次设置clientId "+remote_clientId); 216 | }else { 217 | if(clientControl.getClientId_real()!=remote_clientId){ 218 | //#MLog.println("服务端重启更新clientId "+sType+" "+clientControl.getClientId_real()+" new: "+remote_clientId); 219 | clientControl.updateClientId(remote_clientId); 220 | } 221 | } 222 | //#MLog.println("cccccc "+sType+" "+remote_clientId); 223 | setedTable.add(remote_clientId); 224 | } 225 | } 226 | 227 | 228 | //udp connection 229 | if(mode==2){ 230 | //接收 231 | try { 232 | getConnection2(dp.getAddress(),dp.getPort(),connectId,remote_clientId); 233 | } catch (Exception e) { 234 | e.printStackTrace(); 235 | } 236 | } 237 | 238 | final ConnectionUDP ds3=connTable.get(connectId); 239 | if(ds3!=null){ 240 | final DatagramPacket dp2=dp; 241 | ds3.receiver.onReceivePacket(dp2); 242 | if(sType==MessageType.S_TYPE_DATA_MESSAGE){ 243 | TrafficEvent event=new TrafficEvent("",ran.nextLong(),dp.getLength(),TrafficEvent.type_downloadTraffic); 244 | fireEvent(event); 245 | } 246 | } 247 | 248 | } 249 | } 250 | } 251 | } 252 | }; 253 | mainThread.start(); 254 | 255 | } 256 | 257 | public static void addTrafficlistener(Trafficlistener listener){ 258 | listenerList.add(listener); 259 | } 260 | 261 | static void fireEvent(TrafficEvent event){ 262 | for(Trafficlistener listener:listenerList){ 263 | int type=event.getType(); 264 | if(type==TrafficEvent.type_downloadTraffic){ 265 | listener.trafficDownload(event); 266 | }else if(type==TrafficEvent.type_uploadTraffic){ 267 | listener.trafficUpload(event); 268 | } 269 | } 270 | } 271 | 272 | public void sendPacket(DatagramPacket dp) throws IOException{ 273 | ds.send(dp); 274 | } 275 | 276 | public ConnectionProcessor createTunnelProcessor(){ 277 | ConnectionProcessor o=null; 278 | try { 279 | Class onwClass = Class.forName(pocessName); 280 | o = (ConnectionProcessor) onwClass.newInstance(); 281 | } catch (ClassNotFoundException e) { 282 | e.printStackTrace(); 283 | } catch (InstantiationException e) { 284 | e.printStackTrace(); 285 | } catch (IllegalAccessException e) { 286 | e.printStackTrace(); 287 | } 288 | return o; 289 | } 290 | 291 | void removeConnection(ConnectionUDP conn){ 292 | synchronized (syn_ds2Table){ 293 | closedTable.add(conn.connectId); 294 | connTable.remove(conn.connectId); 295 | } 296 | } 297 | 298 | //接收连接 299 | public ConnectionUDP getConnection2(InetAddress dstIp,int dstPort,int connectId,int clientId) throws Exception{ 300 | ConnectionUDP conn=connTable.get(connectId); 301 | if(conn==null){ 302 | ClientControl clientControl=clientManager.getClientControl(clientId,dstIp,dstPort); 303 | conn=new ConnectionUDP(this,dstIp,dstPort,2,connectId,clientControl); 304 | synchronized (syn_ds2Table){ 305 | connTable.put(connectId, conn); 306 | } 307 | clientControl.addConnection(conn); 308 | } 309 | return conn; 310 | } 311 | 312 | //发起连接 313 | public ConnectionUDP getConnection(String address,int dstPort,String password) throws Exception{ 314 | InetAddress dstIp=InetAddress.getByName(address); 315 | int connectId=Math.abs(ran.nextInt()); 316 | String key=dstIp.getHostAddress()+":"+dstPort; 317 | int remote_clientId=Math.abs(key.hashCode()); 318 | ClientControl clientControl=clientManager.getClientControl(remote_clientId,dstIp,dstPort); 319 | clientControl.setPassword(password); 320 | ConnectionUDP conn=new ConnectionUDP(this,dstIp,dstPort,1,connectId,clientControl); 321 | synchronized (syn_ds2Table){ 322 | connTable.put(connectId, conn); 323 | } 324 | clientControl.addConnection(conn); 325 | lastClientControl=clientControl; 326 | return conn; 327 | } 328 | 329 | public boolean isUseTcpTun() { 330 | return useTcpTun; 331 | } 332 | 333 | public void setUseTcpTun(boolean useTcpTun) { 334 | this.useTcpTun = useTcpTun; 335 | } 336 | 337 | } 338 | 339 | 340 | -------------------------------------------------------------------------------- /src/main/java/net/fs/rudp/SendRecord.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 D1SM.net 2 | package net.fs.rudp; 3 | 4 | public class SendRecord { 5 | 6 | int sendSize,sendSize_First; 7 | 8 | int sendCount; 9 | 10 | int ackedSize; 11 | 12 | int timeId; 13 | 14 | int speed; 15 | 16 | boolean speedRecored=false; 17 | 18 | int resended; 19 | 20 | SendRecord(){ 21 | 22 | } 23 | 24 | float getDropRate(){ 25 | int droped=getSendSize()-getAckedSize(); 26 | if(droped<0){ 27 | droped=0; 28 | } 29 | float dropRate=0; 30 | if(getSendSize()>0){ 31 | dropRate=(float)droped/getSendSize(); 32 | } 33 | return dropRate; 34 | } 35 | 36 | float getResendRate(){ 37 | float resendRate=0; 38 | if(getSendSize_First()>0){ 39 | resendRate=(float)getResended()/getSendSize_First(); 40 | } 41 | return resendRate; 42 | } 43 | 44 | void addResended(int size){ 45 | resended+=size; 46 | } 47 | 48 | void addSended(int size){ 49 | sendCount++; 50 | sendSize+=size; 51 | } 52 | 53 | void addSended_First(int size){ 54 | sendSize_First+=size; 55 | } 56 | 57 | public int getSendSize() { 58 | return sendSize; 59 | } 60 | 61 | public int getSendCount() { 62 | return sendCount; 63 | } 64 | 65 | public int getAckedSize() { 66 | return ackedSize; 67 | } 68 | 69 | //接收到的数据大小 70 | public void setAckedSize(int ackedSize) { 71 | if(ackedSize>this.ackedSize){ 72 | this.ackedSize = ackedSize; 73 | } 74 | } 75 | 76 | public int getTimeId() { 77 | return timeId; 78 | } 79 | 80 | public void setTimeId(int timeId) { 81 | this.timeId = timeId; 82 | } 83 | 84 | public int getSpeed() { 85 | return speed; 86 | } 87 | 88 | public void setSpeed(int speed) { 89 | this.speed = speed; 90 | speedRecored=true; 91 | } 92 | 93 | public boolean isSpeedRecored(){ 94 | return speedRecored; 95 | } 96 | 97 | public int getResended() { 98 | return resended; 99 | } 100 | 101 | public void setResended(int resended) { 102 | this.resended = resended; 103 | } 104 | 105 | public int getSendSize_First() { 106 | return sendSize_First; 107 | } 108 | 109 | public void setSendSize_First(int sendSize_First) { 110 | this.sendSize_First = sendSize_First; 111 | } 112 | 113 | } 114 | -------------------------------------------------------------------------------- /src/main/java/net/fs/rudp/Sender.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 D1SM.net 2 | package net.fs.rudp; 3 | 4 | import java.io.IOException; 5 | import java.net.DatagramPacket; 6 | import java.net.InetAddress; 7 | import java.util.ArrayList; 8 | import java.util.HashMap; 9 | import java.util.Map; 10 | import java.util.Random; 11 | 12 | import net.fs.rudp.message.AckListMessage; 13 | import net.fs.rudp.message.CloseMessage_Conn; 14 | import net.fs.rudp.message.CloseMessage_Stream; 15 | import net.fs.rudp.message.DataMessage; 16 | 17 | public class Sender { 18 | DataMessage me2=null; 19 | int interval; 20 | 21 | public int sum=0; 22 | int sleepTime=100; 23 | ConnectionUDP conn; 24 | Receiver receiver=null; 25 | boolean bussy=false; 26 | Object bussyOb=new Object(); 27 | boolean isHave=false; 28 | public Map sendTable=new HashMap(); 29 | boolean isReady=false; 30 | Object readyOb=new Object(); 31 | Object winOb=new Object(); 32 | public InetAddress dstIp; 33 | public int dstPort; 34 | public int sequence=0; 35 | int sendOffset=-1; 36 | boolean pause=false; 37 | int unAckMin=0; 38 | int unAckMax=-1; 39 | int sendSum=0; 40 | int reSendSum=0; 41 | UDPOutputStream uos; 42 | int sw=0; 43 | 44 | static Random ran=new Random(); 45 | 46 | long lastSendTime=-1; 47 | 48 | boolean closed=false; 49 | 50 | boolean streamClosed=false; 51 | 52 | static int s=0; 53 | 54 | Object syn_send_table=new Object(); 55 | 56 | HashMap unAckTable=new HashMap(); 57 | 58 | Sender(ConnectionUDP conn){ 59 | this.conn=conn; 60 | uos=new UDPOutputStream (conn); 61 | receiver=conn.receiver; 62 | this.dstIp=conn.dstIp; 63 | this.dstPort=conn.dstPort; 64 | } 65 | 66 | void sendData(byte[] data,int offset,int length) throws ConnectException, InterruptedException{ 67 | int packetLength=RUDPConfig.packageSize; 68 | int sum=(length/packetLength); 69 | if(length%packetLength!=0){ 70 | sum+=1; 71 | } 72 | if(sum==0){ 73 | sum=1; 74 | } 75 | int len=packetLength; 76 | if(length<=len){ 77 | sw++; 78 | sendNata(data,0,length); 79 | sw--; 80 | }else{ 81 | for(int i=0;ilength){ 87 | len=length-(sum-1)*packetLength; 88 | } 89 | } 90 | } 91 | } 92 | 93 | void sendNata(byte[] data,int offset,int length) throws ConnectException, InterruptedException{ 94 | 95 | if(!closed){ 96 | if(!streamClosed){ 97 | DataMessage me=new DataMessage(sequence,data,0,(short) length,conn.connectId,conn.route.localclientId); 98 | me.setDstAddress(dstIp); 99 | me.setDstPort(dstPort); 100 | synchronized (syn_send_table) { 101 | sendTable.put(me.getSequence(),me); 102 | } 103 | 104 | synchronized (winOb){ 105 | if(!conn.receiver.checkWin()){ 106 | try { 107 | winOb.wait(); 108 | } catch (InterruptedException e) { 109 | throw e; 110 | } 111 | } 112 | } 113 | 114 | boolean twice=false; 115 | if(RUDPConfig.twice_tcp){ 116 | twice=true; 117 | } 118 | if(RUDPConfig.double_send_start){ 119 | if(me.getSequence()<=5){ 120 | twice=true; 121 | } 122 | } 123 | sendDataMessage(me,false,twice,true); 124 | lastSendTime=System.currentTimeMillis(); 125 | sendOffset++; 126 | s+=me.getData().length; 127 | conn.clientControl.resendMange.addTask(conn, sequence); 128 | sequence++;//必须放最后 129 | }else{ 130 | throw new ConnectException("RDP连接已断开sendData"); 131 | } 132 | }else{ 133 | throw new ConnectException("RDP连接已经关闭"); 134 | } 135 | 136 | } 137 | 138 | public void closeStream_Local(){ 139 | if(!streamClosed){ 140 | streamClosed=true; 141 | conn.receiver.closeStream_Local(); 142 | if(!conn.stopnow){ 143 | sendCloseMessage_Stream(); 144 | } 145 | } 146 | } 147 | 148 | public void closeStream_Remote(){ 149 | if(!streamClosed){ 150 | streamClosed=true; 151 | } 152 | } 153 | 154 | void sendDataMessage(DataMessage me,boolean resend,boolean twice,boolean block){ 155 | synchronized (conn.clientControl.getSynlock()) { 156 | long startTime=System.nanoTime(); 157 | long t1=System.currentTimeMillis(); 158 | conn.clientControl.onSendDataPacket(conn); 159 | 160 | int timeId=conn.clientControl.getCurrentTimeId(); 161 | 162 | me.create(timeId); 163 | 164 | SendRecord record_current=conn.clientControl.getSendRecord(timeId); 165 | if(!resend){ 166 | //第一次发,修改当前时间记录 167 | me.setFirstSendTimeId(timeId); 168 | me.setFirstSendTime(System.currentTimeMillis()); 169 | record_current.addSended_First(me.getData().length); 170 | record_current.addSended(me.getData().length); 171 | }else { 172 | //重发,修改第一次发送时间记录 173 | SendRecord record=conn.clientControl.getSendRecord(me.getFirstSendTimeId()); 174 | record.addResended(me.getData().length); 175 | record_current.addSended(me.getData().length); 176 | } 177 | 178 | try { 179 | sendSum++; 180 | sum++; 181 | unAckMax++; 182 | 183 | long t=System.currentTimeMillis(); 184 | send(me.getDatagramPacket()); 185 | 186 | if(twice){ 187 | send(me.getDatagramPacket());//发两次 188 | } 189 | if(block){ 190 | conn.clientControl.sendSleep(startTime, me.getData().length); 191 | } 192 | TrafficEvent event=new TrafficEvent("",ran.nextLong(),me.getData().length,TrafficEvent.type_uploadTraffic); 193 | Route.fireEvent(event); 194 | } catch (IOException e) { 195 | e.printStackTrace(); 196 | } 197 | } 198 | 199 | } 200 | 201 | void sendAckDelay(int ackSequence){ 202 | conn.route.delayAckManage.addAck(conn, ackSequence); 203 | } 204 | 205 | void sendLastReadDelay(){ 206 | conn.route.delayAckManage.addLastRead(conn); 207 | } 208 | 209 | DataMessage getDataMessage(int sequence){ 210 | return sendTable.get(sequence); 211 | } 212 | 213 | public void reSend(int sequence,int count){ 214 | if(sendTable.containsKey(sequence)){ 215 | DataMessage dm=sendTable.get(sequence); 216 | if(dm!=null){ 217 | sendDataMessage(dm,true,false,true); 218 | } 219 | } 220 | } 221 | 222 | public void destroy(){ 223 | synchronized (syn_send_table) { 224 | sendTable.clear(); 225 | } 226 | } 227 | 228 | //删除后不会重发 229 | void removeSended_Ack(int sequence){ 230 | synchronized (syn_send_table) { 231 | DataMessage dm=sendTable.remove(sequence); 232 | } 233 | } 234 | 235 | void play(){ 236 | synchronized (winOb){ 237 | winOb.notifyAll(); 238 | } 239 | } 240 | 241 | void close(){ 242 | synchronized (winOb){ 243 | closed=true; 244 | winOb.notifyAll(); 245 | } 246 | } 247 | 248 | void sendCloseMessage_Stream(){ 249 | CloseMessage_Stream cm=new CloseMessage_Stream(conn.connectId,conn.route.localclientId,sequence); 250 | cm.setDstAddress(dstIp); 251 | cm.setDstPort(dstPort); 252 | try { 253 | send(cm.getDatagramPacket()); 254 | } catch (IOException e) { 255 | e.printStackTrace(); 256 | } 257 | try { 258 | send(cm.getDatagramPacket()); 259 | } catch (IOException e) { 260 | e.printStackTrace(); 261 | } 262 | } 263 | 264 | void sendCloseMessage_Conn(){ 265 | CloseMessage_Conn cm=new CloseMessage_Conn(conn.connectId,conn.route.localclientId); 266 | cm.setDstAddress(dstIp); 267 | cm.setDstPort(dstPort); 268 | try { 269 | send(cm.getDatagramPacket()); 270 | } catch (IOException e) { 271 | e.printStackTrace(); 272 | } 273 | try { 274 | send(cm.getDatagramPacket()); 275 | } catch (IOException e) { 276 | e.printStackTrace(); 277 | } 278 | } 279 | 280 | void sendALMessage(ArrayList ackList){ 281 | int currentTimeId=conn.receiver.getCurrentTimeId(); 282 | AckListMessage alm=new AckListMessage(conn.connetionId,ackList,conn.receiver.lastRead,conn 283 | .clientControl.sendRecordTable_remote,currentTimeId, 284 | conn.connectId,conn.route.localclientId); 285 | alm.setDstAddress(dstIp); 286 | alm.setDstPort(dstPort); 287 | try { 288 | send(alm.getDatagramPacket()); 289 | } catch (IOException e) { 290 | e.printStackTrace(); 291 | } 292 | } 293 | 294 | void send(DatagramPacket dp) throws IOException { 295 | sendPacket(dp,conn.connectId); 296 | } 297 | 298 | public void sendPacket(DatagramPacket dp,Integer di) throws IOException{ 299 | conn.clientControl.sendPacket(dp); 300 | } 301 | 302 | } 303 | -------------------------------------------------------------------------------- /src/main/java/net/fs/rudp/StreamPipe.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.List; 10 | import java.util.Vector; 11 | import java.util.concurrent.Semaphore; 12 | 13 | 14 | public class StreamPipe { 15 | 16 | DataInputStream is; 17 | 18 | DataOutputStream os; 19 | 20 | List listenerList; 21 | 22 | boolean closed=false; 23 | 24 | int maxLen=2000; 25 | 26 | long lastResetTime; 27 | 28 | int maxSpeed=100*1024*1024; 29 | 30 | int port=0; 31 | 32 | int limiteConnectTime; 33 | 34 | String userId=""; 35 | 36 | byte[] preReadData; 37 | 38 | int preReadDataLength; 39 | 40 | Socket socketA,socketB; 41 | 42 | boolean writing=false; 43 | 44 | int BUF_SIZE; 45 | 46 | ArrayList dataList=new ArrayList(); 47 | 48 | Semaphore semp_have_data=new Semaphore(0); 49 | 50 | int cachedSize=0; 51 | 52 | int supserSocketId=-1; 53 | 54 | static int type_request=1; 55 | 56 | static int type_respone=2; 57 | 58 | int type=0; 59 | 60 | ConnInfo connInfo; 61 | 62 | public StreamPipe(ConnInfo connInfo,final DataInputStream is,final DataOutputStream os,final int BUF_SIZE,final int maxSpeed){ 63 | this(connInfo,is, os, BUF_SIZE, maxSpeed, null, 0); 64 | } 65 | 66 | public StreamPipe(ConnInfo ci,final DataInputStream is,final DataOutputStream os,int BUF_SIZE1,final int maxSpeed,final byte[] preReadData,final int preReadDataLength){ 67 | connInfo=ci; 68 | listenerList=new Vector(); 69 | this.maxSpeed=maxSpeed; 70 | this.preReadData=preReadData; 71 | BUF_SIZE=BUF_SIZE1; 72 | if(maxSpeed<=50*1024){ 73 | //BUF_SIZE=100; 74 | } 75 | Runnable thread=new Runnable(){ 76 | 77 | int count=0; 78 | public void run(){ 79 | byte[] data=new byte[BUF_SIZE]; 80 | int len=0; 81 | try { 82 | if(preReadData!=null){ 83 | // String string=new String(preReadData,0,preReadDataLength); 84 | // Log.println("写预读111 "+string); 85 | try { 86 | os.write(preReadData,0,preReadDataLength); 87 | } catch (IOException e) { 88 | e.printStackTrace(); 89 | return; 90 | } 91 | // Log.println("写预读222 "); 92 | } 93 | //Log.println("pipe发送 111 "+supserSocketId+" "); 94 | boolean parsed=false; 95 | try { 96 | while((len=is.read(data))>0){ 97 | try { 98 | os.write(data,0,len); 99 | } catch (IOException e) { 100 | //e.printStackTrace(); 101 | break; 102 | } 103 | 104 | } 105 | } catch (IOException e) { 106 | //e.printStackTrace(); 107 | } 108 | }finally{ 109 | close(); 110 | } 111 | } 112 | }; 113 | Route.es.execute(thread); 114 | } 115 | 116 | void close(){ 117 | if(!closed){ 118 | closed=true; 119 | try { 120 | Thread.sleep(500); 121 | } catch (InterruptedException e1) { 122 | //e1.printStackTrace(); 123 | } 124 | 125 | if(socketA!=null){ 126 | Route.es.execute(new Runnable() { 127 | 128 | public void run() { 129 | try { 130 | socketA.close(); 131 | } catch (IOException e) { 132 | //e.printStackTrace(); 133 | } 134 | } 135 | 136 | }); 137 | 138 | } 139 | 140 | 141 | if(socketB!=null){ 142 | 143 | Route.es.execute(new Runnable() { 144 | 145 | public void run() { 146 | try { 147 | socketB.close(); 148 | } catch (IOException e) { 149 | //e.printStackTrace(); 150 | } 151 | } 152 | }); 153 | 154 | } 155 | fireClose(); 156 | } 157 | } 158 | 159 | class HttpHost{ 160 | String address; 161 | int port=80; 162 | public String getAddress() { 163 | return address; 164 | } 165 | public void setAddress(String address) { 166 | this.address = address; 167 | } 168 | public int getPort() { 169 | return port; 170 | } 171 | public void setPort(int port) { 172 | this.port = port; 173 | } 174 | 175 | } 176 | 177 | HttpHost readHost(String data){ 178 | HttpHost hh=new HttpHost(); 179 | String host=null; 180 | data=data.replaceAll("\r", ""); 181 | data=data.replaceAll(" ", ""); 182 | String[] ls=data.split("\n"); 183 | for(String l:ls){ 184 | if(l.startsWith("Host:")){ 185 | String s1=l.substring(5); 186 | int index2=s1.indexOf(":"); 187 | if(index2>-1){ 188 | int port=Integer.parseInt(s1.substring(index2+1)); 189 | hh.setPort(port); 190 | s1=s1.substring(0,index2); 191 | } 192 | host=s1; 193 | hh.setAddress(host); 194 | ////#MLog.println("ddd "+s1); 195 | } 196 | } 197 | return hh; 198 | } 199 | 200 | public void addListener(PipeListener listener){ 201 | listenerList.add(listener); 202 | } 203 | 204 | void fireClose(){ 205 | //Log.println("StreamPipe关闭 fireClose111 "+listenerList.size()); 206 | for(PipeListener listener:listenerList){ 207 | //Log.println("StreamPipe关闭 fireClose222"); 208 | listener.pipeClose(); 209 | } 210 | } 211 | 212 | public int getPort() { 213 | return port; 214 | } 215 | 216 | public void setPort(int port) { 217 | this.port = port; 218 | } 219 | 220 | public int getLimiteConnectTime() { 221 | return limiteConnectTime; 222 | } 223 | 224 | public void setLimiteConnectTime(int limiteConnectTime) { 225 | this.limiteConnectTime = limiteConnectTime; 226 | } 227 | 228 | public String getUserId() { 229 | return userId; 230 | } 231 | 232 | public void setUserId(String userId) { 233 | this.userId = userId; 234 | } 235 | 236 | public Socket getSocketA() { 237 | return socketA; 238 | } 239 | 240 | public void setSocketA(Socket socketA) { 241 | this.socketA = socketA; 242 | } 243 | 244 | public Socket getSocketB() { 245 | return socketB; 246 | } 247 | 248 | public void setSocketB(Socket socketB) { 249 | this.socketB = socketB; 250 | } 251 | 252 | public int getSupserSocketId() { 253 | return supserSocketId; 254 | } 255 | 256 | public void setSupserSocketId(int supserSocketId) { 257 | this.supserSocketId = supserSocketId; 258 | } 259 | 260 | public int getType() { 261 | return type; 262 | } 263 | 264 | public void setType(int type) { 265 | this.type = type; 266 | } 267 | 268 | public ConnInfo getConnInfo() { 269 | return connInfo; 270 | } 271 | 272 | public void setConnInfo(ConnInfo connInfo) { 273 | this.connInfo = connInfo; 274 | } 275 | 276 | } 277 | -------------------------------------------------------------------------------- /src/main/java/net/fs/rudp/TrafficEvent.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 D1SM.net 2 | package net.fs.rudp; 3 | 4 | public class TrafficEvent { 5 | 6 | long eventId; 7 | 8 | int traffic; 9 | 10 | public static int type_downloadTraffic=10; 11 | 12 | public static int type_uploadTraffic=11; 13 | 14 | int type=type_downloadTraffic; 15 | 16 | String userId; 17 | 18 | TrafficEvent(long eventId,int traffic,int type){ 19 | this(null,eventId,traffic,type); 20 | } 21 | 22 | public TrafficEvent(String userId,long eventId,int traffic,int type){ 23 | this.userId=userId; 24 | this.eventId=eventId; 25 | this.traffic=traffic; 26 | this.type=type; 27 | } 28 | 29 | public String getUserId() { 30 | return userId; 31 | } 32 | 33 | public void setUserId(String userId) { 34 | this.userId = userId; 35 | } 36 | 37 | public int getType() { 38 | return type; 39 | } 40 | 41 | public long getEventId() { 42 | return eventId; 43 | } 44 | 45 | public void setEventId(long eventId) { 46 | this.eventId = eventId; 47 | } 48 | 49 | public int getTraffic() { 50 | return traffic; 51 | } 52 | 53 | public void setTraffic(int traffic) { 54 | this.traffic = traffic; 55 | } 56 | 57 | 58 | 59 | } 60 | -------------------------------------------------------------------------------- /src/main/java/net/fs/rudp/Trafficlistener.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 D1SM.net 2 | package net.fs.rudp; 3 | 4 | public interface Trafficlistener { 5 | 6 | public void trafficDownload(TrafficEvent event); 7 | 8 | 9 | public void trafficUpload(TrafficEvent event); 10 | 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/net/fs/rudp/UDPInputStream.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 D1SM.net 2 | package net.fs.rudp; 3 | 4 | import java.net.DatagramSocket; 5 | import java.net.InetAddress; 6 | 7 | public class UDPInputStream { 8 | 9 | DatagramSocket ds; 10 | InetAddress dstIp; 11 | int dstPort; 12 | Receiver receiver; 13 | 14 | boolean streamClosed=false; 15 | 16 | ConnectionUDP conn; 17 | 18 | UDPInputStream(ConnectionUDP conn){ 19 | this.conn=conn; 20 | receiver=conn.receiver; 21 | } 22 | 23 | public int read(byte[] b, int off, int len) throws ConnectException, InterruptedException { 24 | byte[] b2=null; 25 | b2 = read2(); 26 | if(len ackList; 16 | byte[] dpData=null; 17 | int lastRead; 18 | 19 | int r1,r2,r3,s1,s2,s3; 20 | 21 | @SuppressWarnings("unchecked") 22 | public AckListMessage(long connId, ArrayList ackList, int lastRead, 23 | Map sendRecordTable, int timeId, 24 | int connectId, int clientId){ 25 | this.clientId=clientId; 26 | this.connectId=connectId; 27 | this.ackList=ackList; 28 | this.lastRead=lastRead; 29 | int len1=4+4+10+4*ackList.size(); 30 | dpData=new byte[len1+24+9]; 31 | sType=MessageType.S_TYPE_ACK_LIST_MESSAGE; 32 | ByteShortConvert.toByteArray(ver, dpData, 0); //add: ver 33 | ByteShortConvert.toByteArray(sType, dpData, 2); //add: service type 34 | ByteIntConvert.toByteArray(connectId, dpData, 4); //add: sequence 35 | ByteIntConvert.toByteArray(clientId, dpData, 8); //add: sequence 36 | 37 | ByteIntConvert.toByteArray(lastRead, dpData, 4+8); 38 | //dpData[8]=(byte) ackList.size(); 39 | ByteShortConvert.toByteArray((short) ackList.size(), dpData, 8+8); //add: service type 40 | for(int i=0;i(); 93 | int t=0; 94 | for(int i=0;i 0) { 221 | // MLog.println("删除行 "+row); 222 | String cmd = "iptables -D INPUT " + row; 223 | runCommand(cmd); 224 | } else { 225 | break; 226 | } 227 | } 228 | } 229 | 230 | void setFireWall_linux_tcp() { 231 | cleanTcpTunRule(); 232 | String cmd2 = "iptables -I INPUT -p tcp --dport " + routePort + " -j DROP" 233 | + " -m comment --comment tcptun_fs_server "; 234 | runCommand(cmd2); 235 | 236 | } 237 | 238 | void cleanTcpTunRule() { 239 | while (true) { 240 | int row = getRow("tcptun_fs_server"); 241 | if (row > 0) { 242 | // MLog.println("删除行 "+row); 243 | String cmd = "iptables -D INPUT " + row; 244 | runCommand(cmd); 245 | } else { 246 | break; 247 | } 248 | } 249 | } 250 | 251 | int getRow(String name) { 252 | int row_delect = -1; 253 | String cme_list_rule = "iptables -L -n --line-number"; 254 | // String [] cmd={"netsh","advfirewall set allprofiles state on"}; 255 | Thread errorReadThread = null; 256 | try { 257 | final Process p = Runtime.getRuntime().exec(cme_list_rule, null); 258 | 259 | errorReadThread = new Thread() { 260 | public void run() { 261 | InputStream is = p.getErrorStream(); 262 | BufferedReader localBufferedReader = new BufferedReader(new InputStreamReader(is)); 263 | while (true) { 264 | String line; 265 | try { 266 | line = localBufferedReader.readLine(); 267 | if (line == null) { 268 | break; 269 | } else { 270 | // System.out.println("erroraaa "+line); 271 | } 272 | } catch (IOException e) { 273 | e.printStackTrace(); 274 | // error(); 275 | break; 276 | } 277 | } 278 | } 279 | }; 280 | errorReadThread.start(); 281 | 282 | InputStream is = p.getInputStream(); 283 | BufferedReader localBufferedReader = new BufferedReader(new InputStreamReader(is)); 284 | while (true) { 285 | String line; 286 | try { 287 | line = localBufferedReader.readLine(); 288 | // System.out.println("standaaa "+line); 289 | if (line == null) { 290 | break; 291 | } else { 292 | if (line.contains(name)) { 293 | int index = line.indexOf(" "); 294 | if (index > 0) { 295 | String n = line.substring(0, index); 296 | try { 297 | if (row_delect < 0) { 298 | // System.out.println("standaaabbb 299 | // "+line); 300 | row_delect = Integer.parseInt(n); 301 | } 302 | } catch (Exception e) { 303 | 304 | } 305 | } 306 | } 307 | ; 308 | } 309 | } catch (IOException e) { 310 | e.printStackTrace(); 311 | break; 312 | } 313 | } 314 | 315 | errorReadThread.join(); 316 | p.waitFor(); 317 | } catch (Exception e) { 318 | e.printStackTrace(); 319 | // error(); 320 | } 321 | return row_delect; 322 | } 323 | 324 | void runCommand(String command) { 325 | Thread standReadThread = null; 326 | Thread errorReadThread = null; 327 | try { 328 | final Process p = Runtime.getRuntime().exec(command, null); 329 | standReadThread = new Thread() { 330 | public void run() { 331 | InputStream is = p.getInputStream(); 332 | BufferedReader localBufferedReader = new BufferedReader(new InputStreamReader(is)); 333 | while (true) { 334 | String line; 335 | try { 336 | line = localBufferedReader.readLine(); 337 | // System.out.println("stand "+line); 338 | if (line == null) { 339 | break; 340 | } 341 | } catch (IOException e) { 342 | e.printStackTrace(); 343 | break; 344 | } 345 | } 346 | } 347 | }; 348 | standReadThread.start(); 349 | 350 | errorReadThread = new Thread() { 351 | public void run() { 352 | InputStream is = p.getErrorStream(); 353 | BufferedReader localBufferedReader = new BufferedReader(new InputStreamReader(is)); 354 | while (true) { 355 | String line; 356 | try { 357 | line = localBufferedReader.readLine(); 358 | if (line == null) { 359 | break; 360 | } else { 361 | // System.out.println("error "+line); 362 | } 363 | } catch (IOException e) { 364 | e.printStackTrace(); 365 | // error(); 366 | break; 367 | } 368 | } 369 | } 370 | }; 371 | errorReadThread.start(); 372 | standReadThread.join(); 373 | errorReadThread.join(); 374 | p.waitFor(); 375 | } catch (Exception e) { 376 | e.printStackTrace(); 377 | // error(); 378 | } 379 | } 380 | 381 | String readFileData(String path) { 382 | String content = null; 383 | FileInputStream fis = null; 384 | DataInputStream dis = null; 385 | try { 386 | File file = new File(path); 387 | fis = new FileInputStream(file); 388 | dis = new DataInputStream(fis); 389 | byte[] data = new byte[(int) file.length()]; 390 | dis.readFully(data); 391 | content = new String(data, "utf-8"); 392 | } catch (Exception e) { 393 | // e.printStackTrace(); 394 | } finally { 395 | if (dis != null) { 396 | try { 397 | dis.close(); 398 | } catch (IOException e) { 399 | e.printStackTrace(); 400 | } 401 | } 402 | } 403 | return content; 404 | } 405 | 406 | public int getRoutePort() { 407 | return routePort; 408 | } 409 | 410 | } 411 | -------------------------------------------------------------------------------- /src/main/java/net/fs/server/MapTunnelProcessor.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 D1SM.net 2 | package net.fs.server; 3 | 4 | import com.alibaba.fastjson.JSONObject; 5 | 6 | import net.fs.client.Pipe; 7 | import net.fs.rudp.ConnectionProcessor; 8 | import net.fs.rudp.ConnectionUDP; 9 | import net.fs.rudp.Constant; 10 | import net.fs.rudp.Route; 11 | import net.fs.rudp.UDPInputStream; 12 | import net.fs.rudp.UDPOutputStream; 13 | import net.fs.utils.MLog; 14 | 15 | import java.io.IOException; 16 | import java.io.InputStream; 17 | import java.io.OutputStream; 18 | import java.net.Socket; 19 | 20 | 21 | public class MapTunnelProcessor implements ConnectionProcessor{ 22 | 23 | Socket dstSocket=null; 24 | 25 | boolean closed=false; 26 | 27 | MapTunnelProcessor pc; 28 | 29 | ConnectionUDP conn; 30 | 31 | 32 | UDPInputStream tis; 33 | 34 | UDPOutputStream tos; 35 | 36 | InputStream sis; 37 | 38 | OutputStream sos; 39 | 40 | public void process(final ConnectionUDP conn){ 41 | this.conn=conn; 42 | pc=this; 43 | Route.es.execute(new Runnable(){ 44 | public void run(){ 45 | process(); 46 | } 47 | }); 48 | } 49 | 50 | 51 | void process(){ 52 | 53 | tis=conn.uis; 54 | tos=conn.uos; 55 | 56 | byte[] headData; 57 | try { 58 | headData = tis.read2(); 59 | String hs=new String(headData,"utf-8"); 60 | JSONObject requestJSon=JSONObject.parseObject(hs); 61 | final int dstPort=requestJSon.getIntValue("dst_port"); 62 | String message=""; 63 | JSONObject responeJSon=new JSONObject(); 64 | int code=Constant.CODE_FAILED; 65 | code=Constant.CODE_SUCCESS; 66 | responeJSon.put("code", code); 67 | responeJSon.put("message", message); 68 | byte[] responeData=responeJSon.toJSONString().getBytes("utf-8"); 69 | tos.write(responeData, 0, responeData.length); 70 | if(code!=Constant.CODE_SUCCESS){ 71 | close(); 72 | return; 73 | } 74 | dstSocket = new Socket("127.0.0.1", dstPort); 75 | dstSocket.setTcpNoDelay(true); 76 | sis=dstSocket.getInputStream(); 77 | sos=dstSocket.getOutputStream(); 78 | 79 | final Pipe p1=new Pipe(); 80 | final Pipe p2=new Pipe(); 81 | 82 | Route.es.execute(new Runnable() { 83 | 84 | public void run() { 85 | try { 86 | p1.pipe(sis, tos,100*1024,p2); 87 | }catch (Exception e) { 88 | //e.printStackTrace(); 89 | }finally{ 90 | close(); 91 | if(p1.getReadedLength()==0){ 92 | MLog.println("端口"+dstPort+"无返回数据"); 93 | } 94 | } 95 | } 96 | 97 | }); 98 | Route.es.execute(new Runnable() { 99 | 100 | public void run() { 101 | try { 102 | p2.pipe(tis,sos,100*1024*1024,conn); 103 | }catch (Exception e) { 104 | //e.printStackTrace(); 105 | }finally{ 106 | close(); 107 | } 108 | } 109 | }); 110 | 111 | 112 | } catch (Exception e2) { 113 | //e2.printStackTrace(); 114 | close(); 115 | } 116 | 117 | 118 | 119 | } 120 | 121 | void close(){ 122 | if(!closed){ 123 | closed=true; 124 | if(sis!=null){ 125 | try { 126 | sis.close(); 127 | } catch (IOException e) { 128 | //e.printStackTrace(); 129 | } 130 | } 131 | if(sos!=null){ 132 | try { 133 | sos.close(); 134 | } catch (IOException e) { 135 | //e.printStackTrace(); 136 | } 137 | } 138 | if(tos!=null){ 139 | tos.closeStream_Local(); 140 | } 141 | if(tis!=null){ 142 | tis.closeStream_Local(); 143 | } 144 | if(conn!=null){ 145 | conn.close_local(); 146 | } 147 | if(dstSocket!=null){ 148 | try { 149 | dstSocket.close(); 150 | } catch (IOException e) { 151 | //e.printStackTrace(); 152 | } 153 | } 154 | } 155 | } 156 | 157 | } 158 | -------------------------------------------------------------------------------- /src/main/java/net/fs/utils/ByteIntConvert.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 D1SM.net 2 | package net.fs.utils; 3 | 4 | 5 | public class ByteIntConvert { 6 | 7 | private ByteIntConvert() { 8 | } 9 | 10 | public static int toInt(byte[] b, int offset) { 11 | return b[offset + 3] & 0xff | (b[offset + 2] & 0xff) << 8 12 | | (b[offset + 1] & 0xff) << 16 | (b[offset] & 0xff) << 24; 13 | } 14 | 15 | public static void toByteArray(int n,byte[] buf,int offset) { 16 | buf[offset] = (byte) (n >> 24); 17 | buf[offset + 1] = (byte) (n >> 16); 18 | buf[offset + 2] = (byte) (n >> 8); 19 | buf[offset + 3] = (byte) n; 20 | } 21 | 22 | } 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /src/main/java/net/fs/utils/ByteShortConvert.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 D1SM.net 2 | package net.fs.utils; 3 | 4 | public final class ByteShortConvert { 5 | 6 | private ByteShortConvert() { 7 | } 8 | 9 | public static byte[] toByteArray(short i, byte[] b, int offset) { 10 | b[offset] = (byte) (i >> 8); 11 | b[offset + 1] = (byte) (i >> 0); 12 | return b; 13 | } 14 | 15 | 16 | 17 | public static short toShort(byte[] b,int offset) { 18 | return (short) (((b[offset] << 8) | b[offset + 1] & 0xff)); 19 | } 20 | 21 | //无符号 22 | public static byte[] toByteArrayUnsigned(int s,byte[] b,int offset) { 23 | b[offset] = (byte) (s >> 8); 24 | b[offset+1] = (byte) (s >> 0); 25 | return b; 26 | } 27 | 28 | //无符号 29 | public static int toShortUnsigned(byte[] b,int offset) { 30 | int i = 0; 31 | i |= b[offset+0] & 0xFF; 32 | i <<= 8; 33 | i |= b[offset+1] & 0xFF; 34 | return i; 35 | } 36 | 37 | 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/net/fs/utils/LogListener.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 D1SM.net 2 | package net.fs.utils; 3 | 4 | public interface LogListener { 5 | 6 | public void onAppendContent(LogOutputStream los, String text); 7 | 8 | } 9 | -------------------------------------------------------------------------------- /src/main/java/net/fs/utils/LogOutputStream.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 D1SM.net 2 | package net.fs.utils; 3 | 4 | import java.io.OutputStream; 5 | import java.io.PrintStream; 6 | import java.util.HashSet; 7 | import java.util.Set; 8 | 9 | public class LogOutputStream extends PrintStream{ 10 | 11 | Set listeners=new HashSet(); 12 | 13 | StringBuffer buffer=new StringBuffer(); 14 | 15 | public LogOutputStream(OutputStream out) { 16 | super(out); 17 | } 18 | 19 | @Override 20 | public void write(byte[] buf, int off, int len) { 21 | super.write(buf, off, len); 22 | fireEvent(new String(buf, off, len)); 23 | } 24 | 25 | private void fireEvent(String text){ 26 | if(buffer!=null&&buffer.length()<10000){ 27 | buffer.append(text); 28 | } 29 | for(LogListener listener:listeners){ 30 | listener.onAppendContent(this,text); 31 | } 32 | } 33 | 34 | public void addListener(LogListener listener){ 35 | listeners.add(listener); 36 | } 37 | 38 | public void remvoeListener(LogListener listener){ 39 | listeners.remove(listener); 40 | } 41 | 42 | public StringBuffer getBuffer() { 43 | return buffer; 44 | } 45 | 46 | public void setBuffer(StringBuffer buffer) { 47 | this.buffer = buffer; 48 | } 49 | 50 | 51 | } 52 | -------------------------------------------------------------------------------- /src/main/java/net/fs/utils/MLog.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 D1SM.net 2 | package net.fs.utils; 3 | 4 | 5 | public class MLog { 6 | 7 | public static void info(Object str){ 8 | System.out.println(str); 9 | } 10 | 11 | // public static void println(Object str){ 12 | // System.out.println(str); 13 | // } 14 | 15 | public static void println(String str){ 16 | System.out.println(str); 17 | } 18 | 19 | // public static void println(){ 20 | // System.out.println(); 21 | // } 22 | // 23 | // public static void print(String str){ 24 | // System.out.print(str); 25 | // } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/net/fs/utils/MessageCheck.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 D1SM.net 2 | package net.fs.utils; 3 | 4 | import java.net.DatagramPacket; 5 | 6 | 7 | public class MessageCheck{ 8 | public static int checkVer(DatagramPacket dp){ 9 | int ver=ByteShortConvert.toShort(dp.getData(), 0); 10 | return ver; 11 | } 12 | public static int checkSType(DatagramPacket dp){ 13 | int sType=ByteShortConvert.toShort(dp.getData(), 2); 14 | return sType; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/net/fs/utils/NetStatus.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.utils; 21 | 22 | import java.util.List; 23 | import java.util.Vector; 24 | 25 | 26 | public class NetStatus { 27 | 28 | public long uploadSum; 29 | public long downloadSum; 30 | 31 | Thread mainThread; 32 | 33 | int averageTime; 34 | 35 | List speedList; 36 | SpeedUnit currentUnit; 37 | 38 | public int upSpeed=0; 39 | public int downSpeed=0; 40 | 41 | public NetStatus(){ 42 | this(2); 43 | } 44 | 45 | public NetStatus(int averageTime){ 46 | this.averageTime=averageTime; 47 | speedList=new Vector(); 48 | for(int i=0;i1000){ 61 | ////#MLog.println("yyyyyyyyyyy "); 62 | lastTime=System.currentTimeMillis(); 63 | calcuSpeed(); 64 | } 65 | try { 66 | Thread.sleep(100); 67 | } catch (InterruptedException e) { 68 | // e.printStackTrace(); 69 | break; 70 | } 71 | } 72 | } 73 | }; 74 | mainThread.start(); 75 | } 76 | 77 | public void stop(){ 78 | mainThread.interrupt(); 79 | } 80 | 81 | 82 | public int getUpSpeed() { 83 | return upSpeed; 84 | } 85 | 86 | public void setUpSpeed(int upSpeed) { 87 | this.upSpeed = upSpeed; 88 | } 89 | 90 | public int getDownSpeed() { 91 | return downSpeed; 92 | } 93 | 94 | public void setDownSpeed(int downSpeed) { 95 | this.downSpeed = downSpeed; 96 | } 97 | 98 | 99 | void calcuSpeed(){ 100 | int ds = 0,us=0; 101 | for(SpeedUnit unit:speedList){ 102 | ds+=unit.downSum; 103 | us+=unit.upSum; 104 | } 105 | upSpeed=(int) ((float)us/speedList.size()); 106 | downSpeed=(int)(float)ds/speedList.size(); 107 | 108 | speedList.remove(0); 109 | SpeedUnit unit=new SpeedUnit(); 110 | currentUnit=unit; 111 | speedList.add(unit); 112 | } 113 | 114 | public void addDownload(int sum){ 115 | downloadSum+=sum; 116 | currentUnit.addDown(sum); 117 | } 118 | 119 | public void addUpload(int sum){ 120 | uploadSum+=sum; 121 | currentUnit.addUp(sum); 122 | } 123 | 124 | public void sendAvail(){ 125 | 126 | } 127 | 128 | public void receiveAvail(){ 129 | 130 | } 131 | 132 | public void setUpLimite(int speed){ 133 | 134 | } 135 | 136 | public void setDownLimite(int speed){ 137 | 138 | } 139 | } 140 | 141 | 142 | class SpeedUnit{ 143 | int downSum; 144 | int upSum; 145 | SpeedUnit(){ 146 | 147 | } 148 | 149 | void addUp(int n){ 150 | upSum+=n; 151 | } 152 | 153 | void addDown(int n){ 154 | downSum+=n; 155 | } 156 | } 157 | 158 | -------------------------------------------------------------------------------- /src/main/java/net/fs/utils/Tools.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 D1SM.net 2 | package net.fs.utils; 3 | 4 | import java.net.HttpURLConnection; 5 | import java.net.URL; 6 | 7 | import javax.net.ssl.HostnameVerifier; 8 | import javax.net.ssl.HttpsURLConnection; 9 | import javax.net.ssl.SSLSession; 10 | 11 | 12 | public class Tools { 13 | 14 | private Tools() { 15 | } 16 | 17 | public static HttpURLConnection getConnection(String urlString) throws Exception{ 18 | URL url = new URL(urlString); 19 | HttpURLConnection conn = null; 20 | if(urlString.startsWith("http://")){ 21 | conn = (HttpURLConnection) url.openConnection(); 22 | }else if(urlString.startsWith("https://")){ 23 | HttpsURLConnection conns=(HttpsURLConnection)url.openConnection(); 24 | conns.setHostnameVerifier(new HostnameVerifier() { 25 | public boolean verify(String hostname, SSLSession session) { 26 | return true; 27 | } 28 | }); 29 | conn=conns; 30 | } 31 | if(conn!=null){ 32 | conn.setConnectTimeout(10*1000); 33 | conn.setReadTimeout(10*1000); 34 | conn.setRequestMethod("POST"); 35 | conn.setDoInput(true); 36 | conn.setDoOutput(true); 37 | conn.setUseCaches(false); 38 | } 39 | return conn; 40 | } 41 | 42 | public static String getMD5(String str) { 43 | byte[] source=str.getBytes(); 44 | return getMD5(source); 45 | } 46 | 47 | public static String getMD5(byte[] source) { 48 | String s = null; 49 | char hexDigits[] = { 50 | '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; 51 | try 52 | { 53 | java.security.MessageDigest md = java.security.MessageDigest.getInstance( "MD5" ); 54 | md.update( source ); 55 | byte tmp[] = md.digest(); 56 | char str[] = new char[16 * 2]; 57 | int k = 0; 58 | for (int i = 0; i < 16; i++) { 59 | byte byte0 = tmp[i]; 60 | str[k++] = hexDigits[byte0 >>> 4 & 0xf]; 61 | str[k++] = hexDigits[byte0 & 0xf]; 62 | } 63 | s = new String(str); 64 | 65 | }catch( Exception e ) 66 | { 67 | e.printStackTrace(); 68 | } 69 | return s; 70 | } 71 | 72 | 73 | public static String getSizeStringKB(long size){ 74 | int gb=(int) (size/(1024*1024*1024)); 75 | int gbl=(int) (size%(1024*1024*1024)); 76 | int mb=gbl/(1024*1024); 77 | int mbl=gbl%(1024*1024); 78 | int kb=mbl/(1024); 79 | String ls=""; 80 | if(gb>0){ 81 | ls+=gb+","; 82 | } 83 | if(mb>0){ 84 | String mbs=""; 85 | if(gb>0){ 86 | if(mb<10){ 87 | mbs+="00"; 88 | }else if(mb<100){ 89 | mbs+="0"; 90 | } 91 | } 92 | mbs+=mb; 93 | ls+=mbs+","; 94 | }else{ 95 | if(gb>0){ 96 | ls+="000,"; 97 | } 98 | } 99 | 100 | if(kb>0){ 101 | String kbs=""; 102 | if(gb>0|mb>0){ 103 | if(kb<10){ 104 | kbs+="00"; 105 | }else if(kb<100){ 106 | kbs+="0"; 107 | } 108 | } 109 | kbs+=kb; 110 | ls+=kbs+" KB"; 111 | }else{ 112 | if(mb>0|gb>0){ 113 | ls+="000 KB"; 114 | } 115 | } 116 | if(size==0){ 117 | ls+=0+" KB"; 118 | } 119 | if(size<1024){ 120 | //ls=size+" b"; 121 | ls=0+" KB"; 122 | } 123 | return ls; 124 | } 125 | 126 | } 127 | --------------------------------------------------------------------------------