|
@@ -11,6 +11,8 @@ import (
|
|
|
"io"
|
|
"io"
|
|
|
"log"
|
|
"log"
|
|
|
"sync"
|
|
"sync"
|
|
|
|
|
+
|
|
|
|
|
+ "github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/protocol"
|
|
|
)
|
|
)
|
|
|
|
|
|
|
|
const (
|
|
const (
|
|
@@ -20,35 +22,47 @@ const (
|
|
|
// the minimum.
|
|
// the minimum.
|
|
|
channelMaxPacket = 1 << 15
|
|
channelMaxPacket = 1 << 15
|
|
|
|
|
|
|
|
- // We follow OpenSSH here.
|
|
|
|
|
- //channelWindowSize = 64 * channelMaxPacket
|
|
|
|
|
-
|
|
|
|
|
// PSIPHON
|
|
// PSIPHON
|
|
|
// =======
|
|
// =======
|
|
|
- // - Use a smaller initial/max channel window size.
|
|
|
|
|
- // - Testing with the full Psiphon stack shows that
|
|
|
|
|
- // this smaller channel window size is more performant
|
|
|
|
|
- // for low bandwidth connections while still adequate for
|
|
|
|
|
- // higher bandwidth connections.
|
|
|
|
|
- // - In Psiphon, a single SSH connection is used for all
|
|
|
|
|
- // client port forwards. Bulk data transfers with large
|
|
|
|
|
- // channel windows can immediately backlog the connection
|
|
|
|
|
- // with many large SSH packets, introducing large latency
|
|
|
|
|
- // for opening new channels. For Psiphon, we don't wish to
|
|
|
|
|
- // optimize for a single bulk transfer throughput.
|
|
|
|
|
- // - TODO: can we implement some sort of adaptive max
|
|
|
|
|
- // channel window size, starting with this small initial
|
|
|
|
|
- // value and only growing based on connection properties?
|
|
|
|
|
- // - channelWindowSize directly defines the local channel
|
|
|
|
|
- // window initial and max size. We also cap remote channel
|
|
|
|
|
- // window sizes via an extra customization in the
|
|
|
|
|
- // channelOpenConfirmMsg handler. Both upstream and
|
|
|
|
|
- // downstream bulk data transfers have the same latency
|
|
|
|
|
- // issue.
|
|
|
|
|
-
|
|
|
|
|
- channelWindowSize = 4 * channelMaxPacket
|
|
|
|
|
|
|
+ // Use getChannelWindowSize() instead of channelWindowSize.
|
|
|
|
|
+ //
|
|
|
|
|
+ // We follow OpenSSH here.
|
|
|
|
|
+ //channelWindowSize = 64 * channelMaxPacket
|
|
|
)
|
|
)
|
|
|
|
|
|
|
|
|
|
+// PSIPHON
|
|
|
|
|
+// =======
|
|
|
|
|
+// - Use a smaller initial/max channel window size.
|
|
|
|
|
+// - Testing with the full Psiphon stack shows that
|
|
|
|
|
+// this smaller channel window size is more performant
|
|
|
|
|
+// for low bandwidth connections while still adequate for
|
|
|
|
|
+// higher bandwidth connections.
|
|
|
|
|
+// - In Psiphon, a single SSH connection is used for all
|
|
|
|
|
+// client port forwards. Bulk data transfers with large
|
|
|
|
|
+// channel windows can immediately backlog the connection
|
|
|
|
|
+// with many large SSH packets, introducing large latency
|
|
|
|
|
+// for opening new channels. For Psiphon, we don't wish to
|
|
|
|
|
+// optimize for a single bulk transfer throughput.
|
|
|
|
|
+// - TODO: can we implement some sort of adaptive max
|
|
|
|
|
+// channel window size, starting with this small initial
|
|
|
|
|
+// value and only growing based on connection properties?
|
|
|
|
|
+// - channelWindowSize directly defines the local channel
|
|
|
|
|
+// window initial and max size. We also cap remote channel
|
|
|
|
|
+// window sizes via an extra customization in the
|
|
|
|
|
+// channelOpenConfirmMsg handler. Both upstream and
|
|
|
|
|
+// downstream bulk data transfers have the same latency
|
|
|
|
|
+// issue.
|
|
|
|
|
+// - For packet tunnel, use a larger channel window size,
|
|
|
|
|
+// since all tunneled traffic flows through a single
|
|
|
|
|
+// channel; we still select a size smaller than the stock
|
|
|
|
|
+// channelWindowSize due to client memory constraints.
|
|
|
|
|
+func getChannelWindowSize(chanType string) int {
|
|
|
|
|
+ if chanType == protocol.PACKET_TUNNEL_CHANNEL_TYPE {
|
|
|
|
|
+ return 16 * channelMaxPacket
|
|
|
|
|
+ }
|
|
|
|
|
+ return 4 * channelMaxPacket
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
// NewChannel represents an incoming request to a channel. It must either be
|
|
// NewChannel represents an incoming request to a channel. It must either be
|
|
|
// accepted for use by calling Accept, or rejected by calling Reject.
|
|
// accepted for use by calling Accept, or rejected by calling Reject.
|
|
|
type NewChannel interface {
|
|
type NewChannel interface {
|
|
@@ -466,7 +480,7 @@ func (c *channel) handlePacket(packet []byte) error {
|
|
|
// - See comments above channelWindowSize definition.
|
|
// - See comments above channelWindowSize definition.
|
|
|
|
|
|
|
|
//c.remoteWin.add(msg.MyWindow)
|
|
//c.remoteWin.add(msg.MyWindow)
|
|
|
- c.remoteWin.add(min(msg.MyWindow, channelWindowSize))
|
|
|
|
|
|
|
+ c.remoteWin.add(min(msg.MyWindow, getChannelWindowSize(c.chanType)))
|
|
|
|
|
|
|
|
c.msg <- msg
|
|
c.msg <- msg
|
|
|
case *windowAdjustMsg:
|
|
case *windowAdjustMsg:
|
|
@@ -491,7 +505,7 @@ func (c *channel) handlePacket(packet []byte) error {
|
|
|
func (m *mux) newChannel(chanType string, direction channelDirection, extraData []byte) *channel {
|
|
func (m *mux) newChannel(chanType string, direction channelDirection, extraData []byte) *channel {
|
|
|
ch := &channel{
|
|
ch := &channel{
|
|
|
remoteWin: window{Cond: newCond()},
|
|
remoteWin: window{Cond: newCond()},
|
|
|
- myWindow: channelWindowSize,
|
|
|
|
|
|
|
+ myWindow: uint32(getChannelWindowSize(chanType)),
|
|
|
pending: newBuffer(),
|
|
pending: newBuffer(),
|
|
|
extPending: newBuffer(),
|
|
extPending: newBuffer(),
|
|
|
direction: direction,
|
|
direction: direction,
|