gnet icon indicating copy to clipboard operation
gnet copied to clipboard

使用 gnet 做代理隧道时,React 的 frame 参数显得多余

Open dawndiy opened this issue 3 years ago • 8 comments

如果用 gnet 做全双工的代理隧道的场景。

client -- raw --> proxy(use gnet) -- socks5(raw) --> server

这里遇见几个问题。 1)按 gnet 的事件划分,在 OnOpen 里同步去建立 proxy -> server 的连接会比较合适,那么需要 读取 client 数据流里的前几个 bytes 来在 client <-> proxy 间做握手,但是 OnOpen 里调用 c.Read() 会得不到数据,inbound buf 是空的。 2)假设 gnet 里 上面的问题 1 不允许 Read 。那么只能在 React 回调里去做 client <-> proxy 的握手并建立 proxy <-> server 的连接。但是 React(frame []byte, c gent.Conn) 的第一个参数 frame 就显得很费解。我理解的 gnet 的设计思路,应该是用自定义 codec 来做 TCP 流的分包,然后直接给到 "逻辑开发者" 调用的 React 函数来处理,这样方便 “开发者” 在 React 写每个分包的逻辑。但我上面的这个场景,如果要自定义 codec 有几个问题,因为 握手 是一次性的(一个 TCP 流建立时只有一次和 client 的握手),我只能控制 React 调用后不返回,为了让 React 只回调一次,然后自己控制全双工转发。这样写就违背了我上面理解的思路,而且假设 不是 socks5 协议,而是client到proxy的流要按块来做解密加密,那么 React 的 frame 参数就比较合适。

综上,有办法在 OnOpen 里 Read client 的数据吗?如果不行,上面的场景有合适的写法吗?

dawndiy avatar Jul 19 '21 03:07 dawndiy

Thanks for opening a new issue. The team has been notified and will review it as soon as possible. For urgent issues and priority support, visit https://xscode.com/panjf2000/gnet

xscode-auto-reply[bot] avatar Jul 19 '21 03:07 xscode-auto-reply[bot]

看起来和 #220 是一类问题?看来这种连接建立后首个包特殊处理的场景不少见,可以考虑新增一个 API 支持这类场景。

panjf2000 avatar Jul 21 '21 03:07 panjf2000

看了一下 #220 ,是一类问题。对于数据流服务,一般都有一个 7 层的协议握手。如果新增一个 API,也可以同时考虑扩展 gnet.ICodec 来做自定义扩展。

dawndiy avatar Jul 21 '21 05:07 dawndiy

扩展 codec 是啥意思?

panjf2000 avatar Jul 21 '21 06:07 panjf2000

如果是做数据流服务,除了数据分包的 Encode/Decode,还有最开始的 Handshake,看 gnet.ICodec 的设计,应该现在只是为了 解析或编码 数据分包。我的意思是按这个思路,可以给 gnet.ICodec 接口添加 Handeshake 方法。这样,一个 gnet.ICodec 就可以支持一套协议。

dawndiy avatar Jul 21 '21 06:07 dawndiy

gnet.ICodec 和 handshake 没什么关系,编解码器主要关心的是协议的处理,握手应该是有一个专门的 handler。

我想可能都不需要新加一个 API,直接让用户注册一个 handshake handler,然后收到第一个包的时候调用一下就行。

panjf2000 avatar Jul 21 '21 08:07 panjf2000

确实需要第一个包的处理,专门处理 handshake, 所有建立在 tcp 连接之上的协议都需要

bean-du avatar Aug 04 '21 06:08 bean-du

我理解是不是业务方实现 gnet.ICodec 接口的 struct 里设置一个 bool 值,然后在 codec.Decode() 里面直接判断一下就行了?如果是第一个包就去调用业务方的 handshake handler 进行握手,这样是不是就可以解决你们的问题了?

panjf2000 avatar Aug 04 '21 07:08 panjf2000