go 有办法调用基础库 golang.org/x/crypto 的私有结构和方法吗?

198 天前
 LonnyWong

开源项目 https://github.com/trzsz/trzsz-ssh 想支持 ssh ControlMaster 的功能。

go 基础库 golang.org/x/crypto 有个 PR https://go-review.googlesource.com/c/crypto/+/383374 还没合入。

有办法在不 fork 基础库 golang.org/x/crypto 的情况下,优雅地在自己的项目实现这个 PR 的逻辑吗?

import "golang.org/x/crypto/ssh"

func NewControlClientConn(c net.Conn) (ssh.Conn, <-chan ssh.NewChannel, <-chan *ssh.Request, error) {
  conn := &ssh.connection{     ■ undefined: ssh.connection
    sshConn: ssh.sshConn{conn: c},     ■ undefined: ssh.sshConn
  }
  var err error
  if conn.transport, err = handshakeControlProxy(c); err != nil {
    return nil, nil, nil, fmt.Errorf("ssh: control proxy handshake failed; %v", err)
  }
  conn.mux = ssh.newMux(conn.transport)     ■ undefined: ssh.newMux
  return conn, conn.mux.incomingChannels, conn.mux.incomingRequests, nil
}

handshakeControlProxy 这个函数很好办,直接从 PR 中复制出来就行了。

问题:上面的 ssh.connectionssh.sshConnssh.newMux 依赖很深,发现很难直接 copy 出来。

1970 次点击
所在节点    Go 编程语言
25 条回复
Nazz
198 天前
用 go:linkname 把私有函数链出来; unsafe 读写私有结构
LonnyWong
198 天前
@Nazz unsafe 能引用私有结构吗?具体怎么做?
liuidetmks
198 天前
chatGPT ?
LonnyWong
198 天前
@liuidetmks 你问问看?
ysicing
198 天前
@LonnyWong V2EX 不允许 gpt 回答的,会 ban 账号的。
Junian
198 天前
@LonnyWong 可以看 https://github.com/dolthub/maphash 这玩意的实现,其实就是自己整个和私有结构体一模一样的,然后把指针映射到自己的结构体上
lysS
198 天前
@Nazz #1 link 要在 golang.org/x/crypto 里面写

其实可以用 go 汇编,可以直接根据包名﹒变量名引用(这个不安全)
kkbblzq
198 天前
@lysS 不需要的,外面写一个相同定义的函数 link 原函数就行了


//go:linkname func1 pkg.func1
func func1(a string) string

记得 import _ "unsafe"
LonnyWong
198 天前
@kkbblzq 现在要调用的函数是

func newMux(p packetConn) *mux

问题是 packetConn 和 mux 都是私有的,怎么用 go:linkname 定义呢?

type packetConn interface {
// Encrypt and send a packet of data to the remote peer.
writePacket(packet []byte) error

// Read a packet from the connection. The read is blocking,
// i.e. if error is nil, then the returned byte slice is
// always non-empty.
readPacket() ([]byte, error)

// Close closes the write-side of the connection.
Close() error
}


type mux struct {
conn packetConn
chanList chanList

incomingChannels chan NewChannel

globalSentMu sync.Mutex
globalResponses chan interface{}
incomingRequests chan *Request

errCond *sync.Cond
err error
}
lysS
198 天前
@kkbblzq #8 你这反了,你看 runtime now

https://github.com/golang/go/blob/master/src/runtime/timestub.go#L14

连接到 time now ,linkname 是写在 runtime 而不是 time
learningman
198 天前
最好别拿 linkname 搞,升级 go 版本的时候容易炸。
还是乖乖开个 fork 吧
lysS
198 天前
LonnyWong
198 天前
@learningman fork golang.org/x/crypto 也不好啊。
777777
198 天前
Go 创始人说:最好的方法就是复制
LonnyWong
198 天前
@777777 #14 反对他。我只是要加一点点功能,我可没有能力和精力去维护那么大一个库。
Nazz
198 天前
@LonnyWong 可以算偏移量直接读写; 或者定义一个相同结构的 struct, unsafe 强转 (我不清楚是否安全)
wwqgtxx
198 天前
@lysS #10 ,linkname 在哪边写都是可以的
chimission
198 天前
可以复制, 毕竟标准库里为了解决循环引用 也搞了很多复制
bruce0
198 天前
用 `unsafe.Pointer` + 偏移量 可以做到
kkbblzq
198 天前
@LonnyWong packetConn 是个 interface 吧,直接拷贝出来就是了,

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/985115

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX