bd30afaaf9
Local sync and sync over SSH seems to work. The sshdirect transport might be interesting / re-usable for zrepl as well, although we'd still need some kind of locking in that case.
92 lines
1.7 KiB
Go
92 lines
1.7 KiB
Go
package sshdirect
|
|
|
|
import (
|
|
"bytes"
|
|
"io"
|
|
"log"
|
|
"net"
|
|
"os"
|
|
"time"
|
|
|
|
"github.com/hashicorp/yamux"
|
|
)
|
|
|
|
type ServeConn struct {
|
|
stdin, stdout *os.File
|
|
}
|
|
|
|
var _ net.Conn = (*ServeConn)(nil)
|
|
|
|
func ServeStdin() (net.Listener, error) {
|
|
|
|
conn := &ServeConn{
|
|
stdin: os.Stdin,
|
|
stdout: os.Stdout,
|
|
}
|
|
|
|
var buf bytes.Buffer
|
|
buf.Write(banner_msg)
|
|
if _, err := io.Copy(conn, &buf); err != nil {
|
|
log.Printf("error sending confirm message: %s", err)
|
|
conn.Close()
|
|
return nil, err
|
|
}
|
|
buf.Reset()
|
|
if _, err := io.CopyN(&buf, conn, int64(len(begin_msg))); err != nil {
|
|
log.Printf("error reading begin message: %s", err)
|
|
conn.Close()
|
|
return nil, err
|
|
}
|
|
|
|
return yamux.Server(conn, nil)
|
|
}
|
|
|
|
func (c *ServeConn) Read(p []byte) (int, error) {
|
|
return c.stdin.Read(p)
|
|
}
|
|
|
|
func (c *ServeConn) Write(p []byte) (int, error) {
|
|
return c.stdout.Write(p)
|
|
}
|
|
|
|
func (f *ServeConn) Close() (err error) {
|
|
e1 := f.stdin.Close()
|
|
e2 := f.stdout.Close()
|
|
// FIXME merge errors
|
|
if e1 != nil {
|
|
return e1
|
|
}
|
|
return e2
|
|
}
|
|
|
|
func (f *ServeConn) SetReadDeadline(t time.Time) error {
|
|
return f.stdin.SetReadDeadline(t)
|
|
}
|
|
|
|
func (f *ServeConn) SetWriteDeadline(t time.Time) error {
|
|
return f.stdout.SetReadDeadline(t)
|
|
}
|
|
|
|
func (f *ServeConn) SetDeadline(t time.Time) error {
|
|
// try both...
|
|
werr := f.SetWriteDeadline(t)
|
|
rerr := f.SetReadDeadline(t)
|
|
if werr != nil {
|
|
return werr
|
|
}
|
|
if rerr != nil {
|
|
return rerr
|
|
}
|
|
return nil
|
|
}
|
|
|
|
type serveAddr struct{}
|
|
|
|
const GoNetwork string = "sshdirect"
|
|
|
|
func (serveAddr) Network() string { return GoNetwork }
|
|
func (serveAddr) String() string { return "???" }
|
|
|
|
func (f *ServeConn) LocalAddr() net.Addr { return serveAddr{} }
|
|
func (f *ServeConn) RemoteAddr() net.Addr { return serveAddr{} }
|