netgiv/client.go

243 lines
5.1 KiB
Go
Raw Permalink Normal View History

package main
import (
2022-01-13 22:20:35 +10:30
"bufio"
2022-01-14 23:30:14 +10:30
"bytes"
"encoding/gob"
"errors"
"fmt"
2022-01-13 22:20:35 +10:30
"io"
"net"
2022-01-13 22:20:35 +10:30
"os"
"time"
log "github.com/sirupsen/logrus"
2022-01-15 23:10:46 +10:30
"github.com/dustin/go-humanize"
"github.com/tardisx/netgiv/secure"
)
type Client struct {
2022-01-17 08:28:08 +10:30
address string
port int
list bool
send bool
burnNum int
2022-01-17 08:28:08 +10:30
receiveNum int
authToken string
}
func (c *Client) Connect() error {
2022-01-13 22:20:35 +10:30
address := fmt.Sprintf("%s:%d", c.address, c.port)
d := net.Dialer{Timeout: 5 * time.Second}
conn, err := d.Dial("tcp", address)
if err != nil {
return fmt.Errorf("problem connecting to server, is it running?: %v", err)
}
defer conn.Close()
2022-01-16 20:35:35 +10:30
log.Debugf("established connection on %s", address)
tcpConn, ok := conn.(*net.TCPConn)
if !ok {
log.Fatal("could not assert")
}
sharedKey := secure.Handshake(tcpConn)
2022-01-14 23:30:14 +10:30
secureConnection := secure.SecureConnection{Conn: conn, SharedKey: sharedKey, Buffer: &bytes.Buffer{}}
enc := gob.NewEncoder(&secureConnection)
2022-01-14 23:30:14 +10:30
dec := gob.NewDecoder(&secureConnection)
switch {
case c.list:
2022-01-16 20:35:35 +10:30
log.Debugf("requesting file list")
err := c.connectToServer(secure.OperationTypeList, enc, dec)
2022-01-14 23:30:14 +10:30
if err != nil {
return fmt.Errorf("could not connect and auth: %v", err)
2022-01-14 23:30:14 +10:30
}
2022-01-14 23:30:14 +10:30
// now we expect to get stuff back until we don't
2022-01-26 08:49:54 +10:30
numFiles := 0
2022-01-14 23:30:14 +10:30
for {
listPacket := secure.PacketListData{}
err := dec.Decode(&listPacket)
if err == io.EOF {
break
}
if err != nil {
panic(err)
}
2022-01-26 08:49:54 +10:30
fmt.Printf("%d: %s (%s) - %s\n", listPacket.Id, listPacket.Kind, humanize.Bytes(uint64(listPacket.FileSize)), listPacket.Timestamp)
numFiles++
2022-01-14 23:30:14 +10:30
}
2022-01-26 08:49:54 +10:30
fmt.Printf("total: %d files\n", numFiles)
2022-01-14 23:30:14 +10:30
conn.Close()
2022-01-16 20:35:35 +10:30
log.Debugf("done listing")
case c.receiveNum >= 0:
2022-01-17 08:28:08 +10:30
log.Debugf("receiving file %d", c.receiveNum)
err := c.connectToServer(secure.OperationTypeReceive, enc, dec)
2022-01-15 14:04:13 +10:30
if err != nil {
return fmt.Errorf("could not connect and auth: %v", err)
2022-01-15 14:04:13 +10:30
}
req := secure.PacketReceiveDataStartRequest{
2022-01-17 08:28:08 +10:30
Id: uint32(c.receiveNum),
2022-01-15 14:04:13 +10:30
}
err = enc.Encode(req)
if err != nil {
panic(err)
}
// expect a response telling us if we can go ahead
res := secure.PacketReceiveDataStartResponse{}
err = dec.Decode(&res)
if err != nil {
panic(err)
}
switch res.Status {
case secure.ReceiveDataStartResponseOK:
2022-01-15 14:04:13 +10:30
for {
res := secure.PacketReceiveDataNext{}
err = dec.Decode(&res)
if err != nil {
panic(err)
}
os.Stdout.Write(res.Data[:res.Size])
if res.Last {
break
}
}
2022-01-16 20:35:35 +10:30
log.Debugf("finished")
case secure.ReceiveDataStartResponseNotFound:
2022-01-16 20:35:35 +10:30
log.Error("ngf not found")
default:
panic("unknown status")
2022-01-15 14:04:13 +10:30
}
conn.Close()
case c.send:
2022-01-15 18:20:31 +10:30
// send mode
err := c.connectToServer(secure.OperationTypeSend, enc, dec)
if err != nil {
return fmt.Errorf("could not connect and auth: %v", err)
}
data := secure.PacketSendDataStart{
Filename: "",
TotalSize: 0,
}
err = enc.Encode(data)
if err != nil {
panic(err)
}
2022-01-13 22:20:35 +10:30
nBytes, nChunks := int64(0), int64(0)
reader := bufio.NewReader(os.Stdin)
buf := make([]byte, 0, 1024)
for {
n, err := reader.Read(buf[:cap(buf)])
2022-01-14 10:06:55 +10:30
2022-01-13 22:20:35 +10:30
buf = buf[:n]
2022-01-14 10:06:55 +10:30
2022-01-13 22:20:35 +10:30
if n == 0 {
if err == nil {
continue
}
if err == io.EOF {
break
}
log.Fatal(err)
}
nChunks++
nBytes += int64(len(buf))
2022-01-14 10:06:55 +10:30
2022-01-13 22:20:35 +10:30
send := secure.PacketSendDataNext{
Size: 5000,
Data: buf,
}
2022-01-16 20:35:35 +10:30
err = enc.Encode(send)
2022-01-13 22:20:35 +10:30
// time.Sleep(time.Second)
if err != nil {
log.Fatal(err)
}
}
2022-01-16 20:35:35 +10:30
log.Debugf("Sent %s in %d chunks", humanize.Bytes(uint64(nBytes)), nChunks)
2022-01-13 22:20:35 +10:30
conn.Close()
case c.burnNum >= 0:
log.Debugf("burning file %d", c.burnNum)
err := c.connectToServer(secure.OperationTypeBurn, enc, dec)
if err != nil {
return fmt.Errorf("could not connect and auth: %v", err)
}
req := secure.PacketBurnRequest{
Id: uint32(c.burnNum),
}
err = enc.Encode(req)
if err != nil {
panic(err)
}
// expect a response telling us if we can go ahead
res := secure.PacketBurnResponse{}
err = dec.Decode(&res)
if err != nil {
panic(err)
}
switch res.Status {
case secure.BurnResponseOK:
log.Debugf("finished")
case secure.BurnResponseNotFound:
log.Error("ngf not found")
default:
panic("unknown status")
}
conn.Close()
default:
2022-01-15 18:20:31 +10:30
panic("no client mode set")
}
return nil
}
func (c *Client) connectToServer(op secure.OperationTypeEnum, enc *gob.Encoder, dec *gob.Decoder) error {
// list mode
startPacket := secure.PacketStartRequest{
OperationType: op,
ClientName: "",
2022-01-26 10:49:23 +10:30
ProtocolVersion: ProtocolVersion,
AuthToken: c.authToken,
}
err := enc.Encode(startPacket)
if err != nil {
return fmt.Errorf("could not send start packet: %v", err)
}
// check the response is ok
response := secure.PacketStartResponse{}
err = dec.Decode(&response)
if err != nil {
return fmt.Errorf("could not receive start packet response: %v", err)
}
if response.Response == secure.PacketStartResponseEnumWrongProtocol {
log.Print("wrong protocol version")
return errors.New("protocol version mismatch")
}
if response.Response == secure.PacketStartResponseEnumBadAuthToken {
log.Print("bad authtoken")
return errors.New("bad authtoken")
}
return nil
}