Module: Mnet
- Defined in:
- lib/mnet.rb,
lib/mnet/version.rb
Defined Under Namespace
Modules: SessionIO Classes: Endpoint, Frame, KcpSession, Packet, Server, Session
Constant Summary collapse
- MAGIC =
"\x12\xE9\x97".b
- MAGIC_LEN =
3- SESSION_ID_LEN =
16- IP_MTU =
Conservative MTU for mobile networks / VPN tunnels (mosh uses 1280).
1280- DEFAULT_MSS =
IP(20) + UDP(8) + our header + GCM tag(16) leaves ~1190 for a segment.
1200- MIN_RTO =
RTO bounds (mosh: MIN_RTO = 50ms, MAX_RTO = 1000ms).
0.05- MAX_RTO =
1.0- MAX_OLD_SOCKET_AGE =
How long to keep a superseded (hopped-away-from) socket alive to catch delayed packets (mosh: MAX_OLD_SOCKET_AGE = 60000ms).
60.0- MSG_DONTWAIT =
非阻塞发送标志:POSIX 有 MSG_DONTWAIT,Windows 没有(用 nonblock 模式兜底)。
Socket.const_defined?(:MSG_DONTWAIT) ? Socket::MSG_DONTWAIT : 0
- TYPE_SYN =
Message types (mirrors the enum-message-types pattern from tmux-protocol.h).
0x01- TYPE_SYNACK =
0x02- TYPE_DATA =
0x03- TYPE_ACK =
0x04- TYPE_FIN =
0x05- TYPE_PING =
0x06- TYPE_PONG =
0x07- FLAG_NONE =
0x00- FLAG_MIGRATE =
0x01- FLAG_KCP =
session uses the KCP (C) engine instead of the Ruby ARQ
0x02- HEADER_LEN =
MAGIC_LEN + SESSION_ID_LEN + 8 + 8 + 1 + 1 + 4
- MAX_RETRIES =
10- TYPES =
{ TYPE_SYN => "SYN", TYPE_SYNACK => "SYNACK", TYPE_DATA => "DATA", TYPE_ACK => "ACK", TYPE_FIN => "FIN", TYPE_PING => "PING", TYPE_PONG => "PONG" }.freeze
- VERSION =
'0.1.3'
Class Method Summary collapse
- .addr_pair(addr) ⇒ Object
- .fmt(addr) ⇒ Object
- .now ⇒ Object
- .pack(session_id, seq, ack, type, flags, window, payload = "".b) ⇒ Object
-
.session_id_from_key(key) ⇒ Object
Session id is derived from the shared session key (mosh-style), so the id identifies the key and vice versa; without a key it is just random.
-
.socket_pair ⇒ Object
A connected stream socket pair, portable across Windows/Linux/macOS.
- .type_name(type) ⇒ Object
- .unpack(data) ⇒ Object
Class Method Details
.addr_pair(addr) ⇒ Object
93 94 95 |
# File 'lib/mnet.rb', line 93 def addr_pair(addr) [addr[3], addr[1]] end |
.fmt(addr) ⇒ Object
97 98 99 |
# File 'lib/mnet.rb', line 97 def fmt(addr) "#{addr[0]}:#{addr[1]}" end |
.now ⇒ Object
101 102 103 |
# File 'lib/mnet.rb', line 101 def now Process.clock_gettime(Process::CLOCK_MONOTONIC) end |
.pack(session_id, seq, ack, type, flags, window, payload = "".b) ⇒ Object
76 77 78 79 |
# File 'lib/mnet.rb', line 76 def pack(session_id, seq, ack, type, flags, window, payload = "".b) [MAGIC, session_id, seq, ack, type, flags, window, payload] .pack("a3a16Q>Q>CCNa*") end |
.session_id_from_key(key) ⇒ Object
Session id is derived from the shared session key (mosh-style), so the id identifies the key and vice versa; without a key it is just random.
107 108 109 |
# File 'lib/mnet.rb', line 107 def session_id_from_key(key) OpenSSL::Digest::SHA256.digest(key)[0, SESSION_ID_LEN] end |
.socket_pair ⇒ Object
A connected stream socket pair, portable across Windows/Linux/macOS. Prefers a UNIX socketpair; falls back to a loopback TCP pair where AF_UNIX socketpair is unavailable (Windows).
114 115 116 117 118 119 120 121 122 123 |
# File 'lib/mnet.rb', line 114 def socket_pair Socket.pair(:UNIX, :STREAM, 0) rescue SystemCallError, NotImplementedError server = TCPServer.new("127.0.0.1", 0) port = server.addr[1] client = TCPSocket.new("127.0.0.1", port) accepted = server.accept server.close [accepted, client] end |
.type_name(type) ⇒ Object
89 90 91 |
# File 'lib/mnet.rb', line 89 def type_name(type) TYPES.fetch(type, "UNKNOWN(#{type})") end |
.unpack(data) ⇒ Object
81 82 83 84 85 86 87 |
# File 'lib/mnet.rb', line 81 def unpack(data) return nil if data.bytesize < HEADER_LEN magic, sid, seq, ack, type, flags, window = data.unpack("a3a16Q>Q>CCN") return nil unless magic == MAGIC Packet.new(sid, seq, ack, type, flags, window, data.byteslice(HEADER_LEN, data.bytesize - HEADER_LEN) || "".b) end |