-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathconn.go
More file actions
144 lines (119 loc) · 2.97 KB
/
conn.go
File metadata and controls
144 lines (119 loc) · 2.97 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
package echogy
import (
"fmt"
gossh "golang.org/x/crypto/ssh"
"io"
"net"
"time"
)
// bufferedReader implements an io.Reader that buffers data and supports re-reading
type bufferedReader struct {
reader io.Reader
buffer []byte
position int
}
// newBufferedReader creates a new bufferedReader
func newBufferedReader(reader io.Reader) *bufferedReader {
return &bufferedReader{
reader: reader,
buffer: make([]byte, 0),
position: 0,
}
}
type bufferedConn struct {
reader io.Reader
net.Conn
}
func (c *bufferedConn) Read(b []byte) (n int, err error) {
return c.reader.Read(b)
}
func (b *bufferedReader) toBufferedConn(conn net.Conn) net.Conn {
b.Reset()
return &bufferedConn{
reader: io.MultiReader(b, conn),
Conn: conn,
}
}
// Read implements io.Reader interface
func (b *bufferedReader) Read(p []byte) (n int, err error) {
// If we have buffered data and haven't reached the end
if b.position < len(b.buffer) {
n = copy(p, b.buffer[b.position:])
b.position += n
return n, nil
}
// Read new data from the underlying reader
n, err = b.reader.Read(p)
if n > 0 {
// Append new data to our buffer
b.buffer = append(b.buffer, p[:n]...)
b.position += n
}
return n, err
}
// Reset resets the read position to the beginning of the buffer
func (b *bufferedReader) Reset() {
b.position = 0
}
// Seek sets the read position to a specific offset
func (b *bufferedReader) Seek(offset int64, whence int) (int64, error) {
var abs int64
switch whence {
case io.SeekStart:
abs = offset
case io.SeekCurrent:
abs = int64(b.position) + offset
case io.SeekEnd:
abs = int64(len(b.buffer)) + offset
default:
return 0, fmt.Errorf("invalid whence: %d", whence)
}
if abs < 0 {
return 0, fmt.Errorf("negative position: %d", abs)
}
if abs > int64(len(b.buffer)) {
return 0, fmt.Errorf("seek position %d beyond buffer length %d", abs, len(b.buffer))
}
b.position = int(abs)
return abs, nil
}
// Bytes returns a copy of the buffered data
func (b *bufferedReader) Bytes() []byte {
return append([]byte(nil), b.buffer...)
}
// Len returns the total length of buffered data
func (b *bufferedReader) Len() int {
return len(b.buffer)
}
// Position returns the current read position
func (b *bufferedReader) Position() int {
return b.position
}
type wrappedConn struct {
conn *gossh.ServerConn
gossh.Channel
}
func wrapChannelConn(conn *gossh.ServerConn, channel gossh.Channel) *wrappedConn {
return &wrappedConn{conn: conn, Channel: channel}
}
func (w *wrappedConn) bufferedReader() *bufferedReader {
return newBufferedReader(w)
}
func (w *wrappedConn) LocalAddr() net.Addr {
return w.conn.LocalAddr()
}
func (w *wrappedConn) RemoteAddr() net.Addr {
return w.conn.RemoteAddr()
}
func (w *wrappedConn) SetDeadline(t time.Time) error {
return nil
}
func (w *wrappedConn) SetReadDeadline(t time.Time) error {
return nil
}
func (w *wrappedConn) SetWriteDeadline(t time.Time) error {
return nil
}
func (w *wrappedConn) Close() error {
return w.Channel.Close()
}