mnet 0.1.0 → 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/mnet/version.rb +1 -1
- data/lib/mnet.rb +29 -13
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 426aa10a38e121d68b9a895f6ca52c30b8f074b1dfc355e457602198a35e94f9
|
|
4
|
+
data.tar.gz: 4847c3712519daa9bc2f97c57c662436966aa60dd44c23016d4676aad2356742
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 9cd167304267f4665d3df1429d2214453926f4981ff791649e2eaf5cf0a75185e1290df774cea5b65508ebf7d1ae5028532cbe963e0c8ad9ff60ce3d44d4257e
|
|
7
|
+
data.tar.gz: 738fbf86f844faf9eef17b0fbc55de691fa6734bbd399188cf692dbb3c6f0d811354e653b4041272f0be4a07501c5230eb0912ead10eed99098d29177945a029
|
data/lib/mnet/version.rb
CHANGED
data/lib/mnet.rb
CHANGED
|
@@ -26,8 +26,8 @@ require "mnet/version"
|
|
|
26
26
|
require "kcp"
|
|
27
27
|
|
|
28
28
|
module Mnet
|
|
29
|
-
MAGIC = "
|
|
30
|
-
MAGIC_LEN =
|
|
29
|
+
MAGIC = "\x12\xE9\x97".b
|
|
30
|
+
MAGIC_LEN = 3
|
|
31
31
|
SESSION_ID_LEN = 16
|
|
32
32
|
|
|
33
33
|
# Conservative MTU for mobile networks / VPN tunnels (mosh uses 1280).
|
|
@@ -43,6 +43,9 @@ module Mnet
|
|
|
43
43
|
# delayed packets (mosh: MAX_OLD_SOCKET_AGE = 60000ms).
|
|
44
44
|
MAX_OLD_SOCKET_AGE = 60.0
|
|
45
45
|
|
|
46
|
+
# 非阻塞发送标志:POSIX 有 MSG_DONTWAIT,Windows 没有(用 nonblock 模式兜底)。
|
|
47
|
+
MSG_DONTWAIT = Socket.const_defined?(:MSG_DONTWAIT) ? Socket::MSG_DONTWAIT : 0
|
|
48
|
+
|
|
46
49
|
# Message types (mirrors the enum-message-types pattern from tmux-protocol.h).
|
|
47
50
|
TYPE_SYN = 0x01
|
|
48
51
|
TYPE_SYNACK = 0x02
|
|
@@ -72,12 +75,12 @@ module Mnet
|
|
|
72
75
|
|
|
73
76
|
def pack(session_id, seq, ack, type, flags, window, payload = "".b)
|
|
74
77
|
[MAGIC, session_id, seq, ack, type, flags, window, payload]
|
|
75
|
-
.pack("
|
|
78
|
+
.pack("a3a16Q>Q>CCNa*")
|
|
76
79
|
end
|
|
77
80
|
|
|
78
81
|
def unpack(data)
|
|
79
82
|
return nil if data.bytesize < HEADER_LEN
|
|
80
|
-
magic, sid, seq, ack, type, flags, window = data.unpack("
|
|
83
|
+
magic, sid, seq, ack, type, flags, window = data.unpack("a3a16Q>Q>CCN")
|
|
81
84
|
return nil unless magic == MAGIC
|
|
82
85
|
Packet.new(sid, seq, ack, type, flags, window,
|
|
83
86
|
data.byteslice(HEADER_LEN, data.bytesize - HEADER_LEN) || "".b)
|
|
@@ -110,7 +113,7 @@ module Mnet
|
|
|
110
113
|
# socketpair is unavailable (Windows).
|
|
111
114
|
def socket_pair
|
|
112
115
|
Socket.pair(:UNIX, :STREAM, 0)
|
|
113
|
-
rescue
|
|
116
|
+
rescue SystemCallError, NotImplementedError
|
|
114
117
|
server = TCPServer.new("127.0.0.1", 0)
|
|
115
118
|
port = server.addr[1]
|
|
116
119
|
client = TCPSocket.new("127.0.0.1", port)
|
|
@@ -137,6 +140,15 @@ module Mnet
|
|
|
137
140
|
def sync=(_value)
|
|
138
141
|
end
|
|
139
142
|
|
|
143
|
+
# 返回对端真实地址(Addrinfo)。Session/KcpSession 没有内核 socket,远端地址
|
|
144
|
+
# 由 @peer_addr 跟踪(含切网迁移后的新地址),供 LSocket#io.remote_address 等使用。
|
|
145
|
+
def remote_address
|
|
146
|
+
return nil unless @peer_addr
|
|
147
|
+
Addrinfo.udp(@peer_addr[0], @peer_addr[1])
|
|
148
|
+
rescue SocketError
|
|
149
|
+
nil
|
|
150
|
+
end
|
|
151
|
+
|
|
140
152
|
# Hook overridden by KcpSession to pull decoded bytes out of the engine.
|
|
141
153
|
def pump_recv
|
|
142
154
|
end
|
|
@@ -271,6 +283,11 @@ module Mnet
|
|
|
271
283
|
end
|
|
272
284
|
end
|
|
273
285
|
|
|
286
|
+
# 桥接 socketpair 本身拿不到远端地址,把 remote_address 委托回 session,
|
|
287
|
+
# 这样 SSLServer#io.remote_address 等仍能取到对端真实 ip:port。
|
|
288
|
+
session = self
|
|
289
|
+
app.define_singleton_method(:remote_address) { session.remote_address }
|
|
290
|
+
|
|
274
291
|
@bridge_io = app
|
|
275
292
|
end
|
|
276
293
|
end
|
|
@@ -971,11 +988,9 @@ module Mnet
|
|
|
971
988
|
def send_raw(data, ip, port)
|
|
972
989
|
sock = @socks.last[0]
|
|
973
990
|
@send_mutex.synchronize do
|
|
974
|
-
sock.send(data,
|
|
991
|
+
sock.send(data, Mnet::MSG_DONTWAIT, ip, port)
|
|
975
992
|
true
|
|
976
|
-
rescue IO::
|
|
977
|
-
false
|
|
978
|
-
rescue IOError, Errno::EBADF, Errno::ECONNRESET, Errno::ECONNREFUSED
|
|
993
|
+
rescue IO::WaitWritable, IO::WaitReadable, SystemCallError, IOError
|
|
979
994
|
false
|
|
980
995
|
end
|
|
981
996
|
end
|
|
@@ -999,6 +1014,9 @@ module Mnet
|
|
|
999
1014
|
|
|
1000
1015
|
def configure_socket(sock)
|
|
1001
1016
|
sock.setsockopt(Socket::SOL_SOCKET, Socket::SO_REUSEADDR, true)
|
|
1017
|
+
# Windows 没有 MSG_DONTWAIT,用 nonblock 模式让 send 在缓冲满时返回错误
|
|
1018
|
+
# 而非阻塞(避免发送端死锁)。
|
|
1019
|
+
sock.nonblock = true if Mnet::MSG_DONTWAIT == 0
|
|
1002
1020
|
# Request buffers sized for the receive window. Linux clamps these to
|
|
1003
1021
|
# net.core.rmem_max/wmem_max, so read back the real value and cap the
|
|
1004
1022
|
# flow-control window to what the kernel can actually buffer -- otherwise
|
|
@@ -1038,7 +1056,7 @@ module Mnet
|
|
|
1038
1056
|
break if socks.empty?
|
|
1039
1057
|
begin
|
|
1040
1058
|
ready = IO.select(socks, nil, nil, 0.5)
|
|
1041
|
-
rescue IOError,
|
|
1059
|
+
rescue IOError, SystemCallError
|
|
1042
1060
|
break
|
|
1043
1061
|
end
|
|
1044
1062
|
next unless ready
|
|
@@ -1055,9 +1073,7 @@ module Mnet
|
|
|
1055
1073
|
cap.times do
|
|
1056
1074
|
data, addr = sock.recvfrom_nonblock(65_535)
|
|
1057
1075
|
dispatch(data, addr)
|
|
1058
|
-
rescue IO::WaitReadable,
|
|
1059
|
-
break
|
|
1060
|
-
rescue IOError, Errno::EBADF, Errno::ECONNRESET
|
|
1076
|
+
rescue IO::WaitReadable, SystemCallError, IOError
|
|
1061
1077
|
break
|
|
1062
1078
|
rescue => e
|
|
1063
1079
|
warn "mnet: #{e.class}: #{e.message}"
|