mirror of https://github.com/v2ray/v2ray-core
move framemeta onto stack
parent
fce64b1665
commit
f9f8c21a07
|
@ -1,6 +1,8 @@
|
||||||
package mux
|
package mux
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"io"
|
||||||
|
|
||||||
"v2ray.com/core/common"
|
"v2ray.com/core/common"
|
||||||
"v2ray.com/core/common/bitmask"
|
"v2ray.com/core/common/bitmask"
|
||||||
"v2ray.com/core/common/buf"
|
"v2ray.com/core/common/buf"
|
||||||
|
@ -86,18 +88,36 @@ func (f FrameMetadata) WriteTo(b *buf.Buffer) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// ReadFrameFrom reads a FrameMetadata from the given buffer.
|
// ReadFrom reads FrameMetadata from the given reader.
|
||||||
// Visible for testing only.
|
func (f *FrameMetadata) ReadFrom(reader io.Reader) error {
|
||||||
func ReadFrameFrom(b *buf.Buffer) (*FrameMetadata, error) {
|
metaLen, err := serial.ReadUint16(reader)
|
||||||
if b.Len() < 4 {
|
if err != nil {
|
||||||
return nil, newError("insufficient buffer: ", b.Len())
|
return err
|
||||||
|
}
|
||||||
|
if metaLen > 512 {
|
||||||
|
return newError("invalid metalen ", metaLen).AtError()
|
||||||
}
|
}
|
||||||
|
|
||||||
f := &FrameMetadata{
|
b := buf.New()
|
||||||
SessionID: serial.BytesToUint16(b.BytesTo(2)),
|
defer b.Release()
|
||||||
SessionStatus: SessionStatus(b.Byte(2)),
|
|
||||||
Option: bitmask.Byte(b.Byte(3)),
|
if err := b.Reset(buf.ReadFullFrom(reader, int32(metaLen))); err != nil {
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
return f.ReadFromBuffer(b)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ReadFromBuffer reads a FrameMetadata from the given buffer.
|
||||||
|
// Visible for testing only.
|
||||||
|
func (f *FrameMetadata) ReadFromBuffer(b *buf.Buffer) error {
|
||||||
|
if b.Len() < 4 {
|
||||||
|
return newError("insufficient buffer: ", b.Len())
|
||||||
|
}
|
||||||
|
|
||||||
|
f.SessionID = serial.BytesToUint16(b.BytesTo(2))
|
||||||
|
f.SessionStatus = SessionStatus(b.Byte(2))
|
||||||
|
f.Option = bitmask.Byte(b.Byte(3))
|
||||||
|
f.Target.Network = net.Network_Unknown
|
||||||
|
|
||||||
if f.SessionStatus == SessionStatusNew {
|
if f.SessionStatus == SessionStatusNew {
|
||||||
network := TargetNetwork(b.Byte(4))
|
network := TargetNetwork(b.Byte(4))
|
||||||
|
@ -105,7 +125,7 @@ func ReadFrameFrom(b *buf.Buffer) (*FrameMetadata, error) {
|
||||||
|
|
||||||
addr, port, err := addrParser.ReadAddressPort(nil, b)
|
addr, port, err := addrParser.ReadAddressPort(nil, b)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, newError("failed to parse address and port").Base(err)
|
return newError("failed to parse address and port").Base(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
switch network {
|
switch network {
|
||||||
|
@ -114,9 +134,9 @@ func ReadFrameFrom(b *buf.Buffer) (*FrameMetadata, error) {
|
||||||
case TargetNetworkUDP:
|
case TargetNetworkUDP:
|
||||||
f.Target = net.UDPDestination(addr, port)
|
f.Target = net.UDPDestination(addr, port)
|
||||||
default:
|
default:
|
||||||
return nil, newError("unknown network type: ", network)
|
return newError("unknown network type: ", network)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return f, nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -264,8 +264,9 @@ func (m *Client) fetchOutput() {
|
||||||
|
|
||||||
reader := &buf.BufferedReader{Reader: m.link.Reader}
|
reader := &buf.BufferedReader{Reader: m.link.Reader}
|
||||||
|
|
||||||
|
var meta FrameMetadata
|
||||||
for {
|
for {
|
||||||
meta, err := ReadMetadata(reader)
|
err := meta.ReadFrom(reader)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if errors.Cause(err) != io.EOF {
|
if errors.Cause(err) != io.EOF {
|
||||||
newError("failed to read metadata").Base(err).WriteToLog()
|
newError("failed to read metadata").Base(err).WriteToLog()
|
||||||
|
@ -275,15 +276,16 @@ func (m *Client) fetchOutput() {
|
||||||
|
|
||||||
switch meta.SessionStatus {
|
switch meta.SessionStatus {
|
||||||
case SessionStatusKeepAlive:
|
case SessionStatusKeepAlive:
|
||||||
err = m.handleStatueKeepAlive(meta, reader)
|
err = m.handleStatueKeepAlive(&meta, reader)
|
||||||
case SessionStatusEnd:
|
case SessionStatusEnd:
|
||||||
err = m.handleStatusEnd(meta, reader)
|
err = m.handleStatusEnd(&meta, reader)
|
||||||
case SessionStatusNew:
|
case SessionStatusNew:
|
||||||
err = m.handleStatusNew(meta, reader)
|
err = m.handleStatusNew(&meta, reader)
|
||||||
case SessionStatusKeep:
|
case SessionStatusKeep:
|
||||||
err = m.handleStatusKeep(meta, reader)
|
err = m.handleStatusKeep(&meta, reader)
|
||||||
default:
|
default:
|
||||||
newError("unknown status: ", meta.SessionStatus).AtError().WriteToLog()
|
status := meta.SessionStatus
|
||||||
|
newError("unknown status: ", status).AtError().WriteToLog()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -437,22 +439,24 @@ func (w *ServerWorker) handleStatusEnd(meta *FrameMetadata, reader *buf.Buffered
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *ServerWorker) handleFrame(ctx context.Context, reader *buf.BufferedReader) error {
|
func (w *ServerWorker) handleFrame(ctx context.Context, reader *buf.BufferedReader) error {
|
||||||
meta, err := ReadMetadata(reader)
|
var meta FrameMetadata
|
||||||
|
err := meta.ReadFrom(reader)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return newError("failed to read metadata").Base(err)
|
return newError("failed to read metadata").Base(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
switch meta.SessionStatus {
|
switch meta.SessionStatus {
|
||||||
case SessionStatusKeepAlive:
|
case SessionStatusKeepAlive:
|
||||||
err = w.handleStatusKeepAlive(meta, reader)
|
err = w.handleStatusKeepAlive(&meta, reader)
|
||||||
case SessionStatusEnd:
|
case SessionStatusEnd:
|
||||||
err = w.handleStatusEnd(meta, reader)
|
err = w.handleStatusEnd(&meta, reader)
|
||||||
case SessionStatusNew:
|
case SessionStatusNew:
|
||||||
err = w.handleStatusNew(ctx, meta, reader)
|
err = w.handleStatusNew(ctx, &meta, reader)
|
||||||
case SessionStatusKeep:
|
case SessionStatusKeep:
|
||||||
err = w.handleStatusKeep(meta, reader)
|
err = w.handleStatusKeep(&meta, reader)
|
||||||
default:
|
default:
|
||||||
return newError("unknown status: ", meta.SessionStatus).AtError()
|
status := meta.SessionStatus
|
||||||
|
return newError("unknown status: ", status).AtError()
|
||||||
}
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -61,7 +61,8 @@ func TestReaderWriter(t *testing.T) {
|
||||||
|
|
||||||
bytesReader := &buf.BufferedReader{Reader: pReader}
|
bytesReader := &buf.BufferedReader{Reader: pReader}
|
||||||
|
|
||||||
meta, err := ReadMetadata(bytesReader)
|
var meta FrameMetadata
|
||||||
|
err := meta.ReadFrom(bytesReader)
|
||||||
assert(err, IsNil)
|
assert(err, IsNil)
|
||||||
assert(meta.SessionID, Equals, uint16(1))
|
assert(meta.SessionID, Equals, uint16(1))
|
||||||
assert(byte(meta.SessionStatus), Equals, byte(SessionStatusNew))
|
assert(byte(meta.SessionStatus), Equals, byte(SessionStatusNew))
|
||||||
|
@ -73,14 +74,14 @@ func TestReaderWriter(t *testing.T) {
|
||||||
assert(len(data), Equals, 1)
|
assert(len(data), Equals, 1)
|
||||||
assert(data[0].String(), Equals, "abcd")
|
assert(data[0].String(), Equals, "abcd")
|
||||||
|
|
||||||
meta, err = ReadMetadata(bytesReader)
|
err = meta.ReadFrom(bytesReader)
|
||||||
assert(err, IsNil)
|
assert(err, IsNil)
|
||||||
assert(byte(meta.SessionStatus), Equals, byte(SessionStatusNew))
|
assert(byte(meta.SessionStatus), Equals, byte(SessionStatusNew))
|
||||||
assert(meta.SessionID, Equals, uint16(2))
|
assert(meta.SessionID, Equals, uint16(2))
|
||||||
assert(byte(meta.Option), Equals, byte(0))
|
assert(byte(meta.Option), Equals, byte(0))
|
||||||
assert(meta.Target, Equals, dest2)
|
assert(meta.Target, Equals, dest2)
|
||||||
|
|
||||||
meta, err = ReadMetadata(bytesReader)
|
err = meta.ReadFrom(bytesReader)
|
||||||
assert(err, IsNil)
|
assert(err, IsNil)
|
||||||
assert(byte(meta.SessionStatus), Equals, byte(SessionStatusKeep))
|
assert(byte(meta.SessionStatus), Equals, byte(SessionStatusKeep))
|
||||||
assert(meta.SessionID, Equals, uint16(1))
|
assert(meta.SessionID, Equals, uint16(1))
|
||||||
|
@ -91,7 +92,7 @@ func TestReaderWriter(t *testing.T) {
|
||||||
assert(len(data), Equals, 1)
|
assert(len(data), Equals, 1)
|
||||||
assert(data[0].String(), Equals, "efgh")
|
assert(data[0].String(), Equals, "efgh")
|
||||||
|
|
||||||
meta, err = ReadMetadata(bytesReader)
|
err = meta.ReadFrom(bytesReader)
|
||||||
assert(err, IsNil)
|
assert(err, IsNil)
|
||||||
assert(byte(meta.SessionStatus), Equals, byte(SessionStatusNew))
|
assert(byte(meta.SessionStatus), Equals, byte(SessionStatusNew))
|
||||||
assert(meta.SessionID, Equals, uint16(3))
|
assert(meta.SessionID, Equals, uint16(3))
|
||||||
|
@ -103,19 +104,19 @@ func TestReaderWriter(t *testing.T) {
|
||||||
assert(len(data), Equals, 1)
|
assert(len(data), Equals, 1)
|
||||||
assert(data[0].String(), Equals, "x")
|
assert(data[0].String(), Equals, "x")
|
||||||
|
|
||||||
meta, err = ReadMetadata(bytesReader)
|
err = meta.ReadFrom(bytesReader)
|
||||||
assert(err, IsNil)
|
assert(err, IsNil)
|
||||||
assert(byte(meta.SessionStatus), Equals, byte(SessionStatusEnd))
|
assert(byte(meta.SessionStatus), Equals, byte(SessionStatusEnd))
|
||||||
assert(meta.SessionID, Equals, uint16(1))
|
assert(meta.SessionID, Equals, uint16(1))
|
||||||
assert(byte(meta.Option), Equals, byte(0))
|
assert(byte(meta.Option), Equals, byte(0))
|
||||||
|
|
||||||
meta, err = ReadMetadata(bytesReader)
|
err = meta.ReadFrom(bytesReader)
|
||||||
assert(err, IsNil)
|
assert(err, IsNil)
|
||||||
assert(byte(meta.SessionStatus), Equals, byte(SessionStatusEnd))
|
assert(byte(meta.SessionStatus), Equals, byte(SessionStatusEnd))
|
||||||
assert(meta.SessionID, Equals, uint16(3))
|
assert(meta.SessionID, Equals, uint16(3))
|
||||||
assert(byte(meta.Option), Equals, byte(0))
|
assert(byte(meta.Option), Equals, byte(0))
|
||||||
|
|
||||||
meta, err = ReadMetadata(bytesReader)
|
err = meta.ReadFrom(bytesReader)
|
||||||
assert(err, IsNil)
|
assert(err, IsNil)
|
||||||
assert(byte(meta.SessionStatus), Equals, byte(SessionStatusKeep))
|
assert(byte(meta.SessionStatus), Equals, byte(SessionStatusKeep))
|
||||||
assert(meta.SessionID, Equals, uint16(2))
|
assert(meta.SessionID, Equals, uint16(2))
|
||||||
|
@ -126,7 +127,7 @@ func TestReaderWriter(t *testing.T) {
|
||||||
assert(len(data), Equals, 1)
|
assert(len(data), Equals, 1)
|
||||||
assert(data[0].String(), Equals, "y")
|
assert(data[0].String(), Equals, "y")
|
||||||
|
|
||||||
meta, err = ReadMetadata(bytesReader)
|
err = meta.ReadFrom(bytesReader)
|
||||||
assert(err, IsNil)
|
assert(err, IsNil)
|
||||||
assert(byte(meta.SessionStatus), Equals, byte(SessionStatusEnd))
|
assert(byte(meta.SessionStatus), Equals, byte(SessionStatusEnd))
|
||||||
assert(meta.SessionID, Equals, uint16(2))
|
assert(meta.SessionID, Equals, uint16(2))
|
||||||
|
@ -134,7 +135,6 @@ func TestReaderWriter(t *testing.T) {
|
||||||
|
|
||||||
pWriter.Close()
|
pWriter.Close()
|
||||||
|
|
||||||
meta, err = ReadMetadata(bytesReader)
|
err = meta.ReadFrom(bytesReader)
|
||||||
assert(err, IsNotNil)
|
assert(err, IsNotNil)
|
||||||
assert(meta, IsNil)
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,25 +8,6 @@ import (
|
||||||
"v2ray.com/core/common/serial"
|
"v2ray.com/core/common/serial"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ReadMetadata reads FrameMetadata from the given reader.
|
|
||||||
func ReadMetadata(reader io.Reader) (*FrameMetadata, error) {
|
|
||||||
metaLen, err := serial.ReadUint16(reader)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if metaLen > 512 {
|
|
||||||
return nil, newError("invalid metalen ", metaLen).AtError()
|
|
||||||
}
|
|
||||||
|
|
||||||
b := buf.New()
|
|
||||||
defer b.Release()
|
|
||||||
|
|
||||||
if err := b.Reset(buf.ReadFullFrom(reader, int32(metaLen))); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return ReadFrameFrom(b)
|
|
||||||
}
|
|
||||||
|
|
||||||
// PacketReader is an io.Reader that reads whole chunk of Mux frames every time.
|
// PacketReader is an io.Reader that reads whole chunk of Mux frames every time.
|
||||||
type PacketReader struct {
|
type PacketReader struct {
|
||||||
reader io.Reader
|
reader io.Reader
|
||||||
|
|
Loading…
Reference in New Issue