sshrpc/client.go

77 lines
1.4 KiB
Go

package sshrpc
import (
"fmt"
"net/rpc"
"golang.org/x/crypto/ssh"
)
type sshrpcSession struct {
*ssh.Session
}
func (s sshrpcSession) Read(p []byte) (n int, err error) {
pipe, err := s.StdoutPipe()
if err != nil {
return 0, err
}
return pipe.Read(p)
}
func (s sshrpcSession) Write(p []byte) (n int, err error) {
pipe, err := s.StdinPipe()
if err != nil {
return 0, err
}
return pipe.Write(p)
}
// Client represents an RPC client using an SSH backed connection.
type Client struct {
*rpc.Client
Config *ssh.ClientConfig
Subsystem string
}
// NewClient returns a new Client to handle RPC requests.
func NewClient() *Client {
config := &ssh.ClientConfig{
User: "sshrpc",
Auth: []ssh.AuthMethod{
ssh.Password("sshrpc"),
},
}
return &Client{nil, config, "sshrpc"}
}
// Connect starts a client connection to the given SSH/RPC server.
func (c *Client) Connect(address string) {
sshClient, err := ssh.Dial("tcp", address, c.Config)
if err != nil {
panic("Failed to dial: " + err.Error())
}
// Each ClientConn can support multiple interactive sessions,
// represented by a Session.
sshSession, err := sshClient.NewSession()
if err != nil {
panic("Failed to create session: " + err.Error())
}
//defer sshSession.Close()
err = sshSession.RequestSubsystem(c.Subsystem)
if err != nil {
fmt.Println("Unable to start subsystem:", err.Error())
}
session := sshrpcSession{sshSession}
c.Client = rpc.NewClient(session)
return
}