├── .classpath ├── .gitignore ├── .project ├── LICENSE ├── README.md ├── ipseccmd.exe ├── lib ├── fastjson-1.1.6.jar ├── fsclient.jar ├── jna.jar ├── miglayout-swing.jar ├── pcap4j-core.jar ├── pcap4j-packetfactory-static.jar ├── slf4j-api-1.6.6.jar └── slf4j-nop-1.6.1.jar └── src └── net └── fs ├── cap ├── CapEnv.java ├── CapServer.java ├── CustomTcpSackOption.java ├── IPacket.java ├── PacketUtils.java ├── SendRecord.java ├── TCPTun.java ├── TunData.java ├── TunManager.java └── VDatagramSocket.java ├── client ├── AddMapFrame.java ├── AlignCellRenderer.java ├── ClientConfig.java ├── ClientNoUI.java ├── ClientStartNoUI.java ├── ClientUI.java ├── ClientUII.java ├── FSClient.java ├── MapClient.java ├── MapRule.java ├── MapRuleListModel.java ├── MapRuleListTable.java ├── MapRuleRender.java ├── Pipe.java ├── PortMapManager.java ├── PortMapProcess.java ├── SpeedSetFrame.java └── TextComponentPopupMenu.java ├── rudp ├── AckListManage.java ├── AckListTask.java ├── ClientControl.java ├── ClientManager.java ├── ClientProcessorInterface.java ├── ConnInfo.java ├── ConnectException.java ├── ConnectionProcessor.java ├── ConnectionUDP.java ├── Constant.java ├── CopiedIterator.java ├── MapSocketPorcessor.java ├── MessageInterface.java ├── PipeListener.java ├── RUDPConfig.java ├── ReceivePingException.java ├── Receiver.java ├── ResendItem.java ├── ResendManage.java ├── Route.java ├── SendRecord.java ├── Sender.java ├── StreamPipe.java ├── TrafficEvent.java ├── Trafficlistener.java ├── UDPInputStream.java ├── UDPOutputStream.java └── message │ ├── AckListMessage.java │ ├── CloseMessage_Conn.java │ ├── CloseMessage_Stream.java │ ├── DataMessage.java │ ├── Message.java │ ├── MessageType.java │ ├── PingMessage.java │ └── PingMessage2.java ├── server ├── FSServer.java └── MapTunnelProcessor.java └── utils ├── ByteIntConvert.java ├── ByteShortConvert.java ├── MLog.java ├── MessageCheck.java ├── NetStatus.java └── Tools.java /.classpath: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /bin/ 2 | /client_config.json 3 | /port_map.json 4 | *.iml 5 | .idea/ -------------------------------------------------------------------------------- /.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | finalspeed 4 | 5 | 6 | 7 | 8 | 9 | org.eclipse.jdt.core.javabuilder 10 | 11 | 12 | 13 | 14 | 15 | org.eclipse.jdt.core.javanature 16 | 17 | 18 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # finalspeed 2 | FinalSpeed是高速双边加速软件,可加速所有基于tcp协议的网络服务,在高丢包和高延迟环境下,仍可达到90%的物理带宽利用率,即使高峰时段也能轻松跑满带宽. 3 | 4 | ### 安装教程 5 | [客户端安装说明](http://www.d1sm.net/thread-7-1-1.html) 6 |
7 | [服务端安装说明](http://www.d1sm.net/thread-8-1-1.html) 8 | 9 | 10 | ### 命令行版本的客户端 11 | 默认是图形化版本的客户端,不方便部署在服务器。如果需要命令行版本的,请在 [Releases](https://github.com/zqhong/finalspeed/releases) 中下载。 12 | 13 | 14 | 要求 15 | * 管理员运行权限 16 | * jre >= 1.6(如果下载上面提供的客户端的话) 17 | 18 | 使用方法:`sudo java -jar client.jar`。如果在 Windows 下,则需要使用管理员运行。 19 | 20 | 配置文件 - clien_config.json 21 | ``` 22 | { 23 | // 下载速度,单位是 B,字节。这里换算起来就是 11MB。请把这里改成本机的下载速度 24 | "download_speed": 11200698, 25 | // 协议:tcp 或 udp。注意:服务端如果是 OpenVZ 架构的话,则只支持 udp。 26 | "protocal": "udp", 27 | // 服务器地址 28 | "server_address": "1.2.3.4", 29 | // 一般不需要更改,保持默认即可。 30 | "server_port": 150, 31 | // 不需要更改,保持默认即可。 32 | "socks5_port": 1083, 33 | // 上传速度,单位是 B,字节。 34 | "upload_speed": 357469 35 | } 36 | ``` 37 | 38 | 配置文件 - port_map.json 39 | ``` 40 | { 41 | "map_list": [ 42 | { 43 | // 要加速的服务器端口 44 | "dst_port": 12345, 45 | // 本地端口 46 | "listen_port": 1099, 47 | // 备注信息 48 | "name": "ss" 49 | }, 50 | { 51 | "dst_port": 23456, 52 | "listen_port": 2200, 53 | "name": "ssh" 54 | } 55 | ] 56 | } 57 | ``` 58 | 59 | > 注意:这两个配置文件不能删除,不然会弹出配置文件的窗口。(没有完全去掉图形化界面的缘故) 60 | 61 | 62 | ### 其他信息 63 | 项目运行需要安装libpcap,windows下为winpcap. 64 | 65 | 客户端启动类: net.fs.client.FSClient 66 | 67 | 服务端启动类: net.fs.server.FSServer 68 | 69 | 论坛 http://www.d1sm.net/forum-44-1.html 70 | 71 | #### 感谢 72 | 该项目 fork 自 [dlsm/finalspeed](https://github.com/d1sm/finalspeed),感谢作者的辛勤付出。 73 | -------------------------------------------------------------------------------- /ipseccmd.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zqhong/finalspeed/6bd98942e992f6bbebdc8cf3631298ba25c53b3b/ipseccmd.exe -------------------------------------------------------------------------------- /lib/fastjson-1.1.6.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zqhong/finalspeed/6bd98942e992f6bbebdc8cf3631298ba25c53b3b/lib/fastjson-1.1.6.jar -------------------------------------------------------------------------------- /lib/fsclient.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zqhong/finalspeed/6bd98942e992f6bbebdc8cf3631298ba25c53b3b/lib/fsclient.jar -------------------------------------------------------------------------------- /lib/jna.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zqhong/finalspeed/6bd98942e992f6bbebdc8cf3631298ba25c53b3b/lib/jna.jar -------------------------------------------------------------------------------- /lib/miglayout-swing.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zqhong/finalspeed/6bd98942e992f6bbebdc8cf3631298ba25c53b3b/lib/miglayout-swing.jar -------------------------------------------------------------------------------- /lib/pcap4j-core.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zqhong/finalspeed/6bd98942e992f6bbebdc8cf3631298ba25c53b3b/lib/pcap4j-core.jar -------------------------------------------------------------------------------- /lib/pcap4j-packetfactory-static.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zqhong/finalspeed/6bd98942e992f6bbebdc8cf3631298ba25c53b3b/lib/pcap4j-packetfactory-static.jar -------------------------------------------------------------------------------- /lib/slf4j-api-1.6.6.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zqhong/finalspeed/6bd98942e992f6bbebdc8cf3631298ba25c53b3b/lib/slf4j-api-1.6.6.jar -------------------------------------------------------------------------------- /lib/slf4j-nop-1.6.1.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zqhong/finalspeed/6bd98942e992f6bbebdc8cf3631298ba25c53b3b/lib/slf4j-nop-1.6.1.jar -------------------------------------------------------------------------------- /src/net/fs/cap/CapServer.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 D1SM.net 2 | 3 | package net.fs.cap; 4 | 5 | 6 | public class CapServer { 7 | 8 | CapServer(){ 9 | CapEnv capEnv=null; 10 | try { 11 | capEnv=new CapEnv(false); 12 | capEnv.init(); 13 | } catch (Exception e) { 14 | e.printStackTrace(); 15 | } 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /src/net/fs/cap/CustomTcpSackOption.java: -------------------------------------------------------------------------------- 1 | /*_########################################################################## 2 | _## 3 | _## Copyright (C) 2014 Pcap4J.org 4 | _## 5 | _########################################################################## 6 | */ 7 | 8 | package net.fs.cap; 9 | 10 | import static org.pcap4j.util.ByteArrays.*; 11 | 12 | import java.io.Serializable; 13 | import java.util.ArrayList; 14 | import java.util.List; 15 | 16 | import org.pcap4j.packet.IllegalRawDataException; 17 | import org.pcap4j.packet.LengthBuilder; 18 | import org.pcap4j.packet.TcpPacket.TcpOption; 19 | import org.pcap4j.packet.namednumber.TcpOptionKind; 20 | import org.pcap4j.util.ByteArrays; 21 | 22 | /** 23 | * @author Kaito Yamada 24 | * @since pcap4j 1.2.0 25 | */ 26 | public final class CustomTcpSackOption implements TcpOption { 27 | 28 | /* 29 | * http://tools.ietf.org/html/rfc2018 30 | * 31 | * +--------+--------+ 32 | * | Kind=5 | Length | 33 | * +--------+--------+--------+--------+ 34 | * | Left Edge of 1st Block | 35 | * +--------+--------+--------+--------+ 36 | * | Right Edge of 1st Block | 37 | * +--------+--------+--------+--------+ 38 | * | | 39 | * / . . . / 40 | * | | 41 | * +--------+--------+--------+--------+ 42 | * | Left Edge of nth Block | 43 | * +--------+--------+--------+--------+ 44 | * | Right Edge of nth Block | 45 | * +--------+--------+--------+--------+ 46 | */ 47 | 48 | /** 49 | * 50 | */ 51 | private static final long serialVersionUID = -3308738405807657257L; 52 | 53 | private final TcpOptionKind kind = TcpOptionKind.SACK; 54 | private final byte length; 55 | private final List sacks = new ArrayList(); 56 | 57 | /** 58 | * A static factory method. 59 | * This method validates the arguments by {@link ByteArrays#validateBounds(byte[], int, int)}, 60 | * which may throw exceptions undocumented here. 61 | * 62 | * @param rawData rawData 63 | * @param offset offset 64 | * @param length length 65 | * @return a new TcpSackOption object. 66 | * @throws IllegalRawDataException if parsing the raw data fails. 67 | */ 68 | public static CustomTcpSackOption newInstance( 69 | byte[] rawData, int offset, int length 70 | ) throws IllegalRawDataException { 71 | ByteArrays.validateBounds(rawData, offset, length); 72 | return new CustomTcpSackOption(rawData, offset, length); 73 | } 74 | 75 | private CustomTcpSackOption(byte[] rawData, int offset, int length) throws IllegalRawDataException { 76 | if (length < 2) { 77 | StringBuilder sb = new StringBuilder(50); 78 | sb.append("The raw data length must be more than 1. rawData: ") 79 | .append(ByteArrays.toHexString(rawData, " ")) 80 | .append(", offset: ") 81 | .append(offset) 82 | .append(", length: ") 83 | .append(length); 84 | throw new IllegalRawDataException(sb.toString()); 85 | } 86 | if (rawData[offset] != kind.value()) { 87 | StringBuilder sb = new StringBuilder(100); 88 | sb.append("The kind must be: ") 89 | .append(kind.valueAsString()) 90 | .append(" rawData: ") 91 | .append(ByteArrays.toHexString(rawData, " ")) 92 | .append(", offset: ") 93 | .append(offset) 94 | .append(", length: ") 95 | .append(length); 96 | throw new IllegalRawDataException(sb.toString()); 97 | } 98 | 99 | this.length = rawData[1 + offset]; 100 | int lengthFieldAsInt = getLengthAsInt(); 101 | if (lengthFieldAsInt < 2) { 102 | throw new IllegalRawDataException( 103 | "The value of length field must be more than 1 but: " + lengthFieldAsInt 104 | ); 105 | } 106 | 107 | if ((lengthFieldAsInt - 2) % (INT_SIZE_IN_BYTES * 2) != 0) { 108 | StringBuilder sb = new StringBuilder(100); 109 | sb.append( 110 | "The value of length field must be an integer multiple of 8 octets long but: " 111 | ) 112 | .append(lengthFieldAsInt); 113 | throw new IllegalRawDataException(sb.toString()); 114 | } 115 | if (length < lengthFieldAsInt) { 116 | StringBuilder sb = new StringBuilder(100); 117 | sb.append("rawData is too short. length field: ") 118 | .append(lengthFieldAsInt) 119 | .append(", rawData: ") 120 | .append(ByteArrays.toHexString(rawData, " ")) 121 | .append(", offset: ") 122 | .append(offset) 123 | .append(", length: ") 124 | .append(length); 125 | throw new IllegalRawDataException(sb.toString()); 126 | } 127 | 128 | for (int i = 2; i < lengthFieldAsInt; i += INT_SIZE_IN_BYTES * 2) { 129 | sacks.add( 130 | new Sack( 131 | ByteArrays.getInt(rawData, i + offset), 132 | ByteArrays.getInt(rawData, i + INT_SIZE_IN_BYTES + offset) 133 | ) 134 | ); 135 | } 136 | } 137 | 138 | private CustomTcpSackOption(Builder builder) { 139 | if ( 140 | builder == null 141 | || builder.sacks == null 142 | ) { 143 | StringBuilder sb = new StringBuilder(); 144 | sb.append("builder: ").append(builder) 145 | .append(" builder.sacks: ").append(builder.sacks); 146 | throw new NullPointerException(sb.toString()); 147 | } 148 | 149 | this.sacks.addAll(builder.sacks); 150 | 151 | if (builder.correctLengthAtBuild) { 152 | this.length = (byte)length(); 153 | } 154 | else { 155 | this.length = builder.length; 156 | } 157 | } 158 | 159 | @Override 160 | public TcpOptionKind getKind() { 161 | return kind; 162 | } 163 | 164 | /** 165 | * 166 | * @return length 167 | */ 168 | public byte getLength() { return length; } 169 | 170 | /** 171 | * 172 | * @return length 173 | */ 174 | public int getLengthAsInt() { return 0xFF & length; } 175 | 176 | @Override 177 | public int length() { 178 | return sacks.size() * INT_SIZE_IN_BYTES * 2 + 2; 179 | } 180 | 181 | @Override 182 | public byte[] getRawData() { 183 | byte[] rawData = new byte[length()]; 184 | rawData[0] = kind.value(); 185 | rawData[1] = length; 186 | 187 | int offset = 2; 188 | for (Sack sack: sacks) { 189 | System.arraycopy( 190 | ByteArrays.toByteArray(sack.leftEdge), 0, 191 | rawData, offset, INT_SIZE_IN_BYTES 192 | ); 193 | System.arraycopy( 194 | ByteArrays.toByteArray(sack.rightEdge), 0, 195 | rawData, offset + INT_SIZE_IN_BYTES, INT_SIZE_IN_BYTES 196 | ); 197 | offset += INT_SIZE_IN_BYTES * 2; 198 | } 199 | 200 | return rawData; 201 | } 202 | 203 | /** 204 | * 205 | * @return a new Builder object populated with this object's fields. 206 | */ 207 | public Builder getBuilder() { 208 | return new Builder(this); 209 | } 210 | 211 | @Override 212 | public String toString() { 213 | StringBuilder sb = new StringBuilder(); 214 | sb.append("[Kind: ") 215 | .append(kind); 216 | sb.append("] [Length: ") 217 | .append(getLengthAsInt()) 218 | .append(" bytes]"); 219 | for (Sack sack: sacks) { 220 | sb.append(" [LE: ") 221 | .append(sack.getLeftEdgeAsLong()) 222 | .append(" RE: ") 223 | .append(sack.getRightEdgeAsLong()) 224 | .append("]"); 225 | } 226 | return sb.toString(); 227 | } 228 | 229 | @Override 230 | public boolean equals(Object obj) { 231 | if (obj == this) { return true; } 232 | if (!this.getClass().isInstance(obj)) { return false; } 233 | 234 | CustomTcpSackOption other = (CustomTcpSackOption)obj; 235 | return 236 | length == other.length 237 | && sacks.equals(other.sacks); 238 | } 239 | 240 | public List getSacks() { 241 | return sacks; 242 | } 243 | 244 | @Override 245 | public int hashCode() { 246 | int result = 17; 247 | result = 31 * result + length; 248 | result = 31 * result + sacks.hashCode(); 249 | return result; 250 | } 251 | 252 | /** 253 | * @author Kaito Yamada 254 | * @since pcap4j 1.2.0 255 | */ 256 | public static final class Builder 257 | implements LengthBuilder { 258 | 259 | private byte length; 260 | private boolean correctLengthAtBuild; 261 | private List sacks; 262 | 263 | /** 264 | * 265 | */ 266 | public Builder() {} 267 | 268 | private Builder(CustomTcpSackOption option) { 269 | this.length = option.length; 270 | } 271 | 272 | /** 273 | * @param length length 274 | * @return this Builder object for method chaining. 275 | */ 276 | public Builder length(byte length) { 277 | this.length = length; 278 | return this; 279 | } 280 | 281 | /** 282 | * @param sacks sacks 283 | * @return this Builder object for method chaining. 284 | */ 285 | public Builder sacks(List sacks) { 286 | this.sacks = sacks; 287 | return this; 288 | } 289 | 290 | @Override 291 | public Builder correctLengthAtBuild(boolean correctLengthAtBuild) { 292 | this.correctLengthAtBuild = correctLengthAtBuild; 293 | return this; 294 | } 295 | 296 | @Override 297 | public CustomTcpSackOption build() { 298 | return new CustomTcpSackOption(this); 299 | } 300 | 301 | } 302 | 303 | /** 304 | * @author Kaito Yamada 305 | * @since pcap4j 1.2.0 306 | */ 307 | public static final class Sack implements Serializable { 308 | 309 | /** 310 | * 311 | */ 312 | private static final long serialVersionUID = 1218420566089129438L; 313 | 314 | private final int leftEdge; 315 | private final int rightEdge; 316 | 317 | /** 318 | * @param leftEdge leftEdge 319 | * @param rightEdge rightEdge 320 | */ 321 | public Sack(int leftEdge, int rightEdge) { 322 | this.leftEdge = leftEdge; 323 | this.rightEdge = rightEdge; 324 | } 325 | 326 | /** 327 | * @return leftEdge 328 | */ 329 | public int getLeftEdge() { 330 | return leftEdge; 331 | } 332 | 333 | /** 334 | * @return leftEdge 335 | */ 336 | public long getLeftEdgeAsLong() { 337 | return 0xFFFFFFFFL & leftEdge; 338 | } 339 | 340 | /** 341 | * @return rightEdge 342 | */ 343 | public int getRightEdge() { 344 | return rightEdge; 345 | } 346 | 347 | /** 348 | * @return rightEdge 349 | */ 350 | public long getRightEdgeAsLong() { 351 | return 0xFFFFFFFFL & rightEdge; 352 | } 353 | 354 | @Override 355 | public boolean equals(Object obj) { 356 | if (obj == this) { return true; } 357 | if (!this.getClass().isInstance(obj)) { return false; } 358 | 359 | Sack other = (Sack)obj; 360 | return 361 | leftEdge == other.leftEdge 362 | && rightEdge == other.rightEdge; 363 | } 364 | 365 | @Override 366 | public int hashCode() { 367 | int result = 17; 368 | result = 31 * result + leftEdge; 369 | result = 31 * result + rightEdge; 370 | return result; 371 | } 372 | 373 | } 374 | 375 | } 376 | -------------------------------------------------------------------------------- /src/net/fs/cap/IPacket.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 D1SM.net 2 | 3 | package net.fs.cap; 4 | 5 | import org.pcap4j.packet.Packet; 6 | 7 | public class IPacket { 8 | 9 | int index; 10 | 11 | int sequence; 12 | 13 | int legth; 14 | 15 | Packet packet; 16 | 17 | long firstSendTime; 18 | 19 | long sendTime; 20 | 21 | long reSendCount; 22 | 23 | } 24 | -------------------------------------------------------------------------------- /src/net/fs/cap/SendRecord.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 D1SM.net 2 | 3 | package net.fs.cap; 4 | 5 | public class SendRecord { 6 | 7 | int sendCount; 8 | 9 | } 10 | -------------------------------------------------------------------------------- /src/net/fs/cap/TCPTun.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 D1SM.net 2 | 3 | package net.fs.cap; 4 | 5 | import java.net.Inet4Address; 6 | import java.net.InetAddress; 7 | import java.util.ArrayList; 8 | import java.util.HashMap; 9 | import java.util.HashSet; 10 | import java.util.Random; 11 | 12 | import net.fs.utils.MLog; 13 | 14 | import org.pcap4j.core.NotOpenException; 15 | import org.pcap4j.core.PcapHandle; 16 | import org.pcap4j.core.PcapNativeException; 17 | import org.pcap4j.packet.EthernetPacket.EthernetHeader; 18 | import org.pcap4j.packet.IpV4Packet.IpV4Header; 19 | import org.pcap4j.packet.Packet; 20 | import org.pcap4j.packet.TcpPacket; 21 | import org.pcap4j.packet.TcpPacket.TcpHeader; 22 | import org.pcap4j.util.MacAddress; 23 | 24 | 25 | public class TCPTun { 26 | 27 | HashMap sendedTable_server=new HashMap (); 28 | HashMap sendedTable_history_server=new HashMap (); 29 | 30 | int clientSequence=Integer.MIN_VALUE; 31 | 32 | static Random random=new Random(); 33 | 34 | PcapHandle sendHandle; 35 | 36 | HashSet selfAckTable=new HashSet(); 37 | 38 | HashMap sendrecordTable=new HashMap(); 39 | 40 | MacAddress dstMacaAddress; 41 | 42 | int sequenceNum=-1; 43 | 44 | Thread sendThread; 45 | 46 | boolean sended=false; 47 | 48 | Packet basePacket_server; 49 | 50 | short baseIdent=100; 51 | 52 | IPacket dst_readed_packet,last_send_packet; 53 | 54 | int presend_server; 55 | 56 | ArrayList packetList=new ArrayList(); 57 | 58 | HashMap packetTable_l=new HashMap(); 59 | 60 | HashMap packetTable=new HashMap(); 61 | 62 | ArrayList unacked_list=new ArrayList(); 63 | 64 | Object syn_packetList=new Object(); 65 | 66 | int max_client_ack=Integer.MIN_VALUE; 67 | 68 | int sendIndex=0; 69 | 70 | long lasSetDelayTime=0; 71 | 72 | long lastDelay=300; 73 | 74 | Object syn_delay=new Object(); 75 | 76 | Thread resendScanThread; 77 | 78 | boolean connectReady=false; 79 | 80 | boolean preDataReady=false; 81 | 82 | CapEnv capEnv; 83 | 84 | public Inet4Address remoteAddress; 85 | public short remotePort; 86 | int remoteStartSequence; 87 | int remoteSequence; 88 | int remoteIdent; 89 | int remoteSequence_max; 90 | 91 | Inet4Address localAddress; 92 | short localPort; 93 | int localStartSequence=random.nextInt(); 94 | int localSequence; 95 | int localIdent=random.nextInt(Short.MAX_VALUE-100); 96 | 97 | Object syn_send_data=new Object(); 98 | 99 | long lastSendAckTime; 100 | 101 | long lastReceiveDataTime; 102 | 103 | long createTime=System.currentTimeMillis();; 104 | 105 | String key; 106 | 107 | Object syn_ident=new Object(); 108 | 109 | //客户端发起 110 | TCPTun(CapEnv capEnv, 111 | Inet4Address serverAddress,short serverPort, 112 | MacAddress srcAddress_mac,MacAddress dstAddrress_mac){ 113 | this.capEnv=capEnv; 114 | sendHandle=capEnv.sendHandle; 115 | this.remoteAddress=serverAddress; 116 | this.remotePort=serverPort; 117 | localAddress=capEnv.local_ipv4; 118 | localPort=(short)(random.nextInt(64*1024-1-10000)+10000); 119 | Packet syncPacket=null; 120 | try { 121 | syncPacket = PacketUtils.createSync(srcAddress_mac, dstAddrress_mac, localAddress, localPort,serverAddress, serverPort, localStartSequence,getIdent()); 122 | try { 123 | sendHandle.sendPacket(syncPacket); 124 | localSequence=localStartSequence+1; 125 | } catch (Exception e) { 126 | e.printStackTrace(); 127 | } 128 | } catch (Exception e1) { 129 | e1.printStackTrace(); 130 | } 131 | //MLog.println("发送第一次握手 "+" ident "+localIdent); 132 | MLog.println(""+syncPacket); 133 | 134 | } 135 | 136 | //服务端接收 137 | TCPTun(CapEnv capServerEnv, 138 | Inet4Address remoteAddress,short remotePort){ 139 | this.capEnv=capServerEnv; 140 | this.remoteAddress=remoteAddress; 141 | this.remotePort=remotePort; 142 | sendHandle=capEnv.sendHandle; 143 | localPort=capServerEnv.listenPort; 144 | localAddress=capEnv.local_ipv4; 145 | } 146 | 147 | void init_client(Inet4Address clientAddress,int clientPort, 148 | Inet4Address serverAddress,int serverPort, 149 | int client_start_sequence){ 150 | 151 | } 152 | 153 | void init_server(Inet4Address clientAddress,int clientPort, 154 | Inet4Address serverAddress,int serverPort, 155 | int client_start_sequence,int server_start_sequence){ 156 | 157 | } 158 | 159 | public void process_server(final Packet packet,EthernetHeader ethernetHeader,IpV4Header ipV4Header,TcpPacket tcpPacket,boolean client){ 160 | TcpHeader tcpHeader=tcpPacket.getHeader(); 161 | 162 | if(!preDataReady){ 163 | if(!connectReady){ 164 | //第一次握手 165 | dstMacaAddress=ethernetHeader.getSrcAddr(); 166 | if(tcpHeader.getSyn()&&!tcpHeader.getAck()){ 167 | remoteStartSequence=tcpHeader.getSequenceNumber(); 168 | remoteSequence=remoteStartSequence+1; 169 | remoteSequence_max=remoteSequence; 170 | //MLog.println("接收第一次握手 "+remoteAddress.getHostAddress()+":"+remotePort+"->"+localAddress.getHostAddress()+":"+localPort+" ident "+ipV4Header.getIdentification()); 171 | MLog.println(""+packet); 172 | Packet responePacket=PacketUtils.createSyncAck( 173 | capEnv.local_mac, 174 | capEnv.gateway_mac, 175 | localAddress,(short)localPort, 176 | ipV4Header.getSrcAddr(),tcpHeader.getSrcPort().value(), 177 | tcpHeader.getSequenceNumber()+1,localStartSequence,(short)0 178 | ); 179 | try { 180 | sendHandle.sendPacket(responePacket); 181 | } catch (Exception e) { 182 | e.printStackTrace(); 183 | } 184 | localSequence=localStartSequence+1; 185 | //MLog.println("发送第二次握手 "+capEnv.local_mac+"->"+capEnv.gateway_mac+" "+localAddress+"->"+" ident "+0); 186 | 187 | MLog.println(""+responePacket); 188 | } 189 | 190 | if(!tcpHeader.getSyn()&&tcpHeader.getAck()){ 191 | if(tcpPacket.getPayload()==null){ 192 | //第三次握手,客户端确认 193 | if(tcpHeader.getAcknowledgmentNumber()==localSequence){ 194 | //MLog.println("接收第三次握手 "+" ident "+ipV4Header.getIdentification()); 195 | MLog.println(packet+""); 196 | Thread t1=new Thread(){ 197 | public void run(){ 198 | //startSend(basePacket_server,syc_sequence_client+1); 199 | } 200 | }; 201 | //t1.start(); 202 | connectReady=true; 203 | } 204 | } 205 | //MLog.println("客户端响应preview\n "+packet); 206 | //MLog.println("request "+tcp.ack()); 207 | sendedTable_server.remove(tcpHeader.getAcknowledgmentNumber()); 208 | boolean selfAck=selfAckTable.contains(ipV4Header.getIdentification()); 209 | //MLog.println("客户端确认 "+"selfack "+selfAck+" id "+ipV4Header.getIdentification()+" ack_sequence "+tcpHeader.getAcknowledgmentNumberAsLong()+" "+sendedTable_server.size()+"ppppppp "+tcpHeader); 210 | } 211 | 212 | }else { 213 | if(tcpPacket.getPayload()!=null){ 214 | preDataReady=true; 215 | onReceiveDataPacket( tcpPacket, tcpHeader, ipV4Header ); 216 | byte[] sim=getSimResponeHead(); 217 | sendData(sim); 218 | } 219 | } 220 | }else { 221 | if(tcpPacket.getPayload()!=null){ 222 | onReceiveDataPacket( tcpPacket, tcpHeader, ipV4Header ); 223 | TunData td=new TunData(); 224 | td.tun=this; 225 | td.data=tcpPacket.getPayload().getRawData(); 226 | capEnv.vDatagramSocket.onReceinveFromTun(td); 227 | } 228 | } 229 | if(tcpHeader.getRst()){ 230 | MLog.println("reset packet "+ipV4Header.getIdentification()+" "+tcpHeader.getSequenceNumber()+" "+remoteAddress.getHostAddress()+":"+remotePort+"->"+localAddress.getHostAddress()+":"+localPort+" "+" ident "+ipV4Header.getIdentification()); 231 | } 232 | 233 | } 234 | 235 | public void process_client(CapEnv capEnv,final Packet packet,EthernetHeader ethernetHeader,IpV4Header ipV4Header,TcpPacket tcpPacket,boolean client){ 236 | 237 | TcpHeader tcpHeader=tcpPacket.getHeader(); 238 | byte[] payload=null; 239 | if(tcpPacket.getPayload()!=null){ 240 | payload=tcpPacket.getPayload().getRawData(); 241 | } 242 | 243 | if(!preDataReady){ 244 | if(!connectReady){ 245 | if(tcpHeader.getAck()&&tcpHeader.getSyn()){ 246 | if(tcpHeader.getAcknowledgmentNumber()==(localStartSequence+1)){ 247 | MLog.println("接收第二次握手 "+" ident "+ipV4Header.getIdentification()); 248 | MLog.println(""+packet); 249 | remoteStartSequence=tcpHeader.getSequenceNumber(); 250 | remoteSequence=remoteStartSequence+1; 251 | remoteSequence_max=remoteSequence; 252 | Packet p3=PacketUtils.createAck(capEnv.local_mac, capEnv.gateway_mac, capEnv.local_ipv4, localPort, remoteAddress, remotePort, remoteSequence , localSequence,getIdent()); 253 | try { 254 | sendHandle.sendPacket(p3); 255 | MLog.println("发送第三次握手 "+" ident "+localIdent); 256 | MLog.println(""+p3); 257 | connectReady=true; 258 | 259 | byte[] sim=getSimRequestHead(remotePort); 260 | sendData(sim); 261 | MLog.println("发送请求 "+" ident "+localIdent); 262 | } catch (PcapNativeException e) { 263 | e.printStackTrace(); 264 | } catch (NotOpenException e) { 265 | e.printStackTrace(); 266 | } 267 | } 268 | } 269 | }else { 270 | if(tcpPacket.getPayload()!=null){ 271 | preDataReady=true; 272 | onReceiveDataPacket( tcpPacket, tcpHeader, ipV4Header ); 273 | MLog.println("接收响应 "+" ident "+ipV4Header.getIdentification()); 274 | } 275 | } 276 | 277 | }else { 278 | if(tcpPacket.getPayload()!=null){ 279 | //MLog.println("客户端正式接收数据 "+capClientEnv.vDatagramSocket); 280 | onReceiveDataPacket( tcpPacket, tcpHeader, ipV4Header ); 281 | TunData td=new TunData(); 282 | td.tun=this; 283 | td.data=tcpPacket.getPayload().getRawData(); 284 | capEnv.vDatagramSocket. 285 | onReceinveFromTun(td); 286 | } 287 | } 288 | if(tcpHeader.getRst()){ 289 | MLog.println("reset packet "+ipV4Header.getIdentification()+" "+tcpHeader.getSequenceNumber()+" "+remoteAddress.getHostAddress()+":"+remotePort+"->"+localAddress.getHostAddress()+":"+localPort); 290 | } 291 | 292 | } 293 | 294 | void onReceiveDataPacket(TcpPacket tcpPacket,TcpHeader tcpHeader,IpV4Header ipV4Header ){ 295 | if(System.currentTimeMillis()-lastSendAckTime>1000){ 296 | int rs=tcpHeader.getSequenceNumber()+tcpPacket.getPayload().getRawData().length; 297 | if(rs>remoteSequence_max){ 298 | remoteSequence_max=rs; 299 | } 300 | Packet ackPacket=PacketUtils.createAck( 301 | capEnv.local_mac, 302 | capEnv.gateway_mac, 303 | localAddress,(short)localPort, 304 | ipV4Header.getSrcAddr(),tcpHeader.getSrcPort().value(), 305 | remoteSequence_max, localSequence,getIdent()); 306 | try { 307 | sendHandle.sendPacket(ackPacket); 308 | } catch (Exception e) { 309 | e.printStackTrace(); 310 | 311 | } 312 | lastSendAckTime=System.currentTimeMillis(); 313 | lastReceiveDataTime=System.currentTimeMillis(); 314 | } 315 | } 316 | 317 | void sendData(byte[] data){ 318 | Packet dataPacket=PacketUtils.createDataPacket(capEnv.local_mac, 319 | capEnv.gateway_mac, 320 | localAddress,localPort, 321 | remoteAddress,remotePort, 322 | localSequence,remoteSequence_max, data, (short) getIdent()); 323 | synchronized (syn_send_data) { 324 | try { 325 | sendHandle.sendPacket(dataPacket); 326 | localSequence+=data.length; 327 | } catch (Exception e) { 328 | e.printStackTrace(); 329 | } 330 | } 331 | 332 | } 333 | 334 | short getIdent(){ 335 | synchronized (syn_ident) { 336 | localIdent++; 337 | if(localIdent>=Short.MAX_VALUE){ 338 | localIdent=0; 339 | } 340 | } 341 | return (short) localIdent; 342 | } 343 | 344 | public static byte[] getSimResponeHead(){ 345 | StringBuffer sb=new StringBuffer(); 346 | 347 | sb.append("HTTP/1.1 200 OK"+"\r\n"); 348 | sb.append("Server: Apache/2.2.15 (CentOS)"+"\r\n"); 349 | sb.append("Accept-Ranges: bytes"+"\r\n"); 350 | sb.append("Content-Length: "+(Math.abs(random.nextInt()))+"\r\n"); 351 | sb.append("Connection: Keep-Alive"+"\r\n"); 352 | sb.append("Content-Type: application/octet-stream"+"\r\n"); 353 | sb.append("\r\n"); 354 | 355 | String simRequest=sb.toString(); 356 | byte[] simData=simRequest.getBytes(); 357 | return simData; 358 | } 359 | 360 | public static byte[] getSimRequestHead(int port){ 361 | StringBuffer sb=new StringBuffer(); 362 | String domainName=getRandomString(5+random.nextInt(10))+".com"; 363 | sb.append("GET /"+getRandomString(8+random.nextInt(10))+"."+getRandomString(2+random.nextInt(5))+" HTTP/1.1"+"\r\n"); 364 | sb.append("Accept: application/x-ms-application, image/jpeg, application/xaml+xml, image/gif, image/pjpeg, application/x-ms-xbap, */*"+"\r\n"); 365 | sb.append("Accept-Language: zh-CN"+"\r\n"); 366 | sb.append("Accept-Encoding: gzip, deflate"+"\r\n"); 367 | sb.append("User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:36.0) Gecko/20100101 Firefox/36.0"+"\r\n"); 368 | sb.append("Host: "+domainName+"\r\n"); 369 | sb.append("Connection: Keep-Alive"+"\r\n"); 370 | sb.append("\r\n"); 371 | String simRequest=sb.toString(); 372 | byte[] simData=simRequest.getBytes(); 373 | return simData; 374 | } 375 | 376 | public static String getRandomString(int length) { //length表示生成字符串的长度 377 | String base = "abcdefghkmnopqrstuvwxyz"; 378 | Random random = new Random(); 379 | StringBuffer sb = new StringBuffer(); 380 | for (int i = 0; i < length; i++) { 381 | int number = random.nextInt(base.length()); 382 | sb.append(base.charAt(number)); 383 | } 384 | return sb.toString(); 385 | } 386 | 387 | public InetAddress getSourcrAddress() { 388 | return localAddress; 389 | } 390 | 391 | public int getSourcePort() { 392 | return localPort; 393 | } 394 | 395 | public void setSourcePort(short sourcePort) { 396 | this.localPort = sourcePort; 397 | } 398 | 399 | public boolean isConnectReady() { 400 | return connectReady; 401 | } 402 | 403 | public void setConnectReady(boolean connectReady) { 404 | this.connectReady = connectReady; 405 | } 406 | 407 | public String getKey() { 408 | return key; 409 | } 410 | 411 | public void setKey(String key) { 412 | this.key = key; 413 | } 414 | 415 | } 416 | -------------------------------------------------------------------------------- /src/net/fs/cap/TunData.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 D1SM.net 2 | 3 | package net.fs.cap; 4 | 5 | 6 | public class TunData { 7 | 8 | TCPTun tun; 9 | 10 | byte[] data; 11 | 12 | } 13 | -------------------------------------------------------------------------------- /src/net/fs/cap/TunManager.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 D1SM.net 2 | 3 | package net.fs.cap; 4 | 5 | import java.util.HashMap; 6 | import java.util.Iterator; 7 | 8 | import net.fs.rudp.CopiedIterator; 9 | import net.fs.utils.MLog; 10 | 11 | public class TunManager { 12 | 13 | HashMap connTable=new HashMap(); 14 | 15 | static TunManager tunManager; 16 | 17 | { 18 | tunManager=this; 19 | } 20 | 21 | TCPTun defaultTcpTun; 22 | 23 | Thread scanThread; 24 | 25 | Object syn_scan=new Object(); 26 | 27 | CapEnv capEnv; 28 | 29 | { 30 | scanThread=new Thread(){ 31 | public void run(){ 32 | while(true){ 33 | try { 34 | Thread.sleep(1000); 35 | } catch (InterruptedException e) { 36 | e.printStackTrace(); 37 | } 38 | scan(); 39 | } 40 | } 41 | }; 42 | scanThread.start(); 43 | } 44 | 45 | TunManager(CapEnv capEnv){ 46 | this.capEnv=capEnv; 47 | } 48 | 49 | void scan(){ 50 | Iterator it=getConnTableIterator(); 51 | while(it.hasNext()){ 52 | String key=it.next(); 53 | TCPTun tun=connTable.get(key); 54 | if(tun!=null){ 55 | if(tun.preDataReady){ 56 | //无数据超时 57 | long t=System.currentTimeMillis()-tun.lastReceiveDataTime; 58 | if(t>6000){ 59 | connTable.remove(key); 60 | if(capEnv.client){ 61 | defaultTcpTun=null; 62 | MLog.println("tcp隧道超时"); 63 | } 64 | } 65 | }else{ 66 | //连接中超时 67 | if(System.currentTimeMillis()-tun.createTime>5000){ 68 | connTable.remove(key); 69 | } 70 | } 71 | } 72 | } 73 | } 74 | 75 | public void removeTun(TCPTun tun){ 76 | connTable.remove(tun.key); 77 | } 78 | 79 | Iterator getConnTableIterator(){ 80 | Iterator it=null; 81 | synchronized (syn_scan) { 82 | it=new CopiedIterator(connTable.keySet().iterator()); 83 | } 84 | return it; 85 | } 86 | 87 | public static TunManager get(){ 88 | return tunManager; 89 | } 90 | 91 | public TCPTun getTcpConnection_Client(String remoteAddress,short remotePort,short localPort){ 92 | return connTable.get(remoteAddress+":"+remotePort+":"+localPort); 93 | } 94 | 95 | public void addConnection_Client(TCPTun conn) { 96 | synchronized (syn_scan) { 97 | String key=conn.remoteAddress.getHostAddress()+":"+conn.remotePort+":"+conn.localPort; 98 | //MLog.println("addConnection "+key); 99 | conn.setKey(key); 100 | connTable.put(key, conn); 101 | } 102 | } 103 | 104 | public TCPTun getTcpConnection_Server(String remoteAddress,short remotePort){ 105 | return connTable.get(remoteAddress+":"+remotePort); 106 | } 107 | 108 | public void addConnection_Server(TCPTun conn) { 109 | synchronized (syn_scan) { 110 | String key=conn.remoteAddress.getHostAddress()+":"+conn.remotePort; 111 | //MLog.println("addConnection "+key); 112 | conn.setKey(key); 113 | connTable.put(key, conn); 114 | } 115 | } 116 | 117 | public TCPTun getDefaultTcpTun() { 118 | return defaultTcpTun; 119 | } 120 | 121 | public void setDefaultTcpTun(TCPTun defaultTcpTun) { 122 | this.defaultTcpTun = defaultTcpTun; 123 | } 124 | 125 | } 126 | -------------------------------------------------------------------------------- /src/net/fs/cap/VDatagramSocket.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 D1SM.net 2 | 3 | package net.fs.cap; 4 | 5 | import java.io.IOException; 6 | import java.net.DatagramPacket; 7 | import java.net.DatagramSocket; 8 | import java.net.InetAddress; 9 | import java.net.SocketException; 10 | import java.util.concurrent.LinkedBlockingQueue; 11 | 12 | import net.fs.rudp.Route; 13 | 14 | public class VDatagramSocket extends DatagramSocket{ 15 | 16 | boolean useTcpTun=true; 17 | 18 | boolean client=true; 19 | 20 | LinkedBlockingQueue packetList=new LinkedBlockingQueue (); 21 | 22 | CapEnv capEnv; 23 | 24 | int localPort; 25 | 26 | Object syn_tun=new Object(); 27 | 28 | boolean tunConnecting=false; 29 | 30 | public VDatagramSocket() throws SocketException { 31 | 32 | } 33 | 34 | public VDatagramSocket(int port) throws SocketException { 35 | localPort=port; 36 | } 37 | 38 | public int getLocalPort() { 39 | return localPort; 40 | } 41 | 42 | public void send(DatagramPacket p) throws IOException { 43 | TCPTun tun=null; 44 | if(client){ 45 | tun=capEnv.tcpManager.getDefaultTcpTun(); 46 | if(tun!=null){ 47 | if(!tun.remoteAddress.getHostAddress().equals(p.getAddress().getHostAddress()) 48 | ||CapEnv.toUnsigned(tun.remotePort)!=p.getPort()){ 49 | capEnv.tcpManager.removeTun(tun); 50 | capEnv.tcpManager.setDefaultTcpTun(null); 51 | } 52 | }else { 53 | tryConnectTun_Client(p.getAddress(),(short) p.getPort()); 54 | tun=capEnv.tcpManager.getDefaultTcpTun(); 55 | } 56 | }else { 57 | tun=capEnv.tcpManager.getTcpConnection_Server(p.getAddress().getHostAddress(), (short) p.getPort()); 58 | } 59 | if(tun!=null){ 60 | if(tun.preDataReady){ 61 | tun.sendData(p.getData()); 62 | }else{ 63 | throw new IOException("隧道未连接!"); 64 | } 65 | }else{ 66 | 67 | throw new IOException("隧道不存在! "+" thread "+Route.es.getActiveCount()+" "+p.getAddress()+":"+p.getPort()); 68 | } 69 | } 70 | 71 | 72 | void tryConnectTun_Client(InetAddress dstAddress,short dstPort){ 73 | synchronized (syn_tun) { 74 | if(capEnv.tcpManager.getDefaultTcpTun()==null){ 75 | if(tunConnecting){ 76 | try { 77 | syn_tun.wait(); 78 | } catch (InterruptedException e) { 79 | e.printStackTrace(); 80 | } 81 | }else { 82 | tunConnecting=true; 83 | try { 84 | capEnv.createTcpTun_Client(dstAddress.getHostAddress(), dstPort); 85 | } catch (Exception e) { 86 | e.printStackTrace(); 87 | } 88 | tunConnecting=false; 89 | } 90 | } 91 | } 92 | } 93 | 94 | 95 | public synchronized void receive(DatagramPacket p) throws IOException { 96 | TunData td=null; 97 | try { 98 | td=packetList.take(); 99 | p.setData(td.data); 100 | p.setLength(td.data.length); 101 | p.setAddress(td.tun.remoteAddress); 102 | p.setPort(CapEnv.toUnsigned(td.tun.remotePort)); 103 | } catch (InterruptedException e) { 104 | e.printStackTrace(); 105 | } 106 | } 107 | 108 | void onReceinveFromTun(TunData td){ 109 | packetList.add(td); 110 | } 111 | 112 | public boolean isClient() { 113 | return client; 114 | } 115 | 116 | public void setClient(boolean client) { 117 | this.client = client; 118 | } 119 | 120 | public CapEnv getCapEnv() { 121 | return capEnv; 122 | } 123 | 124 | public void setCapEnv(CapEnv capEnv) { 125 | this.capEnv = capEnv; 126 | capEnv.vDatagramSocket=this; 127 | } 128 | 129 | } 130 | -------------------------------------------------------------------------------- /src/net/fs/client/AddMapFrame.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 D1SM.net 2 | 3 | package net.fs.client; 4 | 5 | import java.awt.Dialog; 6 | import java.awt.Dimension; 7 | import java.awt.Insets; 8 | import java.awt.event.ActionEvent; 9 | import java.awt.event.ActionListener; 10 | 11 | import javax.swing.BorderFactory; 12 | import javax.swing.JButton; 13 | import javax.swing.JDialog; 14 | import javax.swing.JFrame; 15 | import javax.swing.JLabel; 16 | import javax.swing.JOptionPane; 17 | import javax.swing.JPanel; 18 | import javax.swing.JTextField; 19 | import javax.swing.SwingUtilities; 20 | 21 | import net.fs.rudp.Route; 22 | import net.miginfocom.swing.MigLayout; 23 | 24 | public class AddMapFrame extends JDialog{ 25 | 26 | private static final long serialVersionUID = -3248779355079724594L; 27 | 28 | ClientUI ui; 29 | 30 | JTextField portTextField, text_port,nameTextField; 31 | 32 | int downloadSpeed,uploadSpeed; 33 | 34 | MapRule maprule_origin; 35 | 36 | boolean edit=false; 37 | 38 | AddMapFrame(final ClientUI ui,JFrame parent,final MapRule maprule_origin,final boolean edit){ 39 | super(parent,Dialog.ModalityType.APPLICATION_MODAL); 40 | this.ui=ui; 41 | this.edit=edit; 42 | this.maprule_origin=maprule_origin; 43 | setTitle("增加映射"); 44 | //setSize(size); 45 | if(edit){ 46 | setTitle("编辑映射"); 47 | } 48 | 49 | JPanel panel=(JPanel) getContentPane(); 50 | panel.setLayout(new MigLayout("alignx center,aligny center,insets 10 10 10 10")); 51 | 52 | 53 | String text="" 54 | + "单位Mb ( 1Mb=128KB,10Mb=1280KB )
" 55 | + ""+"请正确输入,该值会直接影响加速效果.
"; 56 | 57 | JPanel p3=new JPanel(); 58 | panel.add(p3,"wrap"); 59 | p3.setBorder(BorderFactory.createEtchedBorder()); 60 | p3.setLayout(new MigLayout("inset 5 5 5 5")); 61 | 62 | p3.add(new JLabel("名称:")); 63 | nameTextField=new JTextField(); 64 | p3.add(nameTextField,"width :100: ,wrap"); 65 | 66 | p3.add(new JLabel("加速端口:")); 67 | portTextField=new JTextField(""); 68 | p3.add(portTextField,"width :50:,wrap"); 69 | portTextField.setToolTipText("需要加速的端口号"); 70 | 71 | p3.add(new JLabel("本地端口: ")); 72 | text_port=new JTextField(); 73 | p3.add(text_port,"width :50: ,wrap"); 74 | 75 | JPanel p6=new JPanel(); 76 | panel.add(p6,"align center,wrap"); 77 | p6.setLayout(new MigLayout("align center")); 78 | 79 | JButton button_ok=createButton("确定"); 80 | p6.add(button_ok); 81 | button_ok.addActionListener(new ActionListener() { 82 | 83 | @Override 84 | public void actionPerformed(ActionEvent e) { 85 | try { 86 | checkName(nameTextField.getText()); 87 | checkPort(text_port.getText()); 88 | checkPort(portTextField.getText()); 89 | String name=nameTextField.getText(); 90 | int listen_port=Integer.parseInt(text_port.getText()); 91 | int dst_port=Integer.parseInt(portTextField.getText()); 92 | MapRule mapRule_new=new MapRule(); 93 | mapRule_new.setName(name); 94 | mapRule_new.listen_port=listen_port; 95 | mapRule_new.setDst_port(dst_port); 96 | if(!edit){ 97 | ui.mapClient.portMapManager.addMapRule(mapRule_new); 98 | }else { 99 | ui.mapClient.portMapManager.updateMapRule(maprule_origin,mapRule_new); 100 | } 101 | ui.loadMapRule(); 102 | ui.select(mapRule_new.name); 103 | setVisible(false); 104 | } catch (Exception e1) { 105 | //e2.printStackTrace(); 106 | JOptionPane.showMessageDialog(ui.mainFrame, e1.getMessage(),"消息",JOptionPane.WARNING_MESSAGE); 107 | } 108 | } 109 | }); 110 | 111 | p6.add(new JLabel(" ")); 112 | 113 | JButton button_cancel=createButton("取消"); 114 | p6.add(button_cancel); 115 | button_cancel.addActionListener(new ActionListener() { 116 | 117 | @Override 118 | public void actionPerformed(ActionEvent e) { 119 | setVisible(false); 120 | } 121 | }); 122 | 123 | 124 | if(edit){ 125 | nameTextField.setText(maprule_origin.name); 126 | text_port.setText(maprule_origin.listen_port+""); 127 | portTextField.setText(maprule_origin.dst_port+""); 128 | } 129 | 130 | pack(); 131 | setLocationRelativeTo(parent); 132 | setVisible(true); 133 | } 134 | 135 | void checkName(String s) throws Exception{ 136 | if(s.trim().equals("")){ 137 | throw new Exception("请输入名称"); 138 | } 139 | } 140 | 141 | void checkDstAddress(String s) throws Exception{ 142 | if(s.trim().equals("")){ 143 | throw new Exception("请输入目标地址"); 144 | } 145 | } 146 | 147 | void checkPort(String s) throws Exception{ 148 | int port=0; 149 | try { 150 | port=Integer.parseInt(s); 151 | } catch (Exception e1) { 152 | throw new Exception("请输入正确端口号"); 153 | } 154 | if(port<1|port>256*256){ 155 | throw new Exception("请输入正确端口号"); 156 | } 157 | } 158 | 159 | JButton createButton(String name){ 160 | JButton button=new JButton(name); 161 | button.setMargin(new Insets(0,5,0,5)); 162 | button.setFocusPainted(false); 163 | return button; 164 | } 165 | 166 | 167 | 168 | } 169 | -------------------------------------------------------------------------------- /src/net/fs/client/AlignCellRenderer.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 D1SM.net 2 | 3 | package net.fs.client; 4 | 5 | import javax.swing.table.DefaultTableCellRenderer; 6 | 7 | public class AlignCellRenderer extends DefaultTableCellRenderer{ 8 | private static final long serialVersionUID = -6003599724059557606L; 9 | 10 | public AlignCellRenderer(int align){ 11 | super(); 12 | setHorizontalAlignment(align); 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /src/net/fs/client/ClientConfig.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 D1SM.net 2 | 3 | package net.fs.client; 4 | 5 | public class ClientConfig { 6 | 7 | String serverAddress=""; 8 | 9 | int serverPort; 10 | 11 | int remotePort; 12 | 13 | int downloadSpeed,uploadSpeed; 14 | 15 | boolean direct_cn=true; 16 | 17 | int socks5Port=1083; 18 | 19 | String remoteAddress; 20 | 21 | String protocal="tcp"; 22 | 23 | public String getServerAddress() { 24 | return serverAddress; 25 | } 26 | 27 | public void setServerAddress(String serverAddress) { 28 | this.serverAddress = serverAddress; 29 | } 30 | 31 | public int getServerPort() { 32 | return serverPort; 33 | } 34 | 35 | public void setServerPort(int serverPort) { 36 | this.serverPort = serverPort; 37 | } 38 | 39 | public int getRemotePort() { 40 | return remotePort; 41 | } 42 | 43 | public void setRemotePort(int remotePort) { 44 | this.remotePort = remotePort; 45 | } 46 | 47 | public boolean isDirect_cn() { 48 | return direct_cn; 49 | } 50 | 51 | public void setDirect_cn(boolean direct_cn) { 52 | this.direct_cn = direct_cn; 53 | } 54 | 55 | public int getDownloadSpeed() { 56 | return downloadSpeed; 57 | } 58 | 59 | public void setDownloadSpeed(int downloadSpeed) { 60 | this.downloadSpeed = downloadSpeed; 61 | } 62 | 63 | public int getUploadSpeed() { 64 | return uploadSpeed; 65 | } 66 | 67 | public void setUploadSpeed(int uploadSpeed) { 68 | this.uploadSpeed = uploadSpeed; 69 | } 70 | 71 | public int getSocks5Port() { 72 | return socks5Port; 73 | } 74 | 75 | public void setSocks5Port(int socks5Port) { 76 | this.socks5Port = socks5Port; 77 | } 78 | 79 | public String getRemoteAddress() { 80 | return remoteAddress; 81 | } 82 | 83 | public void setRemoteAddress(String remoteAddress) { 84 | this.remoteAddress = remoteAddress; 85 | } 86 | 87 | public String getProtocal() { 88 | return protocal; 89 | } 90 | 91 | public void setProtocal(String protocal) { 92 | this.protocal = protocal; 93 | } 94 | 95 | } 96 | -------------------------------------------------------------------------------- /src/net/fs/client/ClientNoUI.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 D1SM.net 2 | 3 | package net.fs.client; 4 | 5 | 6 | import java.io.IOException; 7 | 8 | import org.pcap4j.core.Pcaps; 9 | 10 | import net.fs.rudp.Route; 11 | import net.fs.utils.MLog; 12 | 13 | 14 | public class ClientNoUI extends ClientUI{ 15 | 16 | @Override 17 | void run(){ 18 | systemName=System.getProperty("os.name").toLowerCase(); 19 | MLog.info("System: "+systemName+" "+System.getProperty("os.version")); 20 | ui=this; 21 | 22 | checkQuanxian(); 23 | loadConfig(); 24 | 25 | model=new MapRuleListModel(); 26 | tcpMapRuleListTable=new MapRuleListTable(this,model); 27 | 28 | 29 | 30 | checkFireWallOn(); 31 | if(!success_firewall_windows){ 32 | MLog.info("启动windows防火墙失败,请先运行防火墙服务."); 33 | System.exit(0); 34 | } 35 | if(!success_firewall_osx){ 36 | MLog.info("启动ipfw/pf防火墙失败,请先安装."); 37 | System.exit(0); 38 | } 39 | 40 | Thread thread=new Thread(){ 41 | public void run(){ 42 | try { 43 | Pcaps.findAllDevs(); 44 | b1=true; 45 | } catch (Exception e3) { 46 | e3.printStackTrace(); 47 | 48 | } 49 | } 50 | }; 51 | thread.start(); 52 | try { 53 | thread.join(); 54 | } catch (InterruptedException e1) { 55 | e1.printStackTrace(); 56 | } 57 | //JOptionPane.showMessageDialog(mainFrame,System.getProperty("os.name")); 58 | if(!b1){ 59 | try { 60 | String msg="启动失败,请先安装libpcap"; 61 | if(systemName.contains("windows")){ 62 | msg="启动失败,请先安装winpcap"; 63 | } 64 | MLog.info(msg); 65 | if(systemName.contains("windows")){ 66 | try { 67 | Runtime.getRuntime().exec("winpcap_install.exe",null); 68 | } catch (IOException e) { 69 | e.printStackTrace(); 70 | } 71 | } 72 | System.exit(0); 73 | } catch (Exception e2) { 74 | e2.printStackTrace(); 75 | } 76 | } 77 | 78 | 79 | try { 80 | mapClient=new MapClient(this); 81 | } catch (final Exception e1) { 82 | e1.printStackTrace(); 83 | capException=e1; 84 | //System.exit(0);; 85 | } 86 | 87 | try { 88 | if(!mapClient.route_tcp.capEnv.tcpEnable){ 89 | MLog.info("无可用网络接口,只能使用udp协议."); 90 | } 91 | } catch (Exception e2) { 92 | e2.printStackTrace(); 93 | } 94 | 95 | mapClient.setUi(this); 96 | 97 | mapClient.setMapServer(config.getServerAddress(), config.getServerPort(),config.getRemotePort() ,null,null,config.isDirect_cn(),config.getProtocal().equals("tcp"), 98 | null); 99 | 100 | 101 | 102 | setSpeed(config.getDownloadSpeed(),config.getUploadSpeed()); 103 | 104 | loadMapRule(); 105 | 106 | if(config.getDownloadSpeed()==0||config.getUploadSpeed()==0){ 107 | new SpeedSetFrame(ui,mainFrame); 108 | } 109 | 110 | } 111 | 112 | @Override 113 | public void setMessage(String message){} 114 | 115 | @Override 116 | void setSpeed(int downloadSpeed,int uploadSpeed){ 117 | config.setDownloadSpeed(downloadSpeed); 118 | config.setUploadSpeed(uploadSpeed); 119 | Route.localDownloadSpeed=downloadSpeed; 120 | Route.localUploadSpeed=config.uploadSpeed; 121 | } 122 | } 123 | 124 | -------------------------------------------------------------------------------- /src/net/fs/client/ClientStartNoUI.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 D1SM.net 2 | 3 | package net.fs.client; 4 | 5 | public class ClientStartNoUI { 6 | 7 | public static void main(String[] args) { 8 | new ClientNoUI(); 9 | } 10 | 11 | } 12 | -------------------------------------------------------------------------------- /src/net/fs/client/ClientUII.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 D1SM.net 2 | 3 | package net.fs.client; 4 | 5 | public interface ClientUII { 6 | 7 | 8 | void setMessage(String message); 9 | 10 | void updateUISpeed(int connNum, int downSpeed, int upSpeed); 11 | 12 | boolean login(); 13 | 14 | boolean updateNode(boolean testSpeed); 15 | 16 | boolean isOsx_fw_pf(); 17 | 18 | boolean isOsx_fw_ipfw(); 19 | 20 | } 21 | -------------------------------------------------------------------------------- /src/net/fs/client/FSClient.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 D1SM.net 2 | 3 | package net.fs.client; 4 | 5 | public class FSClient { 6 | 7 | public static void main(String[] args) { 8 | //new ClientUI().run(); 9 | new ClientNoUI().run(); 10 | } 11 | 12 | } 13 | -------------------------------------------------------------------------------- /src/net/fs/client/MapClient.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 D1SM.net 2 | 3 | package net.fs.client; 4 | 5 | import java.io.BufferedReader; 6 | import java.io.File; 7 | import java.io.FileOutputStream; 8 | import java.io.IOException; 9 | import java.io.InputStream; 10 | import java.io.InputStreamReader; 11 | import java.net.InetAddress; 12 | import java.net.ServerSocket; 13 | import java.net.Socket; 14 | import java.security.NoSuchAlgorithmException; 15 | import java.util.ArrayList; 16 | import java.util.HashSet; 17 | import java.util.Random; 18 | 19 | import javax.crypto.KeyGenerator; 20 | import javax.crypto.SecretKey; 21 | 22 | import net.fs.rudp.ClientProcessorInterface; 23 | import net.fs.rudp.ConnectionProcessor; 24 | import net.fs.rudp.RUDPConfig; 25 | import net.fs.rudp.Route; 26 | import net.fs.rudp.TrafficEvent; 27 | import net.fs.rudp.Trafficlistener; 28 | import net.fs.utils.MLog; 29 | import net.fs.utils.NetStatus; 30 | 31 | public class MapClient implements Trafficlistener{ 32 | 33 | ConnectionProcessor imTunnelProcessor; 34 | 35 | Route route_udp,route_tcp; 36 | 37 | short routePort=45; 38 | 39 | ClientUII ui; 40 | 41 | String serverAddress=""; 42 | 43 | InetAddress address=null; 44 | 45 | int serverPort=130; 46 | 47 | NetStatus netStatus; 48 | 49 | long lastTrafficTime; 50 | 51 | int downloadSum=0; 52 | 53 | int uploadSum=0; 54 | 55 | Thread clientUISpeedUpdateThread; 56 | 57 | int connNum=0; 58 | 59 | HashSet processTable=new HashSet(); 60 | 61 | Object syn_process=new Object(); 62 | 63 | static MapClient mapClient; 64 | 65 | PortMapManager portMapManager; 66 | 67 | public String mapdstAddress; 68 | 69 | public int mapdstPort; 70 | 71 | static int monPort=25874; 72 | 73 | String systemName=System.getProperty("os.name").toLowerCase(); 74 | 75 | boolean useTcp=true; 76 | 77 | long clientId; 78 | 79 | Random ran=new Random(); 80 | 81 | MapClient(ClientUI ui) throws Exception { 82 | this.ui=ui; 83 | mapClient=this; 84 | try { 85 | final ServerSocket socket=new ServerSocket(monPort); 86 | new Thread(){ 87 | public void run(){ 88 | try { 89 | socket.accept(); 90 | } catch (IOException e) { 91 | e.printStackTrace(); 92 | System.exit(0); 93 | } 94 | } 95 | }.start(); 96 | } catch (Exception e) { 97 | //e.printStackTrace(); 98 | //System.exit(0); 99 | } 100 | try { 101 | route_tcp = new Route(null,routePort,Route.mode_client,true); 102 | } catch (Exception e1) { 103 | //e1.printStackTrace(); 104 | throw e1; 105 | } 106 | try { 107 | route_udp = new Route(null,routePort,Route.mode_client,false); 108 | } catch (Exception e1) { 109 | //e1.printStackTrace(); 110 | throw e1; 111 | } 112 | netStatus=new NetStatus(); 113 | 114 | portMapManager=new PortMapManager(this); 115 | 116 | clientUISpeedUpdateThread=new Thread(){ 117 | public void run(){ 118 | while(true){ 119 | try { 120 | Thread.sleep(500); 121 | } catch (InterruptedException e1) { 122 | e1.printStackTrace(); 123 | } 124 | updateUISpeed(); 125 | } 126 | } 127 | }; 128 | clientUISpeedUpdateThread.start(); 129 | 130 | Route.addTrafficlistener(this); 131 | 132 | } 133 | 134 | public static MapClient get(){ 135 | return mapClient; 136 | } 137 | 138 | private void updateUISpeed(){ 139 | if(ui!=null){ 140 | ui.updateUISpeed(connNum,netStatus.getDownSpeed(),netStatus.getUpSpeed()); 141 | } 142 | } 143 | 144 | public void setMapServer(String serverAddress,int serverPort,int remotePort,String passwordMd5,String password_proxy_Md5,boolean direct_cn,boolean tcp, 145 | String password){ 146 | if(this.serverAddress==null 147 | ||!this.serverAddress.equals(serverAddress) 148 | ||this.serverPort!=serverPort){ 149 | 150 | if(route_tcp.lastClientControl!=null){ 151 | route_tcp.lastClientControl.close(); 152 | } 153 | 154 | if(route_udp.lastClientControl!=null){ 155 | route_udp.lastClientControl.close(); 156 | } 157 | 158 | cleanRule(); 159 | if(serverAddress!=null&&!serverAddress.equals("")){ 160 | setFireWallRule(serverAddress,serverPort); 161 | } 162 | 163 | } 164 | this.serverAddress=serverAddress; 165 | this.serverPort=serverPort; 166 | address=null; 167 | useTcp=tcp; 168 | resetConnection(); 169 | } 170 | 171 | 172 | void setFireWallRule(String serverAddress,int serverPort){ 173 | String ip; 174 | try { 175 | ip = InetAddress.getByName(serverAddress).getHostAddress(); 176 | if(systemName.contains("mac os")){ 177 | if(ui.isOsx_fw_pf ()){ 178 | String tempPath="./pf.conf"; 179 | File f=new File(tempPath); 180 | File d=f.getParentFile(); 181 | if(!d.exists()){ 182 | d.mkdirs(); 183 | } 184 | if(f.exists()){ 185 | f.delete(); 186 | } 187 | //必须换行结束 188 | String content="block drop quick proto tcp from any to "+ip+" port = "+serverPort+"\n"; 189 | saveFile(content.getBytes(), tempPath); 190 | 191 | String cmd1="pfctl -d"; 192 | runCommand(cmd1); 193 | 194 | String cmd2="pfctl -Rf "+f.getAbsolutePath(); 195 | runCommand(cmd2); 196 | 197 | String cmd3="pfctl -e"; 198 | runCommand(cmd3); 199 | 200 | //f.delete(); 201 | }else if(ui.isOsx_fw_ipfw()){ 202 | String cmd2="sudo ipfw add 5050 deny tcp from any to "+ip+" "+serverAddress+" out"; 203 | runCommand(cmd2); 204 | } 205 | }else if(systemName.contains("linux")){ 206 | String cmd2="iptables -t filter -A OUTPUT -d "+ip+" -p tcp --dport "+serverPort+" -j DROP -m comment --comment tcptun_fs "; 207 | runCommand(cmd2); 208 | }else if (systemName.contains("windows")) { 209 | try { 210 | if(systemName.contains("xp")||systemName.contains("2003")){ 211 | String cmd_add1="ipseccmd -w REG -p \"tcptun_fs\" -r \"Block TCP/"+serverPort+"\" -f 0/255.255.255.255="+ip+"/255.255.255.255:"+serverPort+":tcp -n BLOCK -x "; 212 | final Process p2 = Runtime.getRuntime().exec(cmd_add1,null); 213 | p2.waitFor(); 214 | }else { 215 | String cmd_add1="netsh advfirewall firewall add rule name=tcptun_fs protocol=TCP dir=out remoteport="+serverPort+" remoteip="+ip+" action=block "; 216 | final Process p2 = Runtime.getRuntime().exec(cmd_add1,null); 217 | p2.waitFor(); 218 | String cmd_add2="netsh advfirewall firewall add rule name=tcptun_fs protocol=TCP dir=in remoteport="+serverPort+" remoteip="+ip+" action=block "; 219 | Process p3 = Runtime.getRuntime().exec(cmd_add2,null); 220 | p3.waitFor(); 221 | } 222 | } catch (Exception e1) { 223 | e1.printStackTrace(); 224 | } 225 | } 226 | } catch (Exception e) { 227 | e.printStackTrace(); 228 | } 229 | 230 | } 231 | 232 | void saveFile(byte[] data,String path) throws Exception{ 233 | FileOutputStream fos=null; 234 | try { 235 | fos=new FileOutputStream(path); 236 | fos.write(data); 237 | } catch (Exception e) { 238 | throw e; 239 | } finally { 240 | if(fos!=null){ 241 | fos.close(); 242 | } 243 | } 244 | } 245 | 246 | void cleanRule(){ 247 | if(systemName.contains("mac os")){ 248 | cleanTcpTunRule_osx(); 249 | }else if(systemName.contains("linux")){ 250 | cleanTcpTunRule_linux(); 251 | }else { 252 | try { 253 | if(systemName.contains("xp")||systemName.contains("2003")){ 254 | String cmd_delete="ipseccmd -p \"tcptun_fs\" -w reg -y"; 255 | final Process p1 = Runtime.getRuntime().exec(cmd_delete,null); 256 | p1.waitFor(); 257 | }else { 258 | String cmd_delete="netsh advfirewall firewall delete rule name=tcptun_fs "; 259 | final Process p1 = Runtime.getRuntime().exec(cmd_delete,null); 260 | p1.waitFor(); 261 | } 262 | 263 | } catch (Exception e) { 264 | e.printStackTrace(); 265 | } 266 | } 267 | } 268 | 269 | void cleanTcpTunRule_osx(){ 270 | String cmd2="sudo ipfw delete 5050"; 271 | runCommand(cmd2); 272 | } 273 | 274 | 275 | void cleanTcpTunRule_linux(){ 276 | while(true){ 277 | int row=getRow_linux(); 278 | if(row>0){ 279 | //MLog.println("删除行 "+row); 280 | String cmd="iptables -D OUTPUT "+row; 281 | runCommand(cmd); 282 | }else { 283 | break; 284 | } 285 | } 286 | } 287 | 288 | int getRow_linux(){ 289 | int row_delect=-1; 290 | String cme_list_rule="iptables -L -n --line-number"; 291 | //String [] cmd={"netsh","advfirewall set allprofiles state on"}; 292 | Thread errorReadThread=null; 293 | try { 294 | final Process p = Runtime.getRuntime().exec(cme_list_rule,null); 295 | 296 | errorReadThread=new Thread(){ 297 | public void run(){ 298 | InputStream is=p.getErrorStream(); 299 | BufferedReader localBufferedReader = new BufferedReader(new InputStreamReader(is)); 300 | while (true){ 301 | String line; 302 | try { 303 | line = localBufferedReader.readLine(); 304 | if (line == null){ 305 | break; 306 | }else{ 307 | //System.out.println("erroraaa "+line); 308 | } 309 | } catch (IOException e) { 310 | e.printStackTrace(); 311 | //error(); 312 | break; 313 | } 314 | } 315 | } 316 | }; 317 | errorReadThread.start(); 318 | 319 | 320 | 321 | InputStream is=p.getInputStream(); 322 | BufferedReader localBufferedReader = new BufferedReader(new InputStreamReader(is)); 323 | while (true){ 324 | String line; 325 | try { 326 | line = localBufferedReader.readLine(); 327 | // System.out.println("standaaa "+line); 328 | if (line == null){ 329 | break; 330 | }else{ 331 | if(line.contains("tcptun_fs")){ 332 | int index=line.indexOf(" "); 333 | if(index>0){ 334 | String n=line.substring(0, index); 335 | try { 336 | if(row_delect<0){ 337 | //System.out.println("standaaabbb "+line); 338 | row_delect=Integer.parseInt(n); 339 | } 340 | } catch (Exception e) { 341 | 342 | } 343 | } 344 | }; 345 | } 346 | } catch (IOException e) { 347 | e.printStackTrace(); 348 | break; 349 | } 350 | } 351 | 352 | 353 | errorReadThread.join(); 354 | p.waitFor(); 355 | } catch (Exception e) { 356 | e.printStackTrace(); 357 | //error(); 358 | } 359 | return row_delect; 360 | } 361 | 362 | void resetConnection(){ 363 | synchronized (syn_process) { 364 | 365 | } 366 | } 367 | 368 | public void onProcessClose(ClientProcessorInterface process){ 369 | synchronized (syn_process) { 370 | processTable.remove(process); 371 | } 372 | } 373 | 374 | synchronized public void closeAndTryConnect_Login(boolean testSpeed){ 375 | close(); 376 | boolean loginOK=ui.login(); 377 | if(loginOK){ 378 | ui.updateNode(testSpeed); 379 | //testPool(); 380 | } 381 | } 382 | 383 | synchronized public void closeAndTryConnect(){ 384 | close(); 385 | //testPool(); 386 | } 387 | 388 | public void close(){ 389 | //closeAllProxyRequest(); 390 | //poolManage.close(); 391 | //CSocketPool.closeAll(); 392 | } 393 | 394 | public void trafficDownload(TrafficEvent event) { 395 | ////#MLog.println("下载 "+event.getTraffic()); 396 | netStatus.addDownload(event.getTraffic()); 397 | lastTrafficTime=System.currentTimeMillis(); 398 | downloadSum+=event.getTraffic(); 399 | } 400 | 401 | public void trafficUpload(TrafficEvent event) { 402 | ////#MLog.println("上传 "+event.getTraffic()); 403 | netStatus.addUpload(event.getTraffic()); 404 | lastTrafficTime=System.currentTimeMillis(); 405 | uploadSum+=event.getTraffic(); 406 | } 407 | 408 | static void runCommand(String command){ 409 | Thread standReadThread=null; 410 | Thread errorReadThread=null; 411 | try { 412 | final Process p = Runtime.getRuntime().exec(command,null); 413 | standReadThread=new Thread(){ 414 | public void run(){ 415 | InputStream is=p.getInputStream(); 416 | BufferedReader localBufferedReader = new BufferedReader(new InputStreamReader(is)); 417 | while (true){ 418 | String line; 419 | try { 420 | line = localBufferedReader.readLine(); 421 | //System.out.println("stand "+line); 422 | if (line == null){ 423 | break; 424 | } 425 | } catch (IOException e) { 426 | e.printStackTrace(); 427 | break; 428 | } 429 | } 430 | } 431 | }; 432 | standReadThread.start(); 433 | 434 | errorReadThread=new Thread(){ 435 | public void run(){ 436 | InputStream is=p.getErrorStream(); 437 | BufferedReader localBufferedReader = new BufferedReader(new InputStreamReader(is)); 438 | while (true){ 439 | String line; 440 | try { 441 | line = localBufferedReader.readLine(); 442 | if (line == null){ 443 | break; 444 | }else{ 445 | //System.out.println("error "+line); 446 | } 447 | } catch (IOException e) { 448 | e.printStackTrace(); 449 | //error(); 450 | break; 451 | } 452 | } 453 | } 454 | }; 455 | errorReadThread.start(); 456 | standReadThread.join(); 457 | errorReadThread.join(); 458 | p.waitFor(); 459 | } catch (Exception e) { 460 | e.printStackTrace(); 461 | //error(); 462 | } 463 | } 464 | 465 | public boolean isUseTcp() { 466 | return useTcp; 467 | } 468 | 469 | public void setUseTcp(boolean useTcp) { 470 | this.useTcp = useTcp; 471 | } 472 | 473 | public ClientUII getUi() { 474 | return ui; 475 | } 476 | 477 | public void setUi(ClientUII ui) { 478 | this.ui = ui; 479 | } 480 | 481 | } 482 | -------------------------------------------------------------------------------- /src/net/fs/client/MapRule.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 D1SM.net 2 | 3 | package net.fs.client; 4 | 5 | import java.io.Serializable; 6 | import java.net.ServerSocket; 7 | 8 | 9 | public class MapRule implements Serializable{ 10 | 11 | int listen_port; 12 | 13 | int dst_port; 14 | 15 | String name; 16 | 17 | boolean using=false; 18 | 19 | ServerSocket serverSocket; 20 | 21 | public int getListen_port() { 22 | return listen_port; 23 | } 24 | 25 | public void setListen_port(int listen_port) { 26 | this.listen_port = listen_port; 27 | } 28 | 29 | public int getDst_port() { 30 | return dst_port; 31 | } 32 | 33 | public void setDst_port(int dst_port) { 34 | this.dst_port = dst_port; 35 | } 36 | 37 | public String getName() { 38 | return name; 39 | } 40 | 41 | public void setName(String name) { 42 | this.name = name; 43 | } 44 | 45 | } 46 | -------------------------------------------------------------------------------- /src/net/fs/client/MapRuleListModel.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 D1SM.net 2 | 3 | package net.fs.client; 4 | 5 | import java.util.ArrayList; 6 | import java.util.List; 7 | import java.util.ResourceBundle; 8 | 9 | import javax.swing.table.AbstractTableModel; 10 | 11 | 12 | public class MapRuleListModel extends AbstractTableModel{ 13 | 14 | private static final long serialVersionUID = 2267856423317178816L; 15 | 16 | private List mapRuleList; 17 | 18 | String titles[] ; 19 | 20 | Class types[] = new Class[] {String.class, String.class, String.class,String.class, String.class, String.class}; 21 | 22 | MapRuleListModel(){ 23 | mapRuleList=new ArrayList (); 24 | titles = new String[] {""}; 25 | } 26 | 27 | public void setMapRuleList(List list){ 28 | mapRuleList.clear(); 29 | if(list!=null){ 30 | mapRuleList.addAll(list); 31 | } 32 | fireTableDataChanged(); 33 | } 34 | 35 | public int getMapRuleIndex(String name){ 36 | int index=-1; 37 | int i=0; 38 | for(MapRule r:mapRuleList){ 39 | if(name.equals(r.getName())){ 40 | index=i; 41 | break; 42 | } 43 | i++; 44 | } 45 | return index; 46 | } 47 | 48 | List getMapRuleList(){ 49 | return mapRuleList; 50 | } 51 | 52 | public MapRule getMapRuleAt(int row){ 53 | if(row>-1&row getColumnClass(int c) { 82 | return types[c]; 83 | } 84 | 85 | 86 | public boolean isCellEditable(int row, int col) { 87 | boolean b=false; 88 | if(col==0){ 89 | b=true; 90 | } 91 | return false; 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /src/net/fs/client/MapRuleListTable.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 D1SM.net 2 | 3 | package net.fs.client; 4 | 5 | import java.awt.event.MouseEvent; 6 | import java.awt.event.MouseListener; 7 | import java.util.List; 8 | 9 | import javax.swing.JTable; 10 | import javax.swing.ListSelectionModel; 11 | import javax.swing.SwingUtilities; 12 | import javax.swing.event.ListSelectionEvent; 13 | import javax.swing.event.ListSelectionListener; 14 | 15 | public class MapRuleListTable extends JTable{ 16 | 17 | private static final long serialVersionUID = -547936371303904463L; 18 | 19 | MapRuleListModel model; 20 | 21 | MapRuleListTable table; 22 | 23 | ClientUI ui; 24 | 25 | MapRuleListTable(ClientUI ui,final MapRuleListModel model){ 26 | super(); 27 | this.model=model; 28 | this.ui=ui; 29 | table=this; 30 | setModel(model); 31 | 32 | setSelectionMode(ListSelectionModel.SINGLE_SELECTION); 33 | setRowSorter(null); 34 | 35 | getColumnModel().getColumn(0).setMinWidth(30); 36 | 37 | MapRuleRender rr=new MapRuleRender(); 38 | getColumnModel().getColumn(0).setCellRenderer(rr); 39 | setRowHeight(50); 40 | 41 | new Thread(){ 42 | public void run() { 43 | while(true){ 44 | try { 45 | Thread.sleep(1000); 46 | refresh(); 47 | } catch (InterruptedException e) { 48 | e.printStackTrace(); 49 | } 50 | } 51 | } 52 | }.start(); 53 | 54 | addMouseListener(new MouseListener() { 55 | 56 | @Override 57 | public void mouseReleased(MouseEvent e) {} 58 | 59 | @Override 60 | public void mousePressed(MouseEvent e) { 61 | if(e.getButton()==MouseEvent.BUTTON3&&e.getClickCount()==1){ 62 | int index=rowAtPoint(e.getPoint()); 63 | int modelIndex=convertRowIndexToModel(index); 64 | getSelectionModel().setSelectionInterval(modelIndex, modelIndex); 65 | } 66 | } 67 | 68 | @Override 69 | public void mouseExited(MouseEvent e) {} 70 | 71 | @Override 72 | public void mouseEntered(MouseEvent e) {} 73 | 74 | @Override 75 | public void mouseClicked(MouseEvent e) { 76 | if(e.getButton()==MouseEvent.BUTTON1&&e.getClickCount()==2){ 77 | editRule(); 78 | } 79 | } 80 | }); 81 | 82 | } 83 | 84 | void editRule(){ 85 | int index=getSelectedRow(); 86 | int modelIndex=convertRowIndexToModel(index); 87 | MapRule mapRule=getModel().getMapRuleAt(modelIndex); 88 | AddMapFrame sf=new AddMapFrame(ui,ui.mainFrame,mapRule,true); 89 | //sf.setVisible(true); 90 | } 91 | 92 | void refresh(){ 93 | SwingUtilities.invokeLater(new Runnable() { 94 | 95 | @Override 96 | public void run() { 97 | updateUI(); 98 | } 99 | }); 100 | } 101 | 102 | public void setMapRuleList(List list){ 103 | model.setMapRuleList(list); 104 | } 105 | 106 | public MapRuleListModel getModel() { 107 | return model; 108 | } 109 | 110 | public void setModel(MapRuleListModel model) { 111 | super.setModel(model); 112 | this.model = model; 113 | } 114 | 115 | } 116 | -------------------------------------------------------------------------------- /src/net/fs/client/MapRuleRender.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 D1SM.net 2 | 3 | package net.fs.client; 4 | 5 | import java.awt.Color; 6 | import java.awt.Component; 7 | 8 | import javax.swing.JLabel; 9 | import javax.swing.JPanel; 10 | import javax.swing.JTable; 11 | import javax.swing.table.TableCellRenderer; 12 | 13 | 14 | import net.miginfocom.swing.MigLayout; 15 | import sun.swing.DefaultLookup; 16 | 17 | public class MapRuleRender extends JLabel implements TableCellRenderer { 18 | 19 | private static final long serialVersionUID = -3260748459008436510L; 20 | 21 | JPanel pleft,pright,p1; 22 | 23 | JLabel label_wan_address; 24 | JLabel label2; 25 | 26 | MapRule rule; 27 | 28 | { 29 | setOpaque(true); 30 | setLayout(new MigLayout("insets 8 10 0 0")); 31 | label_wan_address=new JLabel(); 32 | add(label_wan_address,"width :500:,wrap"); 33 | label_wan_address.setBackground(new Color(0f,0f,0f,0f)); 34 | label_wan_address.setOpaque(true); 35 | label2=new JLabel(); 36 | add(label2,"width :500:,wrap"); 37 | label2.setBackground(new Color(0f,0f,0f,0f)); 38 | label2.setOpaque(true); 39 | } 40 | 41 | 42 | void update(MapRule rule,JTable table,int row){ 43 | this.rule=rule; 44 | int rowHeight=50; 45 | int h=table.getRowHeight(row); 46 | if(h!=rowHeight){ 47 | table.setRowHeight(row, rowHeight); 48 | } 49 | String name=rule.getName(); 50 | if(name==null){ 51 | name="无"; 52 | }else if(name.trim().equals("")){ 53 | name="无"; 54 | } 55 | label_wan_address.setText("名称: "+rule.name+" 加速端口: "+rule.dst_port); 56 | label2.setText("本地端口: "+rule.getListen_port()); 57 | 58 | } 59 | 60 | @Override 61 | public Component getTableCellRendererComponent(JTable table, Object value, 62 | boolean isSelected, boolean hasFocus, int row, int column) { 63 | Color fg = null; 64 | Color bg = null; 65 | JTable.DropLocation dropLocation = table.getDropLocation(); 66 | if (dropLocation != null 67 | && !dropLocation.isInsertRow() 68 | && !dropLocation.isInsertColumn() 69 | && dropLocation.getRow() == row 70 | && dropLocation.getColumn() == column) { 71 | 72 | fg = DefaultLookup.getColor(this, ui, "Table.dropCellForeground"); 73 | bg = DefaultLookup.getColor(this, ui, "Table.dropCellBackground"); 74 | isSelected = true; 75 | } 76 | if (isSelected) { 77 | setBackground(DefaultLookup.getColor(this, ui, "Table.dropCellBackground")); 78 | } else { 79 | setBackground( DefaultLookup.getColor(this, ui, "Table.alternateRowColor")); 80 | } 81 | MapRule rule=(MapRule)value; 82 | update(rule,table,row); 83 | return this; 84 | } 85 | 86 | } 87 | -------------------------------------------------------------------------------- /src/net/fs/client/Pipe.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 D1SM.net 2 | 3 | package net.fs.client; 4 | 5 | import java.io.InputStream; 6 | import java.io.OutputStream; 7 | import java.util.HashMap; 8 | import java.util.concurrent.ExecutorService; 9 | import java.util.concurrent.SynchronousQueue; 10 | import java.util.concurrent.ThreadPoolExecutor; 11 | import java.util.concurrent.TimeUnit; 12 | 13 | import net.fs.rudp.ConnectionUDP; 14 | import net.fs.rudp.UDPInputStream; 15 | import net.fs.rudp.UDPOutputStream; 16 | import net.fs.utils.MLog; 17 | 18 | public class Pipe { 19 | 20 | 21 | int lastTime=-1; 22 | 23 | 24 | boolean readed=false; 25 | 26 | public Pipe p2; 27 | 28 | byte[] pv; 29 | 30 | int pvl; 31 | 32 | 33 | public void pipe(InputStream is,UDPOutputStream tos,int initSpeed,final Pipe p2) throws Exception{ 34 | 35 | int len=0; 36 | byte[] buf=new byte[100*1024]; 37 | boolean sendeda=false; 38 | while((len=is.read(buf))>0){ 39 | readed=true; 40 | if(!sendeda){ 41 | sendeda=true; 42 | } 43 | tos.write(buf, 0, len); 44 | } 45 | } 46 | 47 | 48 | 49 | void sendSleep(long startTime,int speed,int length){ 50 | long needTime=(long) (1000f*length/speed); 51 | long usedTime=System.currentTimeMillis()-startTime; 52 | if(usedTime0){ 69 | if(!sendedb){ 70 | pv=buf; 71 | pvl=len; 72 | sendedb=true; 73 | } 74 | n++; 75 | long needTime=1000*len/maxSpeed; 76 | long startTime=System.currentTimeMillis(); 77 | os.write(buf, 0, len); 78 | if(!sended){ 79 | sended=true; 80 | } 81 | long usedTime=System.currentTimeMillis()-startTime; 82 | if(usedTime mapList=new ArrayList(); 27 | 28 | HashMap mapRuleTable=new HashMap(); 29 | 30 | String configFilePath="port_map.json"; 31 | 32 | PortMapManager(MapClient mapClient){ 33 | this.mapClient=mapClient; 34 | //listenPort(); 35 | loadMapRule(); 36 | } 37 | 38 | void addMapRule(MapRule mapRule) throws Exception{ 39 | if(getMapRule(mapRule.name)!=null){ 40 | throw new Exception("映射 "+mapRule.name+" 已存在,请修改名称!"); 41 | } 42 | ServerSocket serverSocket=null; 43 | try { 44 | serverSocket = new ServerSocket(mapRule.getListen_port()); 45 | listen(serverSocket); 46 | mapList.add(mapRule); 47 | mapRuleTable.put(mapRule.listen_port, mapRule); 48 | saveMapRule(); 49 | } catch (IOException e2) { 50 | //e2.printStackTrace(); 51 | throw new Exception("端口 "+mapRule.getListen_port()+" 已经被占用!"); 52 | }finally{ 53 | // if(serverSocket!=null){ 54 | // serverSocket.close(); 55 | // } 56 | } 57 | } 58 | 59 | void removeMapRule(String name){ 60 | MapRule mapRule=getMapRule(name); 61 | if(mapRule!=null){ 62 | mapList.remove(mapRule); 63 | mapRuleTable.remove(mapRule.listen_port); 64 | if(mapRule.serverSocket!=null){ 65 | try { 66 | mapRule.serverSocket.close(); 67 | } catch (IOException e) { 68 | e.printStackTrace(); 69 | } 70 | } 71 | try { 72 | saveMapRule(); 73 | } catch (Exception e) { 74 | e.printStackTrace(); 75 | } 76 | } 77 | } 78 | 79 | void updateMapRule(MapRule mapRule_origin,MapRule mapRule_new) throws Exception{ 80 | if(getMapRule(mapRule_new.name)!=null&&!mapRule_origin.name.equals(mapRule_new.name)){ 81 | throw new Exception("映射 "+mapRule_new.name+" 已存在,请修改名称!"); 82 | } 83 | ServerSocket serverSocket=null; 84 | if(mapRule_origin.listen_port!=mapRule_new.listen_port){ 85 | try { 86 | serverSocket = new ServerSocket(mapRule_new.getListen_port()); 87 | listen(serverSocket); 88 | mapRule_origin.using=false; 89 | if(mapRule_origin.serverSocket!=null){ 90 | mapRule_origin.serverSocket.close(); 91 | } 92 | mapRule_origin.serverSocket=serverSocket; 93 | mapRuleTable.remove(mapRule_origin.listen_port); 94 | mapRuleTable.put(mapRule_new.listen_port, mapRule_new); 95 | } catch (IOException e2) { 96 | //e2.printStackTrace(); 97 | throw new Exception("端口 "+mapRule_new.getListen_port()+" 已经被占用!"); 98 | }finally{ 99 | // if(serverSocket!=null){ 100 | // serverSocket.close(); 101 | // } 102 | } 103 | } 104 | mapRule_origin.name=mapRule_new.name; 105 | mapRule_origin.listen_port=mapRule_new.listen_port; 106 | mapRule_origin.dst_port=mapRule_new.dst_port; 107 | saveMapRule(); 108 | 109 | } 110 | 111 | void saveMapRule() throws Exception{ 112 | JSONObject json=new JSONObject(); 113 | JSONArray json_map_list=new JSONArray(); 114 | json.put("map_list", json_map_list); 115 | if(mapList.size()==0){ 116 | 117 | } 118 | for(MapRule r:mapList){ 119 | JSONObject json_rule=new JSONObject(); 120 | json_rule.put("name", r.name); 121 | json_rule.put("listen_port", r.listen_port); 122 | json_rule.put("dst_port", r.dst_port); 123 | json_map_list.add(json_rule); 124 | } 125 | try { 126 | saveFile(json.toJSONString().getBytes("utf-8"), configFilePath); 127 | } catch (UnsupportedEncodingException e) { 128 | e.printStackTrace(); 129 | } catch (Exception e) { 130 | e.printStackTrace(); 131 | throw new Exception("保存失败!"); 132 | } 133 | } 134 | 135 | void loadMapRule(){ 136 | String content; 137 | JSONObject json=null; 138 | try { 139 | content = readFileUtf8(configFilePath); 140 | json=JSONObject.parseObject(content); 141 | } catch (Exception e) { 142 | //e.printStackTrace(); 143 | } 144 | if(json!=null&&json.containsKey("map_list")){ 145 | JSONArray json_map_list=json.getJSONArray("map_list"); 146 | for(int i=0;i getMapList() { 180 | return mapList; 181 | } 182 | 183 | public void setMapList(ArrayList mapList) { 184 | this.mapList = mapList; 185 | } 186 | 187 | void listen(final ServerSocket serverSocket){ 188 | Route.es.execute(new Runnable() { 189 | 190 | @Override 191 | public void run() { 192 | while(true){ 193 | try { 194 | final Socket socket=serverSocket.accept(); 195 | Route.es.execute(new Runnable() { 196 | 197 | @Override 198 | public void run() { 199 | int listenPort=serverSocket.getLocalPort(); 200 | MapRule mapRule=mapRuleTable.get(listenPort); 201 | if(mapRule!=null){ 202 | Route route=null; 203 | if(mapClient.isUseTcp()){ 204 | route=mapClient.route_tcp; 205 | }else { 206 | route=mapClient.route_udp; 207 | } 208 | PortMapProcess process=new PortMapProcess(mapClient,route, socket,mapClient.serverAddress,mapClient.serverPort,null, 209 | null,mapRule.dst_port); 210 | } 211 | } 212 | 213 | }); 214 | 215 | } catch (IOException e) { 216 | e.printStackTrace(); 217 | break; 218 | } 219 | } 220 | } 221 | }); 222 | } 223 | 224 | void saveFile(byte[] data,String path) throws Exception{ 225 | FileOutputStream fos=null; 226 | try { 227 | fos=new FileOutputStream(path); 228 | fos.write(data); 229 | } catch (Exception e) { 230 | throw e; 231 | } finally { 232 | if(fos!=null){ 233 | fos.close(); 234 | } 235 | } 236 | } 237 | 238 | public static String readFileUtf8(String path) throws Exception{ 239 | String str=null; 240 | FileInputStream fis=null; 241 | DataInputStream dis=null; 242 | try { 243 | File file=new File(path); 244 | 245 | int length=(int) file.length(); 246 | byte[] data=new byte[length]; 247 | 248 | fis=new FileInputStream(file); 249 | dis=new DataInputStream(fis); 250 | dis.readFully(data); 251 | str=new String(data,"utf-8"); 252 | 253 | } catch (Exception e) { 254 | //e.printStackTrace(); 255 | throw e; 256 | }finally{ 257 | if(fis!=null){ 258 | try { 259 | fis.close(); 260 | } catch (IOException e) { 261 | e.printStackTrace(); 262 | } 263 | } 264 | if(dis!=null){ 265 | try { 266 | dis.close(); 267 | } catch (IOException e) { 268 | e.printStackTrace(); 269 | } 270 | } 271 | } 272 | 273 | return str; 274 | } 275 | } 276 | -------------------------------------------------------------------------------- /src/net/fs/client/PortMapProcess.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 D1SM.net 2 | 3 | package net.fs.client; 4 | 5 | import java.io.DataInputStream; 6 | import java.io.DataOutputStream; 7 | import java.io.IOException; 8 | import java.net.Socket; 9 | import java.util.Random; 10 | 11 | import net.fs.rudp.ClientProcessorInterface; 12 | import net.fs.rudp.ConnectionUDP; 13 | import net.fs.rudp.Constant; 14 | import net.fs.rudp.Route; 15 | import net.fs.rudp.UDPInputStream; 16 | import net.fs.rudp.UDPOutputStream; 17 | 18 | import com.alibaba.fastjson.JSONObject; 19 | 20 | public class PortMapProcess implements ClientProcessorInterface{ 21 | 22 | Random ran=new Random(); 23 | 24 | UDPInputStream tis; 25 | 26 | UDPOutputStream tos; 27 | 28 | String serverAddress=""; 29 | 30 | int serverPort; 31 | 32 | ConnectionUDP conn; 33 | 34 | MapClient mapClient; 35 | 36 | public Socket srcSocket,dstSocket; 37 | 38 | String password_proxy_md5; 39 | 40 | DataInputStream srcIs=null; 41 | DataOutputStream srcOs=null; 42 | 43 | boolean closed=false; 44 | boolean success=false; 45 | 46 | public PortMapProcess(MapClient mapClient,Route route,final Socket srcSocket,String serverAddress2,int serverPort2,String password_proxy_md5, 47 | String dstAddress,int dstPort){ 48 | this.mapClient=mapClient; 49 | this.serverAddress=serverAddress2; 50 | this.serverPort=serverPort2; 51 | 52 | this.srcSocket=srcSocket; 53 | this.password_proxy_md5=password_proxy_md5; 54 | 55 | try { 56 | srcIs = new DataInputStream(srcSocket.getInputStream()); 57 | srcOs=new DataOutputStream(srcSocket.getOutputStream()); 58 | conn = route.getConnection(serverAddress, serverPort,null); 59 | tis=conn.uis; 60 | tos=conn.uos; 61 | 62 | JSONObject requestJson=new JSONObject(); 63 | requestJson.put("dst_address", dstAddress); 64 | requestJson.put("dst_port", dstPort); 65 | requestJson.put("password_proxy_md5", password_proxy_md5); 66 | byte[] requestData=requestJson.toJSONString().getBytes("utf-8"); 67 | tos.write(requestData, 0, requestData.length); 68 | 69 | 70 | final Pipe p1=new Pipe(); 71 | final Pipe p2=new Pipe(); 72 | 73 | 74 | byte[] responeData=tis.read2(); 75 | 76 | String hs=new String(responeData,"utf-8"); 77 | JSONObject responeJSon=JSONObject.parseObject(hs); 78 | int code=responeJSon.getIntValue("code"); 79 | String message=responeJSon.getString("message"); 80 | String uimessage=""; 81 | if(code==Constant.code_success){ 82 | 83 | Route.es.execute(new Runnable() { 84 | 85 | @Override 86 | public void run() { 87 | try { 88 | p2.pipe(tis, srcOs,1024*1024*1024,null); 89 | }catch (Exception e) { 90 | e.printStackTrace(); 91 | }finally{ 92 | close(); 93 | } 94 | } 95 | 96 | }); 97 | 98 | Route.es.execute(new Runnable() { 99 | 100 | @Override 101 | public void run() { 102 | try { 103 | p1.pipe(srcIs, tos,200*1024,p2); 104 | } catch (Exception e) { 105 | //e.printStackTrace(); 106 | }finally{ 107 | close(); 108 | } 109 | } 110 | 111 | }); 112 | success=true; 113 | uimessage=("连接服务器成功"); 114 | }else { 115 | close(); 116 | uimessage="连接服务器失败,"+message; 117 | } 118 | if(ClientUI.ui!=null){ 119 | ClientUI.ui.setMessage(uimessage); 120 | } 121 | } catch (Exception e1) { 122 | e1.printStackTrace(); 123 | } 124 | 125 | } 126 | 127 | void close(){ 128 | if(!closed){ 129 | closed=true; 130 | if(srcIs!=null){ 131 | try { 132 | srcIs.close(); 133 | } catch (IOException e) { 134 | e.printStackTrace(); 135 | } 136 | } 137 | if(srcOs!=null){ 138 | try { 139 | srcOs.close(); 140 | } catch (IOException e) { 141 | e.printStackTrace(); 142 | } 143 | } 144 | if(tos!=null){ 145 | tos.closeStream_Local(); 146 | } 147 | if(tis!=null){ 148 | tis.closeStream_Local(); 149 | } 150 | if(conn!=null){ 151 | conn.close_local(); 152 | } 153 | if(srcSocket!=null){ 154 | try { 155 | srcSocket.close(); 156 | } catch (IOException e) { 157 | e.printStackTrace(); 158 | } 159 | } 160 | mapClient.onProcessClose(this); 161 | 162 | } 163 | } 164 | 165 | @Override 166 | public void onMapClientClose() { 167 | try { 168 | srcSocket.close(); 169 | } catch (IOException e) { 170 | e.printStackTrace(); 171 | } 172 | } 173 | } 174 | -------------------------------------------------------------------------------- /src/net/fs/client/SpeedSetFrame.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 D1SM.net 2 | 3 | package net.fs.client; 4 | 5 | import java.awt.Dialog; 6 | import java.awt.Dimension; 7 | import java.awt.Insets; 8 | import java.awt.event.ActionEvent; 9 | import java.awt.event.ActionListener; 10 | 11 | import javax.swing.BorderFactory; 12 | import javax.swing.JButton; 13 | import javax.swing.JDialog; 14 | import javax.swing.JFrame; 15 | import javax.swing.JLabel; 16 | import javax.swing.JOptionPane; 17 | import javax.swing.JPanel; 18 | import javax.swing.JTextField; 19 | import javax.swing.SwingUtilities; 20 | 21 | import net.fs.rudp.Route; 22 | import net.miginfocom.swing.MigLayout; 23 | 24 | public class SpeedSetFrame extends JDialog{ 25 | 26 | private static final long serialVersionUID = -3248779355079724594L; 27 | 28 | ClientUI ui; 29 | 30 | JTextField text_ds,text_us; 31 | 32 | int downloadSpeed,uploadSpeed; 33 | 34 | SpeedSetFrame(final ClientUI ui,JFrame parent){ 35 | super(parent,Dialog.ModalityType.APPLICATION_MODAL); 36 | this.ui=ui; 37 | setTitle("设置带宽"); 38 | 39 | JPanel panel=(JPanel) getContentPane(); 40 | panel.setLayout(new MigLayout("alignx center,aligny center,insets 10 10 10 10")); 41 | 42 | 43 | panel.add(new JLabel("单位Mb ( 1Mb=128KB,10Mb=1280KB )"),"height ::,wrap"); 44 | panel.add(new JLabel("请正确输入,该值会直接影响加速效果."),"height ::,wrap"); 45 | 46 | JPanel p5=new JPanel(); 47 | panel.add(p5,"wrap"); 48 | p5.setLayout(new MigLayout("")); 49 | p5.add(new JLabel("下载带宽:")); 50 | text_ds=new JTextField(""); 51 | p5.add(text_ds,"width 50::"); 52 | p5.add(new JLabel("Mb")); 53 | 54 | p5.add(new JLabel(" ")); 55 | 56 | p5.add(new JLabel("上传带宽:")); 57 | text_us=new JTextField(""); 58 | p5.add(text_us,"width 50::"); 59 | //text_us.setEditable(false); 60 | p5.add(new JLabel("Mb")); 61 | 62 | JPanel p6=new JPanel(); 63 | panel.add(p6,"align center,wrap"); 64 | p6.setLayout(new MigLayout("align center")); 65 | 66 | JButton button_ok=createButton("确定"); 67 | p6.add(button_ok); 68 | button_ok.addActionListener(new ActionListener() { 69 | 70 | @Override 71 | public void actionPerformed(ActionEvent e) { 72 | String us=text_ds.getText().trim(); 73 | String ds=text_us.getText().trim(); 74 | try { 75 | int d=(int) (Float.parseFloat(us)*1024*1024/8/1.1); 76 | int u=(int) (Float.parseFloat(ds)*1024*1024/8/1.1); 77 | ui.setSpeed(d, u); 78 | setVisible(false); 79 | } catch (Exception e2) { 80 | //e2.printStackTrace(); 81 | JOptionPane.showMessageDialog(ui.mainFrame, "输入错误!"); 82 | } 83 | 84 | } 85 | }); 86 | 87 | p6.add(new JLabel(" ")); 88 | 89 | JButton button_cancel=createButton("取消"); 90 | p6.add(button_cancel); 91 | button_cancel.addActionListener(new ActionListener() { 92 | 93 | @Override 94 | public void actionPerformed(ActionEvent e) { 95 | setVisible(false); 96 | } 97 | }); 98 | 99 | pack(); 100 | setLocationRelativeTo(parent); 101 | setVisible(true); 102 | } 103 | 104 | JButton createButton(String name){ 105 | JButton button=new JButton(name); 106 | button.setMargin(new Insets(0,5,0,5)); 107 | button.setFocusPainted(false); 108 | return button; 109 | } 110 | 111 | 112 | 113 | } 114 | -------------------------------------------------------------------------------- /src/net/fs/client/TextComponentPopupMenu.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 D1SM.net 2 | 3 | package net.fs.client; 4 | 5 | import java.awt.Component; 6 | import java.awt.event.ActionEvent; 7 | import java.awt.event.ActionListener; 8 | import java.awt.event.MouseEvent; 9 | import java.awt.event.MouseListener; 10 | 11 | import javax.swing.JMenuItem; 12 | import javax.swing.JPasswordField; 13 | import javax.swing.JPopupMenu; 14 | import javax.swing.JTextField; 15 | import javax.swing.text.BadLocationException; 16 | import javax.swing.text.Document; 17 | import javax.swing.text.JTextComponent; 18 | import javax.swing.text.Position; 19 | 20 | public class TextComponentPopupMenu extends JPopupMenu implements 21 | MouseListener, ActionListener { 22 | 23 | private static final long serialVersionUID = 117096441855319758L; 24 | private static TextComponentPopupMenu sharedInstance = null; 25 | 26 | public static void installToComponent(JTextComponent c) { 27 | if (c instanceof JTextField && !(c instanceof JPasswordField)) { 28 | c.addMouseListener(TextComponentPopupMenu.getSharedInstance()); 29 | } 30 | } 31 | 32 | public static void uninstallFromComponent(JTextComponent c) { 33 | if (c instanceof JTextField && !(c instanceof JPasswordField)) { 34 | c.removeMouseListener(getSharedInstance()); 35 | } 36 | } 37 | 38 | JMenuItem cutItem, copyItem, pasteItem, deleteItem, selectAllItem; 39 | 40 | public TextComponentPopupMenu() { 41 | add(cutItem = new JMenuItem("剪切")); 42 | add(copyItem = new JMenuItem("复制")); 43 | add(pasteItem = new JMenuItem("粘贴")); 44 | add(deleteItem = new JMenuItem("删除")); 45 | addSeparator(); 46 | add(selectAllItem = new JMenuItem("全选")); 47 | 48 | cutItem.setMnemonic('T'); 49 | copyItem.setMnemonic('C'); 50 | pasteItem.setMnemonic('P'); 51 | deleteItem.setMnemonic('D'); 52 | selectAllItem.setMnemonic('A'); 53 | 54 | cutItem.addActionListener(this); 55 | copyItem.addActionListener(this); 56 | pasteItem.addActionListener(this); 57 | deleteItem.addActionListener(this); 58 | selectAllItem.addActionListener(this); 59 | } 60 | 61 | static TextComponentPopupMenu getSharedInstance() { 62 | if (sharedInstance == null) { 63 | sharedInstance = new TextComponentPopupMenu(); 64 | } 65 | return sharedInstance; 66 | } 67 | 68 | public void mouseReleased(MouseEvent e) { 69 | if (e.isPopupTrigger() && e.getSource() instanceof JTextField) { 70 | JTextField textfield = (JTextField) e.getSource(); 71 | if (Boolean.TRUE.equals(textfield 72 | .getClientProperty("DisablePopupMenu"))) { 73 | return; 74 | } 75 | textfield.requestFocusInWindow(); 76 | show(textfield, e.getX(), e.getY()); 77 | } 78 | } 79 | 80 | public void mouseClicked(MouseEvent e) { 81 | } 82 | 83 | public void mousePressed(MouseEvent e) { 84 | } 85 | 86 | public void mouseEntered(MouseEvent e) { 87 | } 88 | 89 | public void mouseExited(MouseEvent e) { 90 | } 91 | 92 | public void show(Component invoker, int x, int y) { 93 | JTextComponent tc = (JTextComponent) invoker; 94 | String sel = tc.getSelectedText(); 95 | 96 | boolean selected = sel != null && !sel.equals(""); 97 | boolean enableAndEditable = tc.isEnabled() && tc.isEditable(); 98 | 99 | cutItem.setEnabled(selected && enableAndEditable); 100 | copyItem.setEnabled(selected && tc.isEnabled()); 101 | deleteItem.setEnabled(selected && enableAndEditable); 102 | pasteItem.setEnabled(enableAndEditable); 103 | selectAllItem.setEnabled(tc.isEnabled()); 104 | 105 | super.show(invoker, x, y); 106 | } 107 | 108 | public void actionPerformed(ActionEvent e) { 109 | JTextComponent tc = (JTextComponent) getInvoker(); 110 | 111 | String sel = tc.getSelectedText(); 112 | 113 | if (e.getSource() == cutItem) { 114 | tc.cut(); 115 | } else if (e.getSource() == copyItem) { 116 | tc.copy(); 117 | } else if (e.getSource() == pasteItem) { 118 | tc.paste(); 119 | } else if (e.getSource() == selectAllItem) { 120 | tc.selectAll(); 121 | } else if (e.getSource() == deleteItem) { 122 | Document doc = tc.getDocument(); 123 | int start = tc.getSelectionStart(); 124 | int end = tc.getSelectionEnd(); 125 | 126 | try { 127 | Position p0 = doc.createPosition(start); 128 | Position p1 = doc.createPosition(end); 129 | 130 | if ((p0 != null) && (p1 != null) 131 | && (p0.getOffset() != p1.getOffset())) { 132 | doc.remove(p0.getOffset(), p1.getOffset() - p0.getOffset()); 133 | } 134 | } catch (BadLocationException be) { 135 | } 136 | } 137 | } 138 | } -------------------------------------------------------------------------------- /src/net/fs/rudp/AckListManage.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 D1SM.net 2 | 3 | package net.fs.rudp; 4 | 5 | import java.util.HashMap; 6 | import java.util.Iterator; 7 | 8 | public class AckListManage implements Runnable{ 9 | Thread mainThread; 10 | HashMap taskTable; 11 | public AckListManage(){ 12 | taskTable=new HashMap(); 13 | mainThread=new Thread(this); 14 | mainThread.start(); 15 | } 16 | 17 | synchronized void addAck(ConnectionUDP conn,int sequence){ 18 | if(!taskTable.containsKey(conn.connectId)){ 19 | AckListTask at=new AckListTask(conn); 20 | taskTable.put(conn.connectId, at); 21 | } 22 | AckListTask at=taskTable.get(conn.connectId); 23 | at.addAck(sequence); 24 | } 25 | 26 | synchronized void addLastRead(ConnectionUDP conn){ 27 | if(!taskTable.containsKey(conn.connectId)){ 28 | AckListTask at=new AckListTask(conn); 29 | taskTable.put(conn.connectId, at); 30 | } 31 | } 32 | 33 | public void run(){ 34 | while(true){ 35 | synchronized (this){ 36 | Iterator it=taskTable.keySet().iterator(); 37 | while(it.hasNext()){ 38 | int id=it.next(); 39 | AckListTask at=taskTable.get(id); 40 | at.run(); 41 | } 42 | taskTable.clear(); 43 | taskTable=null; 44 | taskTable=new HashMap(); 45 | } 46 | 47 | try { 48 | Thread.sleep(RUDPConfig.ackListDelay); 49 | } catch (InterruptedException e) { 50 | e.printStackTrace(); 51 | } 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/net/fs/rudp/AckListTask.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 D1SM.net 2 | 3 | package net.fs.rudp; 4 | 5 | import java.util.ArrayList; 6 | import java.util.HashSet; 7 | 8 | import net.fs.rudp.message.AckListMessage; 9 | 10 | 11 | 12 | public class AckListTask { 13 | ConnectionUDP conn; 14 | AckListMessage alm; 15 | int lastRead=0; 16 | ArrayList ackList; 17 | @SuppressWarnings("unchecked") 18 | HashSet set; 19 | AckListTask(ConnectionUDP conn){ 20 | this.conn=conn; 21 | ackList=new ArrayList(); 22 | set=new HashSet(); 23 | } 24 | 25 | synchronized void addAck(int sequence){ 26 | ////#MLog.println("sendACK "+sequence); 27 | if(!set.contains(sequence)){ 28 | ackList.add(sequence); 29 | set.add(sequence); 30 | } 31 | } 32 | 33 | synchronized void run(){ 34 | int offset=0; 35 | int packetLength=RUDPConfig.ackListSum; 36 | int length=ackList.size(); 37 | ////#MLog.println("ffffffffaaaaaaaaa "+length); 38 | int sum=(length/packetLength); 39 | if(length%packetLength!=0){ 40 | sum+=1; 41 | } 42 | if(sum==0){ 43 | sum=1; 44 | } 45 | int len=packetLength; 46 | if(length<=len){ 47 | conn.sender.sendALMessage(ackList); 48 | conn.sender.sendALMessage(ackList); 49 | }else{ 50 | for(int i=0;i nl=copy(offset,len,ackList); 52 | conn.sender.sendALMessage(nl); 53 | conn.sender.sendALMessage(nl); 54 | // conn.sender.sendALMessage(nl); 55 | // conn.sender.sendALMessage(nl); 56 | // conn.sender.sendALMessage(nl); 57 | offset+=packetLength; 58 | ////#MLog.println("fffffffffa "+nl.size()); 59 | if(offset+len>length){ 60 | len=length-(sum-1)*packetLength; 61 | } 62 | } 63 | } 64 | } 65 | 66 | ArrayList copy(int offset,int length,ArrayList ackList){ 67 | ArrayList nl= new ArrayList(); 68 | for(int i=0;i sendRecordTable=new HashMap(); 28 | 29 | 30 | HashMap sendRecordTable_remote=new HashMap(); 31 | 32 | 33 | long startSendTime=0; 34 | 35 | int maxSpeed=(int) (1024*1024); 36 | 37 | int initSpeed=(int) maxSpeed; 38 | 39 | int currentSpeed=initSpeed; 40 | 41 | int lastTime=-1; 42 | 43 | Object syn_timeid=new Object(); 44 | 45 | long sended=0; 46 | 47 | long markTime=0; 48 | 49 | long lastSendPingTime,lastReceivePingTime=System.currentTimeMillis(); 50 | 51 | Random ran=new Random(); 52 | 53 | HashMap pingTable=new HashMap(); 54 | 55 | public int pingDelay=250; 56 | 57 | int clientId_real=-1; 58 | 59 | long needSleep_All,trueSleep_All; 60 | 61 | int maxAcked=0; 62 | 63 | long lastLockTime; 64 | 65 | Route route; 66 | 67 | InetAddress dstIp; 68 | 69 | int dstPort; 70 | 71 | public HashMap connTable=new HashMap(); 72 | 73 | Object syn_connTable=new Object(); 74 | 75 | Object syn_tunTable=new Object(); 76 | 77 | String password; 78 | 79 | public ResendManage resendMange; 80 | 81 | boolean closed=false; 82 | 83 | { 84 | resendMange = new ResendManage(); 85 | } 86 | 87 | ClientControl(Route route,int clientId,InetAddress dstIp,int dstPort){ 88 | this.clientId=clientId; 89 | this.route=route; 90 | this.dstIp=dstIp; 91 | this.dstPort=dstPort; 92 | } 93 | 94 | public void onReceivePacket(DatagramPacket dp){ 95 | byte[] dpData=dp.getData(); 96 | int sType=0; 97 | sType=MessageCheck.checkSType(dp); 98 | int remote_clientId=ByteIntConvert.toInt(dpData, 8); 99 | if(sType==net.fs.rudp.message.MessageType.sType_PingMessage){ 100 | PingMessage pm=new PingMessage(dp); 101 | sendPingMessage2(pm.getPingId(),dp.getAddress(),dp.getPort()); 102 | currentSpeed=pm.getDownloadSpeed()*1024; 103 | }else if(sType==net.fs.rudp.message.MessageType.sType_PingMessage2){ 104 | PingMessage2 pm=new PingMessage2(dp); 105 | lastReceivePingTime=System.currentTimeMillis(); 106 | Long t=pingTable.get(pm.getPingId()); 107 | if(t!=null){ 108 | pingDelay=(int) (System.currentTimeMillis()-t); 109 | String protocal=""; 110 | if(route.isUseTcpTun()){ 111 | protocal="tcp"; 112 | }else { 113 | protocal="udp"; 114 | } 115 | //MLog.println(" receive_ping222: "+pm.getPingId()+" "+new Date()); 116 | //MLog.println("delay_"+protocal+" "+pingDelay+"ms "+dp.getAddress().getHostAddress()+":"+dp.getPort()); 117 | } 118 | } 119 | } 120 | 121 | public void sendPacket(DatagramPacket dp) throws IOException{ 122 | 123 | //加密 124 | 125 | route.sendPacket(dp); 126 | } 127 | 128 | void addConnection(ConnectionUDP conn){ 129 | synchronized (syn_connTable) { 130 | connTable.put(conn.connectId, conn); 131 | } 132 | } 133 | 134 | void removeConnection(ConnectionUDP conn){ 135 | synchronized (syn_connTable) { 136 | connTable.remove(conn.connectId); 137 | } 138 | } 139 | 140 | public void close(){ 141 | closed=true; 142 | route.clientManager.removeClient(clientId); 143 | synchronized (syn_connTable) { 144 | Iterator it=getConnTableIterator(); 145 | while(it.hasNext()){ 146 | final ConnectionUDP conn=connTable.get(it.next()); 147 | if(conn!=null){ 148 | Route.es.execute(new Runnable() { 149 | 150 | @Override 151 | public void run() { 152 | conn.stopnow=true; 153 | conn.destroy(true); 154 | } 155 | }); 156 | 157 | } 158 | } 159 | } 160 | } 161 | 162 | Iterator getConnTableIterator(){ 163 | Iterator it=null; 164 | synchronized (syn_connTable) { 165 | it=new CopiedIterator(connTable.keySet().iterator()); 166 | } 167 | return it; 168 | } 169 | 170 | public void updateClientId(int newClientId){ 171 | clientId_real=newClientId; 172 | sendRecordTable.clear(); 173 | sendRecordTable_remote.clear(); 174 | } 175 | 176 | public void onSendDataPacket(ConnectionUDP conn){ 177 | 178 | } 179 | 180 | public void sendPingMessage(){ 181 | int pingid=Math.abs(ran.nextInt()); 182 | long pingTime=System.currentTimeMillis(); 183 | pingTable.put(pingid, pingTime); 184 | lastSendPingTime=System.currentTimeMillis(); 185 | PingMessage lm=new PingMessage(0,route.localclientId,pingid,Route.localDownloadSpeed,Route.localUploadSpeed); 186 | lm.setDstAddress(dstIp); 187 | lm.setDstPort(dstPort); 188 | try { 189 | sendPacket(lm.getDatagramPacket()); 190 | } catch (IOException e) { 191 | //e.printStackTrace(); 192 | } 193 | } 194 | 195 | public void sendPingMessage2(int pingId,InetAddress dstIp,int dstPort){ 196 | PingMessage2 lm=new PingMessage2(0,route.localclientId,pingId); 197 | lm.setDstAddress(dstIp); 198 | lm.setDstPort(dstPort); 199 | try { 200 | sendPacket(lm.getDatagramPacket()); 201 | } catch (IOException e) { 202 | e.printStackTrace(); 203 | } 204 | } 205 | 206 | public void onReceivePing(PingMessage pm){ 207 | if(route.mode==2){ 208 | currentSpeed=pm.getDownloadSpeed()*1024; 209 | //#MLog.println("更新对方速度: "+currentSpeed); 210 | } 211 | } 212 | 213 | SendRecord getSendRecord(int timeId){ 214 | SendRecord record=null; 215 | synchronized (syn_timeid) { 216 | record=sendRecordTable.get(timeId); 217 | if(record==null){ 218 | record=new SendRecord(); 219 | record.setTimeId(timeId); 220 | sendRecordTable.put(timeId, record); 221 | } 222 | } 223 | return record; 224 | } 225 | 226 | public int getCurrentTimeId(){ 227 | long current=System.currentTimeMillis(); 228 | if(startSendTime==0){ 229 | startSendTime=current; 230 | } 231 | int timeId=(int) ((current-startSendTime)/1000); 232 | return timeId; 233 | } 234 | 235 | public int getTimeId(long time){ 236 | int timeId=(int) ((time-startSendTime)/1000); 237 | return timeId; 238 | } 239 | 240 | //纳秒 241 | public synchronized void sendSleep(long startTime,int length){ 242 | if(route.mode==1){ 243 | currentSpeed=Route.localUploadSpeed; 244 | } 245 | if(sended==0){ 246 | markTime=startTime; 247 | } 248 | sended+=length; 249 | //10K sleep 250 | if(sended>10*1024){ 251 | long needTime=(long) (1000*1000*1000f*sended/currentSpeed); 252 | long usedTime=System.nanoTime()-markTime; 253 | if(usedTime0){ 259 | if(sleepTime<=moreTime){ 260 | sleepTime=0; 261 | trueSleep_All-=sleepTime; 262 | } 263 | } 264 | 265 | long s=needTime/(1000*1000); 266 | int n=(int) (needTime%(1000*1000)); 267 | long t1=System.nanoTime(); 268 | if(sleepTime>0){ 269 | try { 270 | Thread.sleep(s, n); 271 | } catch (InterruptedException e) { 272 | e.printStackTrace(); 273 | } 274 | trueSleep_All+=(System.nanoTime()-t1); 275 | //#MLog.println("sssssssssss "+(trueSleep_All-needSleep_All)/(1000*1000)); 276 | } 277 | ////#MLog.println("sleepb "+sleepTime+" l "+sended+" s "+s+" n "+n+" tt "+(moreTime)); 278 | } 279 | sended=0; 280 | } 281 | 282 | } 283 | 284 | public Object getSynlock() { 285 | return synlock; 286 | } 287 | 288 | public void setSynlock(Object synlock) { 289 | this.synlock = synlock; 290 | } 291 | 292 | public void setClientId(int clientId) { 293 | this.clientId = clientId; 294 | } 295 | 296 | public int getClientId_real() { 297 | return clientId_real; 298 | } 299 | 300 | public void setClientId_real(int clientId_real) { 301 | this.clientId_real = clientId_real; 302 | lastReceivePingTime=System.currentTimeMillis(); 303 | } 304 | 305 | public long getLastSendPingTime() { 306 | return lastSendPingTime; 307 | } 308 | 309 | public void setLastSendPingTime(long lastSendPingTime) { 310 | this.lastSendPingTime = lastSendPingTime; 311 | } 312 | 313 | public long getLastReceivePingTime() { 314 | return lastReceivePingTime; 315 | } 316 | 317 | public void setLastReceivePingTime(long lastReceivePingTime) { 318 | this.lastReceivePingTime = lastReceivePingTime; 319 | } 320 | 321 | public String getPassword() { 322 | return password; 323 | } 324 | 325 | public void setPassword(String password) { 326 | this.password = password; 327 | } 328 | 329 | } 330 | -------------------------------------------------------------------------------- /src/net/fs/rudp/ClientManager.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 D1SM.net 2 | 3 | package net.fs.rudp; 4 | 5 | import java.net.InetAddress; 6 | import java.util.Date; 7 | import java.util.HashMap; 8 | import java.util.Iterator; 9 | 10 | import net.fs.utils.MLog; 11 | 12 | 13 | public class ClientManager { 14 | 15 | HashMap clientTable=new HashMap(); 16 | 17 | Thread mainThread; 18 | 19 | Route route; 20 | 21 | int receivePingTimeout=8*1000; 22 | 23 | int sendPingInterval=1*1000; 24 | 25 | Object syn_clientTable=new Object(); 26 | 27 | ClientManager(Route route){ 28 | this.route=route; 29 | mainThread=new Thread(){ 30 | @Override 31 | public void run(){ 32 | while(true){ 33 | try { 34 | Thread.sleep(1000); 35 | } catch (InterruptedException e) { 36 | e.printStackTrace(); 37 | } 38 | scanClientControl(); 39 | } 40 | } 41 | }; 42 | mainThread.start(); 43 | } 44 | 45 | void scanClientControl(){ 46 | Iterator it=getClientTableIterator(); 47 | long current=System.currentTimeMillis(); 48 | //MLog.println("ffffffffffff "+clientTable.size()); 49 | while(it.hasNext()){ 50 | ClientControl cc=clientTable.get(it.next()); 51 | if(cc!=null){ 52 | if(current-cc.getLastReceivePingTime()sendPingInterval){ 54 | cc.sendPingMessage(); 55 | } 56 | }else { 57 | //超时关闭client 58 | MLog.println("超时关闭client "+cc.dstIp.getHostAddress()+":"+cc.dstPort+" "+new Date()); 59 | // System.exit(0); 60 | synchronized (syn_clientTable) { 61 | cc.close(); 62 | } 63 | } 64 | } 65 | } 66 | } 67 | 68 | void removeClient(int clientId){ 69 | clientTable.remove(clientId); 70 | } 71 | 72 | Iterator getClientTableIterator(){ 73 | Iterator it=null; 74 | synchronized (syn_clientTable) { 75 | it=new CopiedIterator(clientTable.keySet().iterator()); 76 | } 77 | return it; 78 | } 79 | 80 | ClientControl getClientControl(int clientId,InetAddress dstIp,int dstPort){ 81 | ClientControl c=clientTable.get(clientId); 82 | if(c==null){ 83 | c=new ClientControl(route,clientId,dstIp,dstPort); 84 | synchronized (syn_clientTable) { 85 | clientTable.put(clientId, c); 86 | } 87 | } 88 | return c; 89 | } 90 | 91 | } 92 | -------------------------------------------------------------------------------- /src/net/fs/rudp/ClientProcessorInterface.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 D1SM.net 2 | 3 | package net.fs.rudp; 4 | 5 | public interface ClientProcessorInterface { 6 | 7 | public void onMapClientClose(); 8 | 9 | } 10 | -------------------------------------------------------------------------------- /src/net/fs/rudp/ConnInfo.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 D1SM.net 2 | 3 | package net.fs.rudp; 4 | 5 | import net.fs.rudp.StreamPipe.HttpHost; 6 | 7 | public class ConnInfo { 8 | 9 | 10 | String requestHost=null; 11 | 12 | String requestPath=null; 13 | 14 | boolean http=false; 15 | 16 | HttpHost host=null; 17 | 18 | public String getRequestHost() { 19 | return requestHost; 20 | } 21 | 22 | public void setRequestHost(String requestHost) { 23 | this.requestHost = requestHost; 24 | } 25 | 26 | public String getRequestPath() { 27 | return requestPath; 28 | } 29 | 30 | public void setRequestPath(String requestPath) { 31 | this.requestPath = requestPath; 32 | } 33 | 34 | public boolean isHttp() { 35 | return http; 36 | } 37 | 38 | public void setHttp(boolean http) { 39 | this.http = http; 40 | } 41 | 42 | public HttpHost getHost() { 43 | return host; 44 | } 45 | 46 | public void setHost(HttpHost host) { 47 | this.host = host; 48 | } 49 | 50 | } 51 | -------------------------------------------------------------------------------- /src/net/fs/rudp/ConnectException.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 D1SM.net 2 | 3 | package net.fs.rudp; 4 | 5 | import net.fs.utils.MLog; 6 | 7 | public class ConnectException extends Exception{ 8 | 9 | private static final long serialVersionUID = 8735513900170495107L; 10 | String message; 11 | ConnectException(String message){ 12 | this.message=message; 13 | } 14 | @Override 15 | public void printStackTrace(){ 16 | //#MLog.println("连接异常 "+message); 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /src/net/fs/rudp/ConnectionProcessor.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 D1SM.net 2 | 3 | package net.fs.rudp; 4 | 5 | 6 | 7 | public interface ConnectionProcessor { 8 | abstract void process(final ConnectionUDP conn); 9 | } 10 | -------------------------------------------------------------------------------- /src/net/fs/rudp/ConnectionUDP.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 D1SM.net 2 | 3 | package net.fs.rudp; 4 | import java.net.DatagramPacket; 5 | import java.net.InetAddress; 6 | import java.util.Random; 7 | import java.util.concurrent.LinkedBlockingQueue; 8 | 9 | public class ConnectionUDP { 10 | public InetAddress dstIp; 11 | public int dstPort; 12 | public Sender sender; 13 | public Receiver receiver; 14 | public UDPOutputStream uos; 15 | public UDPInputStream uis; 16 | long connetionId; 17 | Route route; 18 | int mode; 19 | private boolean connected=true; 20 | long lastLiveTime=System.currentTimeMillis(); 21 | long lastSendLiveTime=0; 22 | 23 | static Random ran=new Random(); 24 | 25 | int connectId; 26 | 27 | ConnectionProcessor connectionProcessor; 28 | 29 | private LinkedBlockingQueue dpBuffer=new LinkedBlockingQueue(); 30 | 31 | public ClientControl clientControl; 32 | 33 | public boolean localClosed=false,remoteClosed=false,destroied=false; 34 | 35 | public boolean stopnow=false; 36 | 37 | public ConnectionUDP(Route ro,InetAddress dstIp,int dstPort,int mode,int connectId,ClientControl clientControl) throws Exception { 38 | this.clientControl=clientControl; 39 | this.route=ro; 40 | this.dstIp=dstIp; 41 | this.dstPort=dstPort; 42 | this.mode=mode; 43 | if(mode==1){ 44 | //MLog.println(" 发起连接RUDP "+dstIp+":"+dstPort+" connectId "+connectId); 45 | }else if(mode==2){ 46 | 47 | //MLog.println(" 接受连接RUDP "+dstIp+":"+dstPort+" connectId "+connectId); 48 | } 49 | this.connectId=connectId; 50 | try { 51 | sender=new Sender(this); 52 | receiver=new Receiver(this); 53 | uos=new UDPOutputStream (this); 54 | uis=new UDPInputStream(this); 55 | if(mode==2){ 56 | ro.createTunnelProcessor().process(this); 57 | } 58 | } catch (Exception e) { 59 | e.printStackTrace(); 60 | connected=false; 61 | route.connTable.remove(connectId); 62 | e.printStackTrace(); 63 | //#MLog.println(" 连接失败RUDP "+connectId); 64 | synchronized(this){ 65 | notifyAll(); 66 | } 67 | throw e; 68 | } 69 | //#MLog.println(" 连接成功RUDP "+connectId); 70 | synchronized(this){ 71 | notifyAll(); 72 | } 73 | } 74 | 75 | public DatagramPacket getPacket(int connectId) throws InterruptedException{ 76 | DatagramPacket dp=(DatagramPacket)dpBuffer.take(); 77 | return dp; 78 | } 79 | 80 | @Override 81 | public String toString(){ 82 | return new String(dstIp+":"+dstPort); 83 | } 84 | 85 | public boolean isConnected(){ 86 | return connected; 87 | } 88 | 89 | public void close_local(){ 90 | if(!localClosed){ 91 | localClosed=true; 92 | if(!stopnow){ 93 | sender.sendCloseMessage_Conn(); 94 | } 95 | destroy(false); 96 | } 97 | } 98 | 99 | public void close_remote() { 100 | if(!remoteClosed){ 101 | remoteClosed=true; 102 | destroy(false); 103 | } 104 | } 105 | 106 | //完全关闭 107 | public void destroy(boolean force){ 108 | if(!destroied){ 109 | if((localClosed&&remoteClosed)||force){ 110 | destroied=true; 111 | connected=false; 112 | uis.closeStream_Local(); 113 | uos.closeStream_Local(); 114 | sender.destroy(); 115 | receiver.destroy(); 116 | route.removeConnection(this); 117 | clientControl.removeConnection(this); 118 | } 119 | } 120 | } 121 | 122 | public void close_timeout(){ 123 | ////#MLog.println("超时关闭RDP连接"); 124 | } 125 | 126 | void live(){ 127 | lastLiveTime=System.currentTimeMillis(); 128 | } 129 | } 130 | -------------------------------------------------------------------------------- /src/net/fs/rudp/Constant.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 D1SM.net 2 | 3 | package net.fs.rudp; 4 | 5 | public class Constant { 6 | 7 | 8 | public static int code_success=1; 9 | 10 | public static int code_failed=0; 11 | 12 | public static int code_no_port=41; 13 | 14 | public static int code_password_error=42; 15 | 16 | static int protocal_portmap=5755682; 17 | 18 | public static int protocal_socks5proxy=544643; 19 | 20 | } 21 | -------------------------------------------------------------------------------- /src/net/fs/rudp/CopiedIterator.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 D1SM.net 2 | 3 | package net.fs.rudp; 4 | 5 | import java.util.Iterator; 6 | import java.util.LinkedList; 7 | 8 | public class CopiedIterator implements Iterator { 9 | private Iterator iterator = null; 10 | public CopiedIterator(Iterator itr) { 11 | LinkedList list = new LinkedList( ); 12 | while(itr.hasNext( )) { 13 | list.add(itr.next( )); 14 | } 15 | this.iterator = list.iterator( ); 16 | } 17 | public boolean hasNext( ) { 18 | return this.iterator.hasNext( ); 19 | } 20 | public void remove( ) { 21 | throw new UnsupportedOperationException("This is a read-only iterator."); 22 | } 23 | public Object next( ) { 24 | return this.iterator.next( ); 25 | } 26 | } -------------------------------------------------------------------------------- /src/net/fs/rudp/MapSocketPorcessor.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 D1SM.net 2 | 3 | package net.fs.rudp; 4 | 5 | import java.io.DataInputStream; 6 | import java.io.DataOutputStream; 7 | import java.io.IOException; 8 | import java.net.Socket; 9 | import java.util.ArrayList; 10 | import java.util.Random; 11 | import java.util.concurrent.ExecutorService; 12 | import java.util.concurrent.Executors; 13 | 14 | import net.fs.utils.MLog; 15 | 16 | 17 | public class MapSocketPorcessor implements PipeListener{ 18 | 19 | 20 | Socket srcSocket; 21 | Socket dstSocket; 22 | 23 | public DataInputStream srcIs; 24 | public DataOutputStream dstOs; 25 | public DataInputStream dstIs; 26 | public DataOutputStream srcOs; 27 | 28 | Object srcReadOb=new Object(); 29 | Object dstReadOb=new Object(); 30 | Object dstWriteOb=new Object(); 31 | Object srcWriteOb=new Object(); 32 | 33 | ArrayList srcReadBuffer=new ArrayList(); 34 | ArrayList dstReadBuffer=new ArrayList(); 35 | 36 | Thread srcReadThread; 37 | Thread dstWriteThread; 38 | Thread srcWriteThread; 39 | Thread dstReadThread; 40 | byte[] srcPreRead=new byte[0]; 41 | 42 | int maxDstRead=1; 43 | int maxSrcRead=1; 44 | 45 | boolean isSuperSocket=false; 46 | 47 | boolean dstReadComplete=false; 48 | 49 | boolean srcReadComplete=false; 50 | 51 | boolean srcWriteComplete=false; 52 | 53 | boolean dstWriteComplete=false; 54 | 55 | boolean dstClosed=false; 56 | 57 | boolean srcClosed=false; 58 | 59 | String st=" "; 60 | 61 | 62 | String ss=""; 63 | 64 | static int n=0; 65 | 66 | Random ran=new Random(); 67 | 68 | long id; 69 | 70 | static int m=0,a,b; 71 | 72 | boolean closed=false; 73 | 74 | long lastActiveTime=System.currentTimeMillis(); 75 | 76 | //static HashMap procTable=new HashMap(); 77 | 78 | static ExecutorService es; 79 | 80 | MapSocketPorcessor mp; 81 | 82 | Socket socketA,socketB; 83 | 84 | int supserSocketId=-1; 85 | 86 | String requestHost=null; 87 | 88 | static { 89 | es=Executors.newCachedThreadPool(); 90 | } 91 | 92 | public MapSocketPorcessor(){ 93 | 94 | } 95 | 96 | public void setDstSocket(Socket dstSocket){ 97 | this.dstSocket=dstSocket; 98 | } 99 | 100 | public void setId(long id){ 101 | this.id=id; 102 | } 103 | 104 | public boolean isClosed(){ 105 | return closed; 106 | } 107 | 108 | public long getLastActiveTime(){ 109 | return lastActiveTime; 110 | } 111 | 112 | void active(){ 113 | lastActiveTime=System.currentTimeMillis(); 114 | } 115 | 116 | public long getId(){ 117 | return id; 118 | } 119 | 120 | public void closeAll(){ 121 | closeAll(true); 122 | } 123 | 124 | public void closeAll(boolean closeDst){ 125 | //procTable.remove(id); 126 | //Log.println("closeAll AAAAAAAAA"); 127 | if(!closed){ 128 | //Log.println("closeAll BBBBBBBBBB"); 129 | closed=true; 130 | //#MLog.println("MapSocketPorcessor Close"); 131 | try { 132 | srcSocket.close(); 133 | } catch (IOException e) { 134 | e.printStackTrace(); 135 | } 136 | if(closeDst){ 137 | try { 138 | dstSocket.close(); 139 | } catch (IOException e) { 140 | e.printStackTrace(); 141 | } 142 | } 143 | } 144 | } 145 | 146 | void tryClose(){ 147 | closeAll(); 148 | } 149 | 150 | public void start(){ 151 | Runnable t=new Runnable(){ 152 | public void run(){ 153 | try { 154 | ConnInfo connInfo=new ConnInfo(); 155 | StreamPipe p1=new StreamPipe(connInfo,srcIs,dstOs,10*1024,1000*1024); 156 | StreamPipe p2=new StreamPipe(connInfo,dstIs,srcOs,10*1024,1000*1024); 157 | p1.setType(StreamPipe.type_request); 158 | //p1.addListener(mp); 159 | //p2.addListener(mp); 160 | p1.setSocketA(socketA); 161 | p1.setSocketB(socketB); 162 | p2.setType(StreamPipe.type_respone); 163 | p2.setSocketA(socketA); 164 | p2.setSocketB(socketB); 165 | p1.setSupserSocketId(supserSocketId); 166 | p2.setSupserSocketId(supserSocketId); 167 | } catch (Exception e1) { 168 | e1.printStackTrace(); 169 | } 170 | } 171 | }; 172 | es.execute(t); 173 | } 174 | 175 | public void pipeClose() { 176 | //closeAll(); 177 | 178 | } 179 | 180 | public Socket getSocketA() { 181 | return socketA; 182 | } 183 | 184 | public void setSocketA(Socket socketA) { 185 | this.socketA = socketA; 186 | } 187 | 188 | public Socket getSocketB() { 189 | return socketB; 190 | } 191 | 192 | public void setSocketB(Socket socketB) { 193 | this.socketB = socketB; 194 | } 195 | 196 | public int getSupserSocketId() { 197 | return supserSocketId; 198 | } 199 | 200 | public void setSupserSocketId(int supserSocketId) { 201 | this.supserSocketId = supserSocketId; 202 | } 203 | 204 | public String getRequestHost() { 205 | return requestHost; 206 | } 207 | 208 | public void setRequestHost(String requestHost) { 209 | this.requestHost = requestHost; 210 | } 211 | 212 | } 213 | -------------------------------------------------------------------------------- /src/net/fs/rudp/MessageInterface.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 D1SM.net 2 | 3 | package net.fs.rudp; 4 | 5 | import java.net.DatagramPacket; 6 | 7 | public interface MessageInterface { 8 | public int getVer(); 9 | public int getSType(); 10 | public DatagramPacket getDatagramPacket(); 11 | } 12 | -------------------------------------------------------------------------------- /src/net/fs/rudp/PipeListener.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 D1SM.net 2 | 3 | package net.fs.rudp; 4 | 5 | public interface PipeListener { 6 | 7 | void pipeClose(); 8 | 9 | } 10 | -------------------------------------------------------------------------------- /src/net/fs/rudp/RUDPConfig.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 D1SM.net 2 | 3 | package net.fs.rudp; 4 | 5 | public class RUDPConfig { 6 | 7 | public static short protocal_ver=0; 8 | 9 | public static int packageSize=1000; 10 | 11 | public static boolean twice_udp=false; 12 | 13 | public static boolean twice_tcp=false; 14 | 15 | public static int maxWin = 5*1024; 16 | 17 | public static int ackListDelay = 5; 18 | public static int ackListSum = 300; 19 | 20 | public static boolean double_send_start = true; 21 | 22 | public static int reSendDelay_min = 100; 23 | public static float reSendDelay = 0.37f; 24 | public static int reSendTryTimes = 10; 25 | 26 | } 27 | -------------------------------------------------------------------------------- /src/net/fs/rudp/ReceivePingException.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 D1SM.net 2 | 3 | package net.fs.rudp; 4 | 5 | import net.fs.utils.MLog; 6 | 7 | public class ReceivePingException extends Exception{ 8 | /** 9 | * 10 | */ 11 | private static final long serialVersionUID = -5199731243611486228L; 12 | String message; 13 | ReceivePingException(String message){ 14 | this.message=message; 15 | } 16 | @Override 17 | public void printStackTrace(){ 18 | //#MLog.println("Ping寮傚父 "+message); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/net/fs/rudp/Receiver.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 D1SM.net 2 | 3 | package net.fs.rudp; 4 | import java.net.DatagramPacket; 5 | import java.net.InetAddress; 6 | import java.util.ArrayList; 7 | import java.util.HashMap; 8 | 9 | import net.fs.rudp.message.AckListMessage; 10 | import net.fs.rudp.message.CloseMessage_Conn; 11 | import net.fs.rudp.message.CloseMessage_Stream; 12 | import net.fs.rudp.message.DataMessage; 13 | import net.fs.utils.MessageCheck; 14 | 15 | 16 | public class Receiver { 17 | ConnectionUDP conn; 18 | Sender sender; 19 | public InetAddress dstIp; 20 | public int dstPort; 21 | HashMap receiveTable=new HashMap(); 22 | int lastRead=-1; 23 | int lastReceive=-1; 24 | Object availOb=new Object(); 25 | 26 | boolean isReady=false; 27 | Object readyOb=new Object(); 28 | byte[] b4=new byte[4]; 29 | int lastRead1=0; 30 | int maxWinR=10; 31 | int lastRead2=-1; 32 | UDPInputStream uis; 33 | 34 | float availWin=RUDPConfig.maxWin; 35 | 36 | int currentRemoteTimeId; 37 | 38 | int closeOffset; 39 | 40 | boolean streamClose=false; 41 | 42 | boolean reveivedClose=false; 43 | 44 | static int m=0,x,x2,c; 45 | 46 | boolean b=false,b2; 47 | 48 | public int nw; 49 | 50 | long received; 51 | 52 | Receiver(ConnectionUDP conn){ 53 | this.conn=conn; 54 | uis=new UDPInputStream(conn); 55 | this.sender=conn.sender; 56 | this.dstIp=conn.dstIp; 57 | this.dstPort=conn.dstPort; 58 | } 59 | 60 | //接收流数据 61 | public byte[] receive() throws ConnectException { 62 | DataMessage me=null; 63 | if(conn.isConnected()){ 64 | me=receiveTable.get(lastRead+1); 65 | synchronized (availOb){ 66 | if(me==null){ 67 | //MLog.println("等待中 "+conn.connectId+" "+(lastRead+1)); 68 | 69 | try { 70 | availOb.wait(); 71 | } catch (InterruptedException e) { 72 | e.printStackTrace(); 73 | } 74 | me=receiveTable.get(lastRead+1); 75 | //MLog.println("等待完成aaa "+conn.connectId+" "+(lastRead+1)); 76 | } 77 | } 78 | 79 | }else{ 80 | throw new ConnectException("连接未建立"); 81 | } 82 | 83 | if(!streamClose){ 84 | checkCloseOffset_Remote(); 85 | if(me==null){ 86 | throw new ConnectException("连接已断开ccccccc"); 87 | }else { 88 | } 89 | conn.sender.sendLastReadDelay(); 90 | 91 | lastRead++; 92 | synchronized (availOb){ 93 | receiveTable.remove(me.getSequence()); 94 | } 95 | 96 | received+=me.getData().length; 97 | //System.out.println("received "+received/1024/1024+"MB"); 98 | return me.getData(); 99 | }else{ 100 | throw new ConnectException("连接已断开"); 101 | } 102 | } 103 | 104 | public void onReceivePacket(DatagramPacket dp){ 105 | DataMessage me; 106 | if(dp!=null){ 107 | if(conn.isConnected()){ 108 | int ver=MessageCheck.checkVer(dp); 109 | int sType=MessageCheck.checkSType(dp); 110 | if(ver==RUDPConfig.protocal_ver){ 111 | conn.live(); 112 | if(sType==net.fs.rudp.message.MessageType.sType_DataMessage){ 113 | me=new DataMessage(dp); 114 | int timeId=me.getTimeId(); 115 | SendRecord record=conn.clientControl.sendRecordTable_remote.get(timeId); 116 | if(record==null){ 117 | record=new SendRecord(); 118 | record.setTimeId(timeId); 119 | conn.clientControl.sendRecordTable_remote.put(timeId, record); 120 | } 121 | record.addSended(me.getData().length); 122 | 123 | if(timeId>currentRemoteTimeId){ 124 | currentRemoteTimeId=timeId; 125 | } 126 | 127 | int sequence=me.getSequence(); 128 | 129 | conn.sender.sendAckDelay(me.getSequence()); 130 | if(sequence>lastRead){ 131 | synchronized (availOb){ 132 | receiveTable.put(sequence, me); 133 | if(receiveTable.containsKey(lastRead+1)){ 134 | availOb.notify(); 135 | } 136 | } 137 | } 138 | }else if(sType==net.fs.rudp.message.MessageType.sType_AckListMessage){ 139 | AckListMessage alm=new AckListMessage(dp); 140 | int lastRead3=alm.getLastRead(); 141 | if(lastRead3>lastRead2){ 142 | lastRead2=lastRead3; 143 | } 144 | ArrayList ackList=alm.getAckList(); 145 | 146 | for(int i=0;irc1.getAckedSize()){ 153 | rc1.setAckedSize(alm.getS1()); 154 | } 155 | } 156 | 157 | SendRecord rc2=conn.clientControl.getSendRecord(alm.getR2()); 158 | if(rc2!=null){ 159 | if(alm.getS2()>rc2.getAckedSize()){ 160 | rc2.setAckedSize(alm.getS2()); 161 | } 162 | } 163 | 164 | SendRecord rc3=conn.clientControl.getSendRecord(alm.getR3()); 165 | if(rc3!=null){ 166 | if(alm.getS3()>rc3.getAckedSize()){ 167 | rc3.setAckedSize(alm.getS3()); 168 | } 169 | } 170 | 171 | if(checkWin()){ 172 | conn.sender.play(); 173 | } 174 | }else if(sType==net.fs.rudp.message.MessageType.sType_CloseMessage_Stream){ 175 | CloseMessage_Stream cm=new CloseMessage_Stream(dp); 176 | reveivedClose=true; 177 | int n=cm.getCloseOffset(); 178 | closeStream_Remote(n); 179 | }else if(sType==net.fs.rudp.message.MessageType.sType_CloseMessage_Conn){ 180 | CloseMessage_Conn cm2=new CloseMessage_Conn(dp); 181 | conn.close_remote(); 182 | }else{ 183 | ////#MLog.println("未处理数据包 "+sType); 184 | } 185 | } 186 | 187 | } 188 | } 189 | 190 | } 191 | 192 | public void destroy(){ 193 | //#MLog.println("destroy destroy destroy"); 194 | synchronized (availOb) { 195 | receiveTable.clear(); 196 | } 197 | } 198 | 199 | boolean checkWin(){ 200 | nw=conn.sender.sendOffset-lastRead2; 201 | boolean b=false; 202 | if(nw=closeOffset-1){ 220 | streamClose=true; 221 | synchronized (availOb){ 222 | availOb.notifyAll(); 223 | } 224 | conn.sender.closeStream_Remote(); 225 | } 226 | } 227 | } 228 | } 229 | 230 | void closeStream_Local(){ 231 | if(!streamClose){ 232 | c++; 233 | streamClose=true; 234 | synchronized (availOb){ 235 | availOb.notifyAll(); 236 | } 237 | conn.sender.closeStream_Local(); 238 | } 239 | } 240 | 241 | public int getCurrentTimeId() { 242 | return currentRemoteTimeId; 243 | } 244 | 245 | public void setCurrentTimeId(int currentTimeId) { 246 | this.currentRemoteTimeId = currentTimeId; 247 | } 248 | 249 | 250 | public int getCloseOffset() { 251 | return closeOffset; 252 | } 253 | 254 | 255 | public void setCloseOffset(int closeOffset) { 256 | this.closeOffset = closeOffset; 257 | } 258 | 259 | } 260 | -------------------------------------------------------------------------------- /src/net/fs/rudp/ResendItem.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 D1SM.net 2 | 3 | package net.fs.rudp; 4 | 5 | public class ResendItem { 6 | 7 | int count; 8 | 9 | ConnectionUDP conn; 10 | 11 | int sequence; 12 | 13 | long resendTime; 14 | 15 | ResendItem(ConnectionUDP conn,int sequence){ 16 | this.conn=conn; 17 | this.sequence=sequence; 18 | } 19 | 20 | void addCount(){ 21 | count++; 22 | } 23 | 24 | public int getCount() { 25 | return count; 26 | } 27 | 28 | public void setCount(int count) { 29 | this.count = count; 30 | } 31 | 32 | public ConnectionUDP getConn() { 33 | return conn; 34 | } 35 | 36 | public void setConn(ConnectionUDP conn) { 37 | this.conn = conn; 38 | } 39 | 40 | public int getSequence() { 41 | return sequence; 42 | } 43 | 44 | public void setSequence(int sequence) { 45 | this.sequence = sequence; 46 | } 47 | 48 | public long getResendTime() { 49 | return resendTime; 50 | } 51 | 52 | public void setResendTime(long resendTime) { 53 | this.resendTime = resendTime; 54 | } 55 | 56 | } 57 | -------------------------------------------------------------------------------- /src/net/fs/rudp/ResendManage.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 D1SM.net 2 | 3 | package net.fs.rudp; 4 | 5 | import java.util.HashMap; 6 | import java.util.concurrent.LinkedBlockingQueue; 7 | 8 | 9 | 10 | public class ResendManage implements Runnable{ 11 | 12 | boolean haveTask=false; 13 | Object signalOb=new Object(); 14 | Thread mainThread; 15 | long vTime=0; 16 | long lastReSendTime; 17 | 18 | LinkedBlockingQueue taskList=new LinkedBlockingQueue(); 19 | 20 | public ResendManage(){ 21 | Route.es.execute(this); 22 | } 23 | 24 | public void addTask(final ConnectionUDP conn,final int sequence){ 25 | ResendItem ri=new ResendItem(conn, sequence); 26 | ri.setResendTime(getNewResendTime(conn)); 27 | taskList.add(ri); 28 | } 29 | 30 | long getNewResendTime(ConnectionUDP conn){ 31 | int delayAdd=conn.clientControl.pingDelay+(int) ((float)conn.clientControl.pingDelay*RUDPConfig.reSendDelay); 32 | if(delayAdd0){ 46 | Thread.sleep(sleepTime); 47 | } 48 | ri.addCount(); 49 | 50 | if(ri.conn.sender.getDataMessage(ri.sequence)!=null){ 51 | 52 | if(!ri.conn.stopnow){ 53 | //多线程重发容易内存溢出 54 | // Route.es.execute(new Runnable() { 55 | // 56 | // @Override 57 | // public void run() { 58 | // ri.conn.sender.reSend(ri.sequence,ri.getCount()); 59 | // } 60 | // 61 | // }); 62 | ri.conn.sender.reSend(ri.sequence,ri.getCount()); 63 | } 64 | 65 | } 66 | if(ri.getCount() connTable; 31 | Route route; 32 | Thread mainThread; 33 | Thread reveiveThread; 34 | 35 | public static ThreadPoolExecutor es; 36 | 37 | public AckListManage delayAckManage; 38 | 39 | Object syn_ds2Table=new Object(); 40 | 41 | Object syn_tunTable=new Object(); 42 | 43 | Random ran=new Random(); 44 | 45 | public int localclientId=Math.abs(ran.nextInt()); 46 | 47 | LinkedBlockingQueue packetBuffer=new LinkedBlockingQueue(); 48 | 49 | public static int mode_server=2; 50 | 51 | public static int mode_client=1; 52 | 53 | public int mode=mode_client;//1客户端,2服务端 54 | 55 | String pocessName=""; 56 | 57 | HashSet setedTable=new HashSet(); 58 | 59 | static int vv; 60 | 61 | HashSet closedTable=new HashSet(); 62 | 63 | public static int localDownloadSpeed,localUploadSpeed; 64 | 65 | ClientManager clientManager; 66 | 67 | HashSet pingTable=new HashSet(); 68 | 69 | public CapEnv capEnv=null; 70 | 71 | public ClientControl lastClientControl; 72 | 73 | public boolean useTcpTun=true; 74 | 75 | public HashMap contentTable=new HashMap(); 76 | 77 | private static List listenerList=new Vector(); 78 | 79 | { 80 | 81 | delayAckManage = new AckListManage(); 82 | } 83 | 84 | static{ 85 | SynchronousQueue queue = new SynchronousQueue(); 86 | ThreadPoolExecutor executor = new ThreadPoolExecutor(100, Integer.MAX_VALUE, 10*1000, TimeUnit.MILLISECONDS, queue); 87 | es=executor; 88 | } 89 | 90 | public Route(String pocessName,short routePort,int mode2,boolean tcp) throws Exception{ 91 | 92 | this.mode=mode2; 93 | useTcpTun=tcp; 94 | this.pocessName=pocessName; 95 | if(useTcpTun){ 96 | if(mode==2){ 97 | //服务端 98 | VDatagramSocket d=new VDatagramSocket(routePort); 99 | d.setClient(false); 100 | try { 101 | capEnv=new CapEnv(false); 102 | capEnv.setListenPort(routePort); 103 | capEnv.init(); 104 | } catch (Exception e) { 105 | //e.printStackTrace(); 106 | throw e; 107 | } 108 | d.setCapEnv(capEnv); 109 | 110 | ds=d; 111 | }else { 112 | //客户端 113 | VDatagramSocket d=new VDatagramSocket(); 114 | d.setClient(true); 115 | try { 116 | capEnv=new CapEnv(true); 117 | capEnv.init(); 118 | } catch (Exception e) { 119 | //e.printStackTrace(); 120 | throw e; 121 | } 122 | d.setCapEnv(capEnv); 123 | 124 | ds=d; 125 | } 126 | }else { 127 | if(mode==2){ 128 | MLog.info("Listen udp port: "+CapEnv.toUnsigned(routePort)); 129 | ds=new DatagramSocket(CapEnv.toUnsigned(routePort)); 130 | }else { 131 | ds=new DatagramSocket(); 132 | } 133 | } 134 | 135 | connTable=new HashMap(); 136 | clientManager=new ClientManager(this); 137 | reveiveThread=new Thread(){ 138 | @Override 139 | public void run(){ 140 | while(true){ 141 | byte[] b=new byte[1500]; 142 | DatagramPacket dp=new DatagramPacket(b,b.length); 143 | try { 144 | ds.receive(dp); 145 | //MLog.println("接收 "+dp.getAddress()); 146 | packetBuffer.add(dp); 147 | } catch (IOException e) { 148 | e.printStackTrace(); 149 | try { 150 | Thread.sleep(1); 151 | } catch (InterruptedException e1) { 152 | e1.printStackTrace(); 153 | } 154 | continue; 155 | } 156 | } 157 | } 158 | }; 159 | reveiveThread.start(); 160 | 161 | mainThread=new Thread(){ 162 | public void run() { 163 | while(true){ 164 | DatagramPacket dp=null; 165 | try { 166 | dp = packetBuffer.take(); 167 | } catch (InterruptedException e1) { 168 | e1.printStackTrace(); 169 | } 170 | if(dp==null){ 171 | continue; 172 | } 173 | long t1=System.currentTimeMillis(); 174 | byte[] dpData=dp.getData(); 175 | 176 | int sType=0; 177 | if(dp.getData().length<4){ 178 | return; 179 | } 180 | sType=MessageCheck.checkSType(dp); 181 | //MLog.println("route receive MessageType111#"+sType+" "+dp.getAddress()+":"+dp.getPort()); 182 | if(dp!=null){ 183 | 184 | final int connectId=ByteIntConvert.toInt(dpData, 4); 185 | int remote_clientId=ByteIntConvert.toInt(dpData, 8); 186 | 187 | if(closedTable.contains(connectId)&&connectId!=0){ 188 | //#MLog.println("忽略已关闭连接包 "+connectId); 189 | continue; 190 | } 191 | 192 | if(sType==net.fs.rudp.message.MessageType.sType_PingMessage 193 | ||sType==net.fs.rudp.message.MessageType.sType_PingMessage2){ 194 | ClientControl clientControl=null; 195 | if(mode==2){ 196 | //发起 197 | clientControl=clientManager.getClientControl(remote_clientId,dp.getAddress(),dp.getPort()); 198 | }else if(mode==1){ 199 | //接收 200 | String key=dp.getAddress().getHostAddress()+":"+dp.getPort(); 201 | int sim_clientId=Math.abs(key.hashCode()); 202 | clientControl=clientManager.getClientControl(sim_clientId,dp.getAddress(),dp.getPort()); 203 | } 204 | clientControl.onReceivePacket(dp); 205 | }else { 206 | //发起 207 | if(mode==1){ 208 | if(!setedTable.contains(remote_clientId)){ 209 | String key=dp.getAddress().getHostAddress()+":"+dp.getPort(); 210 | int sim_clientId=Math.abs(key.hashCode()); 211 | ClientControl clientControl=clientManager.getClientControl(sim_clientId,dp.getAddress(),dp.getPort()); 212 | if(clientControl.getClientId_real()==-1){ 213 | clientControl.setClientId_real(remote_clientId); 214 | //#MLog.println("首次设置clientId "+remote_clientId); 215 | }else { 216 | if(clientControl.getClientId_real()!=remote_clientId){ 217 | //#MLog.println("服务端重启更新clientId "+sType+" "+clientControl.getClientId_real()+" new: "+remote_clientId); 218 | clientControl.updateClientId(remote_clientId); 219 | } 220 | } 221 | //#MLog.println("cccccc "+sType+" "+remote_clientId); 222 | setedTable.add(remote_clientId); 223 | } 224 | } 225 | 226 | 227 | //udp connection 228 | if(mode==2){ 229 | //接收 230 | try { 231 | getConnection2(dp.getAddress(),dp.getPort(),connectId,remote_clientId); 232 | } catch (Exception e) { 233 | e.printStackTrace(); 234 | } 235 | } 236 | 237 | final ConnectionUDP ds3=connTable.get(connectId); 238 | if(ds3!=null){ 239 | final DatagramPacket dp2=dp; 240 | ds3.receiver.onReceivePacket(dp2); 241 | if(sType==MessageType.sType_DataMessage){ 242 | TrafficEvent event=new TrafficEvent("",ran.nextLong(),dp.getLength(),TrafficEvent.type_downloadTraffic); 243 | fireEvent(event); 244 | } 245 | } 246 | 247 | } 248 | } 249 | } 250 | } 251 | }; 252 | mainThread.start(); 253 | 254 | } 255 | 256 | public static void addTrafficlistener(Trafficlistener listener){ 257 | listenerList.add(listener); 258 | } 259 | 260 | static void fireEvent(TrafficEvent event){ 261 | for(Trafficlistener listener:listenerList){ 262 | int type=event.getType(); 263 | if(type==TrafficEvent.type_downloadTraffic){ 264 | listener.trafficDownload(event); 265 | }else if(type==TrafficEvent.type_uploadTraffic){ 266 | listener.trafficUpload(event); 267 | } 268 | } 269 | } 270 | 271 | public void sendPacket(DatagramPacket dp) throws IOException{ 272 | ds.send(dp); 273 | } 274 | 275 | public ConnectionProcessor createTunnelProcessor(){ 276 | ConnectionProcessor o=null; 277 | try { 278 | Class onwClass = Class.forName(pocessName); 279 | o = (ConnectionProcessor) onwClass.newInstance(); 280 | } catch (ClassNotFoundException e) { 281 | e.printStackTrace(); 282 | } catch (InstantiationException e) { 283 | e.printStackTrace(); 284 | } catch (IllegalAccessException e) { 285 | e.printStackTrace(); 286 | } 287 | return o; 288 | } 289 | 290 | void removeConnection(ConnectionUDP conn){ 291 | synchronized (syn_ds2Table){ 292 | closedTable.add(conn.connectId); 293 | connTable.remove(conn.connectId); 294 | } 295 | } 296 | 297 | //接收连接 298 | public ConnectionUDP getConnection2(InetAddress dstIp,int dstPort,int connectId,int clientId) throws Exception{ 299 | ConnectionUDP conn=connTable.get(connectId); 300 | if(conn==null){ 301 | ClientControl clientControl=clientManager.getClientControl(clientId,dstIp,dstPort); 302 | conn=new ConnectionUDP(this,dstIp,dstPort,2,connectId,clientControl); 303 | synchronized (syn_ds2Table){ 304 | connTable.put(connectId, conn); 305 | } 306 | clientControl.addConnection(conn); 307 | } 308 | return conn; 309 | } 310 | 311 | //发起连接 312 | public ConnectionUDP getConnection(String address,int dstPort,String password) throws Exception{ 313 | InetAddress dstIp=InetAddress.getByName(address); 314 | int connectId=Math.abs(ran.nextInt()); 315 | String key=dstIp.getHostAddress()+":"+dstPort; 316 | int remote_clientId=Math.abs(key.hashCode()); 317 | ClientControl clientControl=clientManager.getClientControl(remote_clientId,dstIp,dstPort); 318 | clientControl.setPassword(password); 319 | ConnectionUDP conn=new ConnectionUDP(this,dstIp,dstPort,1,connectId,clientControl); 320 | synchronized (syn_ds2Table){ 321 | connTable.put(connectId, conn); 322 | } 323 | clientControl.addConnection(conn); 324 | lastClientControl=clientControl; 325 | return conn; 326 | } 327 | 328 | public boolean isUseTcpTun() { 329 | return useTcpTun; 330 | } 331 | 332 | public void setUseTcpTun(boolean useTcpTun) { 333 | this.useTcpTun = useTcpTun; 334 | } 335 | 336 | } 337 | 338 | 339 | -------------------------------------------------------------------------------- /src/net/fs/rudp/SendRecord.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 D1SM.net 2 | 3 | package net.fs.rudp; 4 | 5 | public class SendRecord { 6 | 7 | int sendSize,sendSize_First; 8 | 9 | int sendCount; 10 | 11 | int ackedSize; 12 | 13 | int timeId; 14 | 15 | int speed; 16 | 17 | boolean speedRecored=false; 18 | 19 | int resended; 20 | 21 | SendRecord(){ 22 | 23 | } 24 | 25 | float getDropRate(){ 26 | int droped=getSendSize()-getAckedSize(); 27 | if(droped<0){ 28 | droped=0; 29 | } 30 | float dropRate=0; 31 | if(getSendSize()>0){ 32 | dropRate=(float)droped/getSendSize(); 33 | } 34 | return dropRate; 35 | } 36 | 37 | float getResendRate(){ 38 | float resendRate=0; 39 | if(getSendSize_First()>0){ 40 | resendRate=(float)getResended()/getSendSize_First(); 41 | } 42 | return resendRate; 43 | } 44 | 45 | void addResended(int size){ 46 | resended+=size; 47 | } 48 | 49 | void addSended(int size){ 50 | sendCount++; 51 | sendSize+=size; 52 | } 53 | 54 | void addSended_First(int size){ 55 | sendSize_First+=size; 56 | } 57 | 58 | public int getSendSize() { 59 | return sendSize; 60 | } 61 | 62 | public int getSendCount() { 63 | return sendCount; 64 | } 65 | 66 | public int getAckedSize() { 67 | return ackedSize; 68 | } 69 | 70 | //接收到的数据大小 71 | public void setAckedSize(int ackedSize) { 72 | if(ackedSize>this.ackedSize){ 73 | this.ackedSize = ackedSize; 74 | } 75 | } 76 | 77 | public int getTimeId() { 78 | return timeId; 79 | } 80 | 81 | public void setTimeId(int timeId) { 82 | this.timeId = timeId; 83 | } 84 | 85 | public int getSpeed() { 86 | return speed; 87 | } 88 | 89 | public void setSpeed(int speed) { 90 | this.speed = speed; 91 | speedRecored=true; 92 | } 93 | 94 | public boolean isSpeedRecored(){ 95 | return speedRecored; 96 | } 97 | 98 | public int getResended() { 99 | return resended; 100 | } 101 | 102 | public void setResended(int resended) { 103 | this.resended = resended; 104 | } 105 | 106 | public int getSendSize_First() { 107 | return sendSize_First; 108 | } 109 | 110 | public void setSendSize_First(int sendSize_First) { 111 | this.sendSize_First = sendSize_First; 112 | } 113 | 114 | } 115 | -------------------------------------------------------------------------------- /src/net/fs/rudp/Sender.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 D1SM.net 2 | 3 | package net.fs.rudp; 4 | 5 | import java.io.IOException; 6 | import java.net.DatagramPacket; 7 | import java.net.InetAddress; 8 | import java.util.ArrayList; 9 | import java.util.HashMap; 10 | import java.util.Random; 11 | 12 | import net.fs.rudp.message.AckListMessage; 13 | import net.fs.rudp.message.CloseMessage_Conn; 14 | import net.fs.rudp.message.CloseMessage_Stream; 15 | import net.fs.rudp.message.DataMessage; 16 | 17 | public class Sender { 18 | DataMessage me2=null; 19 | int interval; 20 | 21 | public int sum=0; 22 | int sleepTime=100; 23 | ConnectionUDP conn; 24 | Receiver receiver=null; 25 | boolean bussy=false; 26 | Object bussyOb=new Object(); 27 | boolean isHave=false; 28 | public HashMap sendTable=new HashMap(); 29 | boolean isReady=false; 30 | Object readyOb=new Object(); 31 | Object winOb=new Object(); 32 | public InetAddress dstIp; 33 | public int dstPort; 34 | public int sequence=0; 35 | int sendOffset=-1; 36 | boolean pause=false; 37 | int unAckMin=0; 38 | int unAckMax=-1; 39 | int sendSum=0; 40 | int reSendSum=0; 41 | UDPOutputStream uos; 42 | int sw=0; 43 | 44 | static Random ran=new Random(); 45 | 46 | long lastSendTime=-1; 47 | 48 | boolean closed=false; 49 | 50 | boolean streamClosed=false; 51 | 52 | static int s=0; 53 | 54 | Object syn_send_table=new Object(); 55 | 56 | HashMap unAckTable=new HashMap(); 57 | 58 | Sender(ConnectionUDP conn){ 59 | this.conn=conn; 60 | uos=new UDPOutputStream (conn); 61 | receiver=conn.receiver; 62 | this.dstIp=conn.dstIp; 63 | this.dstPort=conn.dstPort; 64 | } 65 | 66 | void sendData(byte[] data,int offset,int length) throws ConnectException, InterruptedException{ 67 | int packetLength=RUDPConfig.packageSize; 68 | int sum=(length/packetLength); 69 | if(length%packetLength!=0){ 70 | sum+=1; 71 | } 72 | if(sum==0){ 73 | sum=1; 74 | } 75 | int len=packetLength; 76 | if(length<=len){ 77 | sw++; 78 | sendNata(data,0,length); 79 | sw--; 80 | }else{ 81 | for(int i=0;ilength){ 87 | len=length-(sum-1)*packetLength; 88 | } 89 | } 90 | } 91 | } 92 | 93 | void sendNata(byte[] data,int offset,int length) throws ConnectException, InterruptedException{ 94 | 95 | if(!closed){ 96 | if(!streamClosed){ 97 | DataMessage me=new DataMessage(sequence,data,0,(short) length,conn.connectId,conn.route.localclientId); 98 | me.setDstAddress(dstIp); 99 | me.setDstPort(dstPort); 100 | synchronized (syn_send_table) { 101 | sendTable.put(me.getSequence(),me); 102 | } 103 | 104 | synchronized (winOb){ 105 | if(!conn.receiver.checkWin()){ 106 | try { 107 | winOb.wait(); 108 | } catch (InterruptedException e) { 109 | throw e; 110 | } 111 | } 112 | } 113 | 114 | boolean twice=false; 115 | if(RUDPConfig.twice_tcp){ 116 | twice=true; 117 | } 118 | if(RUDPConfig.double_send_start){ 119 | if(me.getSequence()<=5){ 120 | twice=true; 121 | } 122 | } 123 | sendDataMessage(me,false,twice,true); 124 | lastSendTime=System.currentTimeMillis(); 125 | sendOffset++; 126 | s+=me.getData().length; 127 | conn.clientControl.resendMange.addTask(conn, sequence); 128 | sequence++;//必须放最后 129 | }else{ 130 | throw new ConnectException("RDP连接已断开sendData"); 131 | } 132 | }else{ 133 | throw new ConnectException("RDP连接已经关闭"); 134 | } 135 | 136 | } 137 | 138 | public void closeStream_Local(){ 139 | if(!streamClosed){ 140 | streamClosed=true; 141 | conn.receiver.closeStream_Local(); 142 | if(!conn.stopnow){ 143 | sendCloseMessage_Stream(); 144 | } 145 | } 146 | } 147 | 148 | public void closeStream_Remote(){ 149 | if(!streamClosed){ 150 | streamClosed=true; 151 | } 152 | } 153 | 154 | void sendDataMessage(DataMessage me,boolean resend,boolean twice,boolean block){ 155 | synchronized (conn.clientControl.getSynlock()) { 156 | long startTime=System.nanoTime(); 157 | long t1=System.currentTimeMillis(); 158 | conn.clientControl.onSendDataPacket(conn); 159 | 160 | int timeId=conn.clientControl.getCurrentTimeId(); 161 | 162 | me.create(timeId); 163 | 164 | SendRecord record_current=conn.clientControl.getSendRecord(timeId); 165 | if(!resend){ 166 | //第一次发,修改当前时间记录 167 | me.setFirstSendTimeId(timeId); 168 | me.setFirstSendTime(System.currentTimeMillis()); 169 | record_current.addSended_First(me.getData().length); 170 | record_current.addSended(me.getData().length); 171 | }else { 172 | //重发,修改第一次发送时间记录 173 | SendRecord record=conn.clientControl.getSendRecord(me.getFirstSendTimeId()); 174 | record.addResended(me.getData().length); 175 | record_current.addSended(me.getData().length); 176 | } 177 | 178 | try { 179 | sendSum++; 180 | sum++; 181 | unAckMax++; 182 | 183 | long t=System.currentTimeMillis(); 184 | send(me.getDatagramPacket()); 185 | 186 | if(twice){ 187 | send(me.getDatagramPacket());//发两次 188 | } 189 | if(block){ 190 | conn.clientControl.sendSleep(startTime, me.getData().length); 191 | } 192 | TrafficEvent event=new TrafficEvent("",ran.nextLong(),me.getData().length,TrafficEvent.type_uploadTraffic); 193 | Route.fireEvent(event); 194 | } catch (IOException e) { 195 | e.printStackTrace(); 196 | } 197 | } 198 | 199 | } 200 | 201 | void sendAckDelay(int ackSequence){ 202 | conn.route.delayAckManage.addAck(conn, ackSequence); 203 | } 204 | 205 | void sendLastReadDelay(){ 206 | conn.route.delayAckManage.addLastRead(conn); 207 | } 208 | 209 | DataMessage getDataMessage(int sequence){ 210 | return sendTable.get(sequence); 211 | } 212 | 213 | public void reSend(int sequence,int count){ 214 | if(sendTable.containsKey(sequence)){ 215 | DataMessage dm=sendTable.get(sequence); 216 | if(dm!=null){ 217 | sendDataMessage(dm,true,false,true); 218 | } 219 | } 220 | } 221 | 222 | public void destroy(){ 223 | synchronized (syn_send_table) { 224 | sendTable.clear(); 225 | } 226 | } 227 | 228 | //删除后不会重发 229 | void removeSended_Ack(int sequence){ 230 | synchronized (syn_send_table) { 231 | DataMessage dm=sendTable.remove(sequence); 232 | } 233 | } 234 | 235 | void play(){ 236 | synchronized (winOb){ 237 | winOb.notifyAll(); 238 | } 239 | } 240 | 241 | void close(){ 242 | synchronized (winOb){ 243 | closed=true; 244 | winOb.notifyAll(); 245 | } 246 | } 247 | 248 | void sendCloseMessage_Stream(){ 249 | CloseMessage_Stream cm=new CloseMessage_Stream(conn.connectId,conn.route.localclientId,sequence); 250 | cm.setDstAddress(dstIp); 251 | cm.setDstPort(dstPort); 252 | try { 253 | send(cm.getDatagramPacket()); 254 | } catch (IOException e) { 255 | e.printStackTrace(); 256 | } 257 | try { 258 | send(cm.getDatagramPacket()); 259 | } catch (IOException e) { 260 | e.printStackTrace(); 261 | } 262 | } 263 | 264 | void sendCloseMessage_Conn(){ 265 | CloseMessage_Conn cm=new CloseMessage_Conn(conn.connectId,conn.route.localclientId); 266 | cm.setDstAddress(dstIp); 267 | cm.setDstPort(dstPort); 268 | try { 269 | send(cm.getDatagramPacket()); 270 | } catch (IOException e) { 271 | e.printStackTrace(); 272 | } 273 | try { 274 | send(cm.getDatagramPacket()); 275 | } catch (IOException e) { 276 | e.printStackTrace(); 277 | } 278 | } 279 | 280 | void sendALMessage(ArrayList ackList){ 281 | int currentTimeId=conn.receiver.getCurrentTimeId(); 282 | AckListMessage alm=new AckListMessage(conn.connetionId,ackList,conn.receiver.lastRead,conn 283 | .clientControl.sendRecordTable_remote,currentTimeId, 284 | conn.connectId,conn.route.localclientId); 285 | alm.setDstAddress(dstIp); 286 | alm.setDstPort(dstPort); 287 | try { 288 | send(alm.getDatagramPacket()); 289 | } catch (IOException e) { 290 | e.printStackTrace(); 291 | } 292 | } 293 | 294 | void send(DatagramPacket dp) throws IOException { 295 | sendPacket(dp,conn.connectId); 296 | } 297 | 298 | public void sendPacket(DatagramPacket dp,Integer di) throws IOException{ 299 | conn.clientControl.sendPacket(dp); 300 | } 301 | 302 | } 303 | -------------------------------------------------------------------------------- /src/net/fs/rudp/StreamPipe.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 D1SM.net 2 | 3 | package net.fs.rudp; 4 | 5 | import java.io.DataInputStream; 6 | import java.io.DataOutputStream; 7 | import java.io.IOException; 8 | import java.net.Socket; 9 | import java.util.ArrayList; 10 | import java.util.List; 11 | import java.util.Vector; 12 | import java.util.concurrent.Semaphore; 13 | 14 | 15 | public class StreamPipe { 16 | 17 | DataInputStream is; 18 | 19 | DataOutputStream os; 20 | 21 | List listenerList; 22 | 23 | boolean closed=false; 24 | 25 | int maxLen=2000; 26 | 27 | long lastResetTime; 28 | 29 | int maxSpeed=100*1024*1024; 30 | 31 | int port=0; 32 | 33 | int limiteConnectTime; 34 | 35 | String userId=""; 36 | 37 | byte[] preReadData; 38 | 39 | int preReadDataLength; 40 | 41 | Socket socketA,socketB; 42 | 43 | boolean writing=false; 44 | 45 | int BUF_SIZE; 46 | 47 | ArrayList dataList=new ArrayList(); 48 | 49 | Semaphore semp_have_data=new Semaphore(0); 50 | 51 | int cachedSize=0; 52 | 53 | int supserSocketId=-1; 54 | 55 | static int type_request=1; 56 | 57 | static int type_respone=2; 58 | 59 | int type=0; 60 | 61 | ConnInfo connInfo; 62 | 63 | public StreamPipe(ConnInfo connInfo,final DataInputStream is,final DataOutputStream os,final int BUF_SIZE,final int maxSpeed){ 64 | this(connInfo,is, os, BUF_SIZE, maxSpeed, null, 0); 65 | } 66 | 67 | public StreamPipe(ConnInfo ci,final DataInputStream is,final DataOutputStream os,int BUF_SIZE1,final int maxSpeed,final byte[] preReadData,final int preReadDataLength){ 68 | connInfo=ci; 69 | listenerList=new Vector(); 70 | this.maxSpeed=maxSpeed; 71 | this.preReadData=preReadData; 72 | BUF_SIZE=BUF_SIZE1; 73 | if(maxSpeed<=50*1024){ 74 | //BUF_SIZE=100; 75 | } 76 | Runnable thread=new Runnable(){ 77 | 78 | int count=0; 79 | public void run(){ 80 | byte[] data=new byte[BUF_SIZE]; 81 | int len=0; 82 | try { 83 | if(preReadData!=null){ 84 | // String string=new String(preReadData,0,preReadDataLength); 85 | // Log.println("写预读111 "+string); 86 | try { 87 | os.write(preReadData,0,preReadDataLength); 88 | } catch (IOException e) { 89 | e.printStackTrace(); 90 | return; 91 | } 92 | // Log.println("写预读222 "); 93 | } 94 | //Log.println("pipe发送 111 "+supserSocketId+" "); 95 | boolean parsed=false; 96 | try { 97 | while((len=is.read(data))>0){ 98 | try { 99 | os.write(data,0,len); 100 | } catch (IOException e) { 101 | //e.printStackTrace(); 102 | break; 103 | } 104 | 105 | } 106 | } catch (IOException e) { 107 | //e.printStackTrace(); 108 | } 109 | }finally{ 110 | close(); 111 | } 112 | } 113 | }; 114 | Route.es.execute(thread); 115 | } 116 | 117 | void close(){ 118 | if(!closed){ 119 | closed=true; 120 | try { 121 | Thread.sleep(500); 122 | } catch (InterruptedException e1) { 123 | //e1.printStackTrace(); 124 | } 125 | 126 | if(socketA!=null){ 127 | Route.es.execute(new Runnable() { 128 | 129 | public void run() { 130 | try { 131 | socketA.close(); 132 | } catch (IOException e) { 133 | //e.printStackTrace(); 134 | } 135 | } 136 | 137 | }); 138 | 139 | } 140 | 141 | 142 | if(socketB!=null){ 143 | 144 | Route.es.execute(new Runnable() { 145 | 146 | public void run() { 147 | try { 148 | socketB.close(); 149 | } catch (IOException e) { 150 | //e.printStackTrace(); 151 | } 152 | } 153 | }); 154 | 155 | } 156 | fireClose(); 157 | } 158 | } 159 | 160 | class HttpHost{ 161 | String address; 162 | int port=80; 163 | public String getAddress() { 164 | return address; 165 | } 166 | public void setAddress(String address) { 167 | this.address = address; 168 | } 169 | public int getPort() { 170 | return port; 171 | } 172 | public void setPort(int port) { 173 | this.port = port; 174 | } 175 | 176 | } 177 | 178 | HttpHost readHost(String data){ 179 | HttpHost hh=new HttpHost(); 180 | String host=null; 181 | data=data.replaceAll("\r", ""); 182 | data=data.replaceAll(" ", ""); 183 | String[] ls=data.split("\n"); 184 | for(String l:ls){ 185 | if(l.startsWith("Host:")){ 186 | String s1=l.substring(5); 187 | int index2=s1.indexOf(":"); 188 | if(index2>-1){ 189 | int port=Integer.parseInt(s1.substring(index2+1)); 190 | hh.setPort(port); 191 | s1=s1.substring(0,index2); 192 | } 193 | host=s1; 194 | hh.setAddress(host); 195 | ////#MLog.println("ddd "+s1); 196 | } 197 | } 198 | return hh; 199 | } 200 | 201 | public void addListener(PipeListener listener){ 202 | listenerList.add(listener); 203 | } 204 | 205 | void fireClose(){ 206 | //Log.println("StreamPipe关闭 fireClose111 "+listenerList.size()); 207 | for(PipeListener listener:listenerList){ 208 | //Log.println("StreamPipe关闭 fireClose222"); 209 | listener.pipeClose(); 210 | } 211 | } 212 | 213 | public int getPort() { 214 | return port; 215 | } 216 | 217 | public void setPort(int port) { 218 | this.port = port; 219 | } 220 | 221 | public int getLimiteConnectTime() { 222 | return limiteConnectTime; 223 | } 224 | 225 | public void setLimiteConnectTime(int limiteConnectTime) { 226 | this.limiteConnectTime = limiteConnectTime; 227 | } 228 | 229 | public String getUserId() { 230 | return userId; 231 | } 232 | 233 | public void setUserId(String userId) { 234 | this.userId = userId; 235 | } 236 | 237 | public Socket getSocketA() { 238 | return socketA; 239 | } 240 | 241 | public void setSocketA(Socket socketA) { 242 | this.socketA = socketA; 243 | } 244 | 245 | public Socket getSocketB() { 246 | return socketB; 247 | } 248 | 249 | public void setSocketB(Socket socketB) { 250 | this.socketB = socketB; 251 | } 252 | 253 | public int getSupserSocketId() { 254 | return supserSocketId; 255 | } 256 | 257 | public void setSupserSocketId(int supserSocketId) { 258 | this.supserSocketId = supserSocketId; 259 | } 260 | 261 | public int getType() { 262 | return type; 263 | } 264 | 265 | public void setType(int type) { 266 | this.type = type; 267 | } 268 | 269 | public ConnInfo getConnInfo() { 270 | return connInfo; 271 | } 272 | 273 | public void setConnInfo(ConnInfo connInfo) { 274 | this.connInfo = connInfo; 275 | } 276 | 277 | } 278 | -------------------------------------------------------------------------------- /src/net/fs/rudp/TrafficEvent.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 D1SM.net 2 | 3 | package net.fs.rudp; 4 | 5 | public class TrafficEvent { 6 | 7 | long eventId; 8 | 9 | int traffic; 10 | 11 | public static int type_downloadTraffic=10; 12 | 13 | public static int type_uploadTraffic=11; 14 | 15 | int type=type_downloadTraffic; 16 | 17 | String userId; 18 | 19 | TrafficEvent(long eventId,int traffic,int type){ 20 | this(null,eventId,traffic,type); 21 | } 22 | 23 | public TrafficEvent(String userId,long eventId,int traffic,int type){ 24 | this.userId=userId; 25 | this.eventId=eventId; 26 | this.traffic=traffic; 27 | this.type=type; 28 | } 29 | 30 | public String getUserId() { 31 | return userId; 32 | } 33 | 34 | public void setUserId(String userId) { 35 | this.userId = userId; 36 | } 37 | 38 | public int getType() { 39 | return type; 40 | } 41 | 42 | public long getEventId() { 43 | return eventId; 44 | } 45 | 46 | public void setEventId(long eventId) { 47 | this.eventId = eventId; 48 | } 49 | 50 | public int getTraffic() { 51 | return traffic; 52 | } 53 | 54 | public void setTraffic(int traffic) { 55 | this.traffic = traffic; 56 | } 57 | 58 | 59 | 60 | } 61 | -------------------------------------------------------------------------------- /src/net/fs/rudp/Trafficlistener.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 D1SM.net 2 | 3 | package net.fs.rudp; 4 | 5 | public interface Trafficlistener { 6 | 7 | public void trafficDownload(TrafficEvent event); 8 | 9 | 10 | public void trafficUpload(TrafficEvent event); 11 | 12 | } 13 | -------------------------------------------------------------------------------- /src/net/fs/rudp/UDPInputStream.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 D1SM.net 2 | 3 | package net.fs.rudp; 4 | 5 | import java.net.DatagramSocket; 6 | import java.net.InetAddress; 7 | 8 | public class UDPInputStream { 9 | 10 | DatagramSocket ds; 11 | InetAddress dstIp; 12 | int dstPort; 13 | Receiver receiver; 14 | 15 | boolean streamClosed=false; 16 | 17 | ConnectionUDP conn; 18 | 19 | UDPInputStream(ConnectionUDP conn){ 20 | this.conn=conn; 21 | receiver=conn.receiver; 22 | } 23 | 24 | public int read(byte[] b, int off, int len) throws ConnectException, InterruptedException { 25 | byte[] b2=null; 26 | b2 = read2(); 27 | if(len ackList; 18 | byte[] dpData=null; 19 | int lastRead; 20 | 21 | int r1,r2,r3,s1,s2,s3; 22 | 23 | @SuppressWarnings("unchecked") 24 | public AckListMessage(long connId,ArrayList ackList,int lastRead, 25 | HashMap sendRecordTable,int timeId, 26 | int connectId,int clientId){ 27 | this.clientId=clientId; 28 | this.connectId=connectId; 29 | this.ackList=ackList; 30 | this.lastRead=lastRead; 31 | int len1=4+4+10+4*ackList.size(); 32 | dpData=new byte[len1+24+9]; 33 | sType=MessageType.sType_AckListMessage; 34 | ByteShortConvert.toByteArray(ver, dpData, 0); //add: ver 35 | ByteShortConvert.toByteArray(sType, dpData, 2); //add: service type 36 | ByteIntConvert.toByteArray(connectId, dpData, 4); //add: sequence 37 | ByteIntConvert.toByteArray(clientId, dpData, 8); //add: sequence 38 | 39 | ByteIntConvert.toByteArray(lastRead, dpData, 4+8); 40 | //dpData[8]=(byte) ackList.size(); 41 | ByteShortConvert.toByteArray((short) ackList.size(), dpData, 8+8); //add: service type 42 | for(int i=0;i(); 95 | int t=0; 96 | for(int i=0;i 0) { 225 | // MLog.println("删除行 "+row); 226 | String cmd = "iptables -D INPUT " + row; 227 | runCommand(cmd); 228 | } else { 229 | break; 230 | } 231 | } 232 | } 233 | 234 | void setFireWall_linux_tcp() { 235 | cleanTcpTunRule(); 236 | String cmd2 = "iptables -I INPUT -p tcp --dport " + routePort + " -j DROP" 237 | + " -m comment --comment tcptun_fs_server "; 238 | runCommand(cmd2); 239 | 240 | } 241 | 242 | void cleanTcpTunRule() { 243 | while (true) { 244 | int row = getRow("tcptun_fs_server"); 245 | if (row > 0) { 246 | // MLog.println("删除行 "+row); 247 | String cmd = "iptables -D INPUT " + row; 248 | runCommand(cmd); 249 | } else { 250 | break; 251 | } 252 | } 253 | } 254 | 255 | int getRow(String name) { 256 | int row_delect = -1; 257 | String cme_list_rule = "iptables -L -n --line-number"; 258 | // String [] cmd={"netsh","advfirewall set allprofiles state on"}; 259 | Thread errorReadThread = null; 260 | try { 261 | final Process p = Runtime.getRuntime().exec(cme_list_rule, null); 262 | 263 | errorReadThread = new Thread() { 264 | public void run() { 265 | InputStream is = p.getErrorStream(); 266 | BufferedReader localBufferedReader = new BufferedReader(new InputStreamReader(is)); 267 | while (true) { 268 | String line; 269 | try { 270 | line = localBufferedReader.readLine(); 271 | if (line == null) { 272 | break; 273 | } else { 274 | // System.out.println("erroraaa "+line); 275 | } 276 | } catch (IOException e) { 277 | e.printStackTrace(); 278 | // error(); 279 | break; 280 | } 281 | } 282 | } 283 | }; 284 | errorReadThread.start(); 285 | 286 | InputStream is = p.getInputStream(); 287 | BufferedReader localBufferedReader = new BufferedReader(new InputStreamReader(is)); 288 | while (true) { 289 | String line; 290 | try { 291 | line = localBufferedReader.readLine(); 292 | // System.out.println("standaaa "+line); 293 | if (line == null) { 294 | break; 295 | } else { 296 | if (line.contains(name)) { 297 | int index = line.indexOf(" "); 298 | if (index > 0) { 299 | String n = line.substring(0, index); 300 | try { 301 | if (row_delect < 0) { 302 | // System.out.println("standaaabbb 303 | // "+line); 304 | row_delect = Integer.parseInt(n); 305 | } 306 | } catch (Exception e) { 307 | 308 | } 309 | } 310 | } 311 | ; 312 | } 313 | } catch (IOException e) { 314 | e.printStackTrace(); 315 | break; 316 | } 317 | } 318 | 319 | errorReadThread.join(); 320 | p.waitFor(); 321 | } catch (Exception e) { 322 | e.printStackTrace(); 323 | // error(); 324 | } 325 | return row_delect; 326 | } 327 | 328 | void runCommand(String command) { 329 | Thread standReadThread = null; 330 | Thread errorReadThread = null; 331 | try { 332 | final Process p = Runtime.getRuntime().exec(command, null); 333 | standReadThread = new Thread() { 334 | public void run() { 335 | InputStream is = p.getInputStream(); 336 | BufferedReader localBufferedReader = new BufferedReader(new InputStreamReader(is)); 337 | while (true) { 338 | String line; 339 | try { 340 | line = localBufferedReader.readLine(); 341 | // System.out.println("stand "+line); 342 | if (line == null) { 343 | break; 344 | } 345 | } catch (IOException e) { 346 | e.printStackTrace(); 347 | break; 348 | } 349 | } 350 | } 351 | }; 352 | standReadThread.start(); 353 | 354 | errorReadThread = new Thread() { 355 | public void run() { 356 | InputStream is = p.getErrorStream(); 357 | BufferedReader localBufferedReader = new BufferedReader(new InputStreamReader(is)); 358 | while (true) { 359 | String line; 360 | try { 361 | line = localBufferedReader.readLine(); 362 | if (line == null) { 363 | break; 364 | } else { 365 | // System.out.println("error "+line); 366 | } 367 | } catch (IOException e) { 368 | e.printStackTrace(); 369 | // error(); 370 | break; 371 | } 372 | } 373 | } 374 | }; 375 | errorReadThread.start(); 376 | standReadThread.join(); 377 | errorReadThread.join(); 378 | p.waitFor(); 379 | } catch (Exception e) { 380 | e.printStackTrace(); 381 | // error(); 382 | } 383 | } 384 | 385 | String readFileData(String path) { 386 | String content = null; 387 | FileInputStream fis = null; 388 | DataInputStream dis = null; 389 | try { 390 | File file = new File(path); 391 | fis = new FileInputStream(file); 392 | dis = new DataInputStream(fis); 393 | byte[] data = new byte[(int) file.length()]; 394 | dis.readFully(data); 395 | content = new String(data, "utf-8"); 396 | } catch (Exception e) { 397 | // e.printStackTrace(); 398 | } finally { 399 | if (dis != null) { 400 | try { 401 | dis.close(); 402 | } catch (IOException e) { 403 | e.printStackTrace(); 404 | } 405 | } 406 | } 407 | return content; 408 | } 409 | 410 | public int getRoutePort() { 411 | return routePort; 412 | } 413 | 414 | } 415 | -------------------------------------------------------------------------------- /src/net/fs/server/MapTunnelProcessor.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 D1SM.net 2 | 3 | package net.fs.server; 4 | 5 | import java.io.IOException; 6 | import java.io.InputStream; 7 | import java.io.OutputStream; 8 | import java.net.Socket; 9 | 10 | import net.fs.client.Pipe; 11 | import net.fs.rudp.ConnectionProcessor; 12 | import net.fs.rudp.ConnectionUDP; 13 | import net.fs.rudp.Constant; 14 | import net.fs.rudp.Route; 15 | import net.fs.rudp.UDPInputStream; 16 | import net.fs.rudp.UDPOutputStream; 17 | import net.fs.utils.MLog; 18 | 19 | import com.alibaba.fastjson.JSONObject; 20 | 21 | 22 | public class MapTunnelProcessor implements ConnectionProcessor{ 23 | 24 | Socket dstSocket=null; 25 | 26 | boolean closed=false; 27 | 28 | MapTunnelProcessor pc; 29 | 30 | ConnectionUDP conn; 31 | 32 | 33 | UDPInputStream tis; 34 | 35 | UDPOutputStream tos; 36 | 37 | InputStream sis; 38 | 39 | OutputStream sos; 40 | 41 | public void process(final ConnectionUDP conn){ 42 | this.conn=conn; 43 | pc=this; 44 | Route.es.execute(new Runnable(){ 45 | public void run(){ 46 | process(); 47 | } 48 | }); 49 | } 50 | 51 | 52 | void process(){ 53 | 54 | tis=conn.uis; 55 | tos=conn.uos; 56 | 57 | byte[] headData; 58 | try { 59 | headData = tis.read2(); 60 | String hs=new String(headData,"utf-8"); 61 | JSONObject requestJSon=JSONObject.parseObject(hs); 62 | int dstPort=requestJSon.getIntValue("dst_port"); 63 | String message=""; 64 | JSONObject responeJSon=new JSONObject(); 65 | int code=Constant.code_failed; 66 | code=Constant.code_success; 67 | responeJSon.put("code", code); 68 | responeJSon.put("message", message); 69 | byte[] responeData=responeJSon.toJSONString().getBytes("utf-8"); 70 | tos.write(responeData, 0, responeData.length); 71 | if(code!=Constant.code_success){ 72 | close(); 73 | return; 74 | } 75 | dstSocket = new Socket("127.0.0.1", dstPort); 76 | dstSocket.setTcpNoDelay(true); 77 | sis=dstSocket.getInputStream(); 78 | sos=dstSocket.getOutputStream(); 79 | 80 | final Pipe p1=new Pipe(); 81 | final Pipe p2=new Pipe(); 82 | 83 | Route.es.execute(new Runnable() { 84 | 85 | public void run() { 86 | try { 87 | p1.pipe(sis, tos,300*1024,p2); 88 | } catch (IOException e) { 89 | //e.printStackTrace(); 90 | } catch (Exception e) { 91 | //e.printStackTrace(); 92 | }finally{ 93 | close(); 94 | } 95 | } 96 | 97 | }); 98 | Route.es.execute(new Runnable() { 99 | 100 | public void run() { 101 | try { 102 | p2.pipe(tis,sos,1024*1024*1024,conn); 103 | } catch (IOException e) { 104 | //e.printStackTrace(); 105 | } catch (Exception e) { 106 | //e.printStackTrace(); 107 | }finally{ 108 | close(); 109 | } 110 | } 111 | }); 112 | 113 | 114 | } catch (Exception e2) { 115 | //e2.printStackTrace(); 116 | close(); 117 | } 118 | 119 | 120 | 121 | } 122 | 123 | void close(){ 124 | if(!closed){ 125 | closed=true; 126 | if(sis!=null){ 127 | try { 128 | sis.close(); 129 | } catch (IOException e) { 130 | //e.printStackTrace(); 131 | } 132 | } 133 | if(sos!=null){ 134 | try { 135 | sos.close(); 136 | } catch (IOException e) { 137 | //e.printStackTrace(); 138 | } 139 | } 140 | if(tos!=null){ 141 | tos.closeStream_Local(); 142 | } 143 | if(tis!=null){ 144 | tis.closeStream_Local(); 145 | } 146 | if(conn!=null){ 147 | conn.close_local(); 148 | } 149 | if(dstSocket!=null){ 150 | try { 151 | dstSocket.close(); 152 | } catch (IOException e) { 153 | //e.printStackTrace(); 154 | } 155 | } 156 | } 157 | } 158 | 159 | } 160 | -------------------------------------------------------------------------------- /src/net/fs/utils/ByteIntConvert.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 D1SM.net 2 | 3 | package net.fs.utils; 4 | 5 | 6 | public class ByteIntConvert { 7 | 8 | public static int toInt(byte[] b,int offset) { 9 | return b[offset + 3] & 0xff | (b[offset + 2] & 0xff) << 8 10 | | (b[offset + 1] & 0xff) << 16 | (b[offset] & 0xff) << 24; 11 | } 12 | 13 | public static void toByteArray(int n,byte[] buf,int offset) { 14 | buf[offset] = (byte) (n >> 24); 15 | buf[offset + 1] = (byte) (n >> 16); 16 | buf[offset + 2] = (byte) (n >> 8); 17 | buf[offset + 3] = (byte) n; 18 | } 19 | 20 | } 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /src/net/fs/utils/ByteShortConvert.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 D1SM.net 2 | 3 | package net.fs.utils; 4 | 5 | public final class ByteShortConvert { 6 | 7 | public static byte[] toByteArray(short i,byte[] b,int offset) { 8 | b[offset] = (byte) (i >> 8); 9 | b[offset + 1] = (byte) (i >> 0); 10 | return b; 11 | } 12 | 13 | 14 | 15 | public static short toShort(byte[] b,int offset) { 16 | return (short) (((b[offset] << 8) | b[offset + 1] & 0xff)); 17 | } 18 | 19 | //无符号 20 | public static byte[] toByteArrayUnsigned(int s,byte[] b,int offset) { 21 | b[offset] = (byte) (s >> 8); 22 | b[offset+1] = (byte) (s >> 0); 23 | return b; 24 | } 25 | 26 | //无符号 27 | public static int toShortUnsigned(byte[] b,int offset) { 28 | int i = 0; 29 | i |= b[offset+0] & 0xFF; 30 | i <<= 8; 31 | i |= b[offset+1] & 0xFF; 32 | return i; 33 | } 34 | 35 | 36 | } -------------------------------------------------------------------------------- /src/net/fs/utils/MLog.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 D1SM.net 2 | 3 | package net.fs.utils; 4 | 5 | 6 | public class MLog { 7 | 8 | public static void info(Object str){ 9 | System.out.println(str); 10 | } 11 | 12 | // public static void println(Object str){ 13 | // System.out.println(str); 14 | // } 15 | 16 | public static void println(String str){ 17 | System.out.println(str); 18 | } 19 | 20 | // public static void println(){ 21 | // System.out.println(); 22 | // } 23 | // 24 | // public static void print(String str){ 25 | // System.out.print(str); 26 | // } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /src/net/fs/utils/MessageCheck.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 D1SM.net 2 | 3 | package net.fs.utils; 4 | 5 | import java.net.DatagramPacket; 6 | 7 | 8 | 9 | public class MessageCheck{ 10 | public static int checkVer(DatagramPacket dp){ 11 | int ver=ByteShortConvert.toShort(dp.getData(), 0); 12 | return ver; 13 | } 14 | public static int checkSType(DatagramPacket dp){ 15 | int sType=ByteShortConvert.toShort(dp.getData(), 2); 16 | return sType; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/net/fs/utils/NetStatus.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 D1SM.net 2 | 3 | package net.fs.utils; 4 | 5 | import java.util.Vector; 6 | 7 | 8 | public class NetStatus { 9 | 10 | public long uploadSum; 11 | public long downloadSum; 12 | 13 | Thread mainThread; 14 | 15 | int averageTime; 16 | 17 | Vector speedList; 18 | SpeedUnit currentUnit; 19 | 20 | public int upSpeed=0; 21 | public int downSpeed=0; 22 | 23 | public NetStatus(){ 24 | this(2); 25 | } 26 | 27 | public NetStatus(int averageTime){ 28 | this.averageTime=averageTime; 29 | speedList=new Vector(); 30 | for(int i=0;i1000){ 43 | ////#MLog.println("yyyyyyyyyyy "); 44 | lastTime=System.currentTimeMillis(); 45 | calcuSpeed(); 46 | } 47 | try { 48 | Thread.sleep(100); 49 | } catch (InterruptedException e) { 50 | // e.printStackTrace(); 51 | break; 52 | } 53 | } 54 | } 55 | }; 56 | mainThread.start(); 57 | } 58 | 59 | public void stop(){ 60 | mainThread.interrupt(); 61 | } 62 | 63 | 64 | public int getUpSpeed() { 65 | return upSpeed; 66 | } 67 | 68 | public void setUpSpeed(int upSpeed) { 69 | this.upSpeed = upSpeed; 70 | } 71 | 72 | public int getDownSpeed() { 73 | return downSpeed; 74 | } 75 | 76 | public void setDownSpeed(int downSpeed) { 77 | this.downSpeed = downSpeed; 78 | } 79 | 80 | 81 | void calcuSpeed(){ 82 | int ds = 0,us=0; 83 | for(SpeedUnit unit:speedList){ 84 | ds+=unit.downSum; 85 | us+=unit.upSum; 86 | } 87 | upSpeed=(int) ((float)us/speedList.size()); 88 | downSpeed=(int)(float)ds/speedList.size(); 89 | 90 | speedList.remove(0); 91 | SpeedUnit unit=new SpeedUnit(); 92 | currentUnit=unit; 93 | speedList.add(unit); 94 | } 95 | 96 | public void addDownload(int sum){ 97 | downloadSum+=sum; 98 | currentUnit.addDown(sum); 99 | } 100 | 101 | public void addUpload(int sum){ 102 | uploadSum+=sum; 103 | currentUnit.addUp(sum); 104 | } 105 | 106 | public void sendAvail(){ 107 | 108 | } 109 | 110 | public void receiveAvail(){ 111 | 112 | } 113 | 114 | public void setUpLimite(int speed){ 115 | 116 | } 117 | 118 | public void setDownLimite(int speed){ 119 | 120 | } 121 | } 122 | 123 | 124 | class SpeedUnit{ 125 | int downSum; 126 | int upSum; 127 | SpeedUnit(){ 128 | 129 | } 130 | 131 | void addUp(int n){ 132 | upSum+=n; 133 | } 134 | 135 | void addDown(int n){ 136 | downSum+=n; 137 | } 138 | } 139 | 140 | -------------------------------------------------------------------------------- /src/net/fs/utils/Tools.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 D1SM.net 2 | 3 | package net.fs.utils; 4 | 5 | import java.net.HttpURLConnection; 6 | import java.net.URL; 7 | 8 | import javax.net.ssl.HostnameVerifier; 9 | import javax.net.ssl.HttpsURLConnection; 10 | import javax.net.ssl.SSLSession; 11 | 12 | 13 | public class Tools { 14 | 15 | public static HttpURLConnection getConnection(String urlString) throws Exception{ 16 | URL url = new URL(urlString); 17 | HttpURLConnection conn = null; 18 | if(urlString.startsWith("http://")){ 19 | conn = (HttpURLConnection) url.openConnection(); 20 | }else if(urlString.startsWith("https://")){ 21 | HttpsURLConnection conns=(HttpsURLConnection)url.openConnection(); 22 | conns.setHostnameVerifier(new HostnameVerifier() { 23 | public boolean verify(String hostname, SSLSession session) { 24 | return true; 25 | } 26 | }); 27 | conn=conns; 28 | } 29 | if(conn!=null){ 30 | conn.setConnectTimeout(10*1000); 31 | conn.setReadTimeout(10*1000); 32 | conn.setRequestMethod("POST"); 33 | conn.setDoInput(true); 34 | conn.setDoOutput(true); 35 | conn.setUseCaches(false); 36 | } 37 | return conn; 38 | } 39 | 40 | public static String getMD5(String str) { 41 | byte[] source=str.getBytes(); 42 | return getMD5(source); 43 | } 44 | 45 | public static String getMD5(byte[] source) { 46 | String s = null; 47 | char hexDigits[] = { 48 | '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; 49 | try 50 | { 51 | java.security.MessageDigest md = java.security.MessageDigest.getInstance( "MD5" ); 52 | md.update( source ); 53 | byte tmp[] = md.digest(); 54 | char str[] = new char[16 * 2]; 55 | int k = 0; 56 | for (int i = 0; i < 16; i++) { 57 | byte byte0 = tmp[i]; 58 | str[k++] = hexDigits[byte0 >>> 4 & 0xf]; 59 | str[k++] = hexDigits[byte0 & 0xf]; 60 | } 61 | s = new String(str); 62 | 63 | }catch( Exception e ) 64 | { 65 | e.printStackTrace(); 66 | } 67 | return s; 68 | } 69 | 70 | 71 | public static String getSizeStringKB(long size){ 72 | int gb=(int) (size/(1024*1024*1024)); 73 | int gbl=(int) (size%(1024*1024*1024)); 74 | int mb=gbl/(1024*1024); 75 | int mbl=gbl%(1024*1024); 76 | int kb=mbl/(1024); 77 | String ls=""; 78 | if(gb>0){ 79 | ls+=gb+","; 80 | } 81 | if(mb>0){ 82 | String mbs=""; 83 | if(gb>0){ 84 | if(mb<10){ 85 | mbs+="00"; 86 | }else if(mb<100){ 87 | mbs+="0"; 88 | } 89 | } 90 | mbs+=mb; 91 | ls+=mbs+","; 92 | }else{ 93 | if(gb>0){ 94 | ls+="000,"; 95 | } 96 | } 97 | 98 | if(kb>0){ 99 | String kbs=""; 100 | if(gb>0|mb>0){ 101 | if(kb<10){ 102 | kbs+="00"; 103 | }else if(kb<100){ 104 | kbs+="0"; 105 | } 106 | } 107 | kbs+=kb; 108 | ls+=kbs+" KB"; 109 | }else{ 110 | if(mb>0|gb>0){ 111 | ls+="000 KB"; 112 | } 113 | } 114 | if(size==0){ 115 | ls+=0+" KB"; 116 | } 117 | if(size<1024){ 118 | //ls=size+" b"; 119 | ls=0+" KB"; 120 | } 121 | return ls; 122 | } 123 | 124 | } 125 | --------------------------------------------------------------------------------