2022-01-09 13:05:36 +10:30
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
2022-01-13 22:20:35 +10:30
|
|
|
"bufio"
|
2022-01-14 23:30:14 +10:30
|
|
|
"bytes"
|
2022-01-13 14:26:16 +10:30
|
|
|
"encoding/gob"
|
2022-01-09 13:05:36 +10:30
|
|
|
"errors"
|
|
|
|
"fmt"
|
2022-01-13 22:20:35 +10:30
|
|
|
"io"
|
2022-01-09 13:05:36 +10:30
|
|
|
"net"
|
2022-01-13 22:20:35 +10:30
|
|
|
"os"
|
2022-01-16 19:46:29 +10:30
|
|
|
"time"
|
2022-01-09 13:05:36 +10:30
|
|
|
|
2022-01-16 12:58:11 +10:30
|
|
|
log "github.com/sirupsen/logrus"
|
|
|
|
|
2022-01-15 23:10:46 +10:30
|
|
|
"github.com/dustin/go-humanize"
|
2022-01-09 13:05:36 +10:30
|
|
|
"github.com/tardisx/netgiv/secure"
|
|
|
|
)
|
|
|
|
|
|
|
|
type Client struct {
|
2022-01-17 08:28:08 +10:30
|
|
|
address string
|
|
|
|
port int
|
|
|
|
list bool
|
|
|
|
send bool
|
2025-04-25 14:21:43 +08:00
|
|
|
burnNum int
|
2022-01-17 08:28:08 +10:30
|
|
|
receiveNum int
|
|
|
|
authToken string
|
2022-01-09 13:05:36 +10:30
|
|
|
}
|
|
|
|
|
|
|
|
func (c *Client) Connect() error {
|
2022-01-13 22:20:35 +10:30
|
|
|
address := fmt.Sprintf("%s:%d", c.address, c.port)
|
|
|
|
|
2022-01-16 19:46:29 +10:30
|
|
|
d := net.Dialer{Timeout: 5 * time.Second}
|
2022-01-09 13:05:36 +10:30
|
|
|
|
2022-01-16 19:46:29 +10:30
|
|
|
conn, err := d.Dial("tcp", address)
|
2022-01-09 13:05:36 +10:30
|
|
|
if err != nil {
|
2022-01-16 19:46:29 +10:30
|
|
|
return fmt.Errorf("problem connecting to server, is it running?: %v", err)
|
2022-01-09 13:05:36 +10:30
|
|
|
}
|
|
|
|
defer conn.Close()
|
|
|
|
|
2022-01-16 20:35:35 +10:30
|
|
|
log.Debugf("established connection on %s", address)
|
2022-01-09 13:05:36 +10:30
|
|
|
|
2022-01-16 19:46:29 +10:30
|
|
|
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{}}
|
2022-01-09 13:05:36 +10:30
|
|
|
|
2022-01-13 14:26:16 +10:30
|
|
|
enc := gob.NewEncoder(&secureConnection)
|
2022-01-14 23:30:14 +10:30
|
|
|
dec := gob.NewDecoder(&secureConnection)
|
2022-01-09 13:05:36 +10:30
|
|
|
|
2025-04-25 14:21:43 +08:00
|
|
|
switch {
|
|
|
|
case c.list:
|
2022-01-16 20:35:35 +10:30
|
|
|
log.Debugf("requesting file list")
|
2022-01-16 12:58:11 +10:30
|
|
|
|
2022-01-16 19:46:29 +10:30
|
|
|
err := c.connectToServer(secure.OperationTypeList, enc, dec)
|
2022-01-14 23:30:14 +10:30
|
|
|
if err != nil {
|
2022-01-16 12:58:11 +10:30
|
|
|
return fmt.Errorf("could not connect and auth: %v", err)
|
2022-01-14 23:30:14 +10:30
|
|
|
}
|
2022-01-16 12:58:11 +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")
|
2025-04-25 14:21:43 +08:00
|
|
|
case c.receiveNum >= 0:
|
2022-01-17 08:28:08 +10:30
|
|
|
log.Debugf("receiving file %d", c.receiveNum)
|
2022-01-16 12:58:11 +10:30
|
|
|
|
2022-01-16 19:46:29 +10:30
|
|
|
err := c.connectToServer(secure.OperationTypeReceive, enc, dec)
|
2022-01-15 14:04:13 +10:30
|
|
|
if err != nil {
|
2022-01-16 12:58:11 +10:30
|
|
|
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)
|
|
|
|
}
|
|
|
|
|
2025-04-25 14:21:43 +08:00
|
|
|
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")
|
2025-04-25 14:21:43 +08:00
|
|
|
case secure.ReceiveDataStartResponseNotFound:
|
2022-01-16 20:35:35 +10:30
|
|
|
log.Error("ngf not found")
|
2025-04-25 14:21:43 +08:00
|
|
|
default:
|
2022-01-15 16:47:06 +10:30
|
|
|
panic("unknown status")
|
2022-01-15 14:04:13 +10:30
|
|
|
}
|
|
|
|
|
|
|
|
conn.Close()
|
2025-04-25 14:21:43 +08:00
|
|
|
case c.send:
|
2022-01-15 18:20:31 +10:30
|
|
|
// send mode
|
2022-01-09 13:05:36 +10:30
|
|
|
|
2022-01-16 19:46:29 +10:30
|
|
|
err := c.connectToServer(secure.OperationTypeSend, enc, dec)
|
2022-01-13 14:26:16 +10:30
|
|
|
if err != nil {
|
2022-01-16 12:58:11 +10:30
|
|
|
return fmt.Errorf("could not connect and auth: %v", err)
|
2022-01-13 14:26:16 +10:30
|
|
|
}
|
2022-01-09 13:05:36 +10:30
|
|
|
|
2022-01-14 13:07:56 +10:30
|
|
|
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
|
|
|
|
2022-01-13 14:26:16 +10:30
|
|
|
conn.Close()
|
2025-04-25 14:21:43 +08:00
|
|
|
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")
|
|
|
|
}
|
2022-01-13 14:26:16 +10:30
|
|
|
|
2025-04-25 14:21:43 +08:00
|
|
|
conn.Close()
|
|
|
|
default:
|
2022-01-15 18:20:31 +10:30
|
|
|
panic("no client mode set")
|
2022-01-09 13:05:36 +10:30
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
2022-01-16 12:58:11 +10:30
|
|
|
|
2022-01-16 19:46:29 +10:30
|
|
|
func (c *Client) connectToServer(op secure.OperationTypeEnum, enc *gob.Encoder, dec *gob.Decoder) error {
|
2022-01-16 12:58:11 +10:30
|
|
|
// list mode
|
|
|
|
startPacket := secure.PacketStartRequest{
|
|
|
|
OperationType: op,
|
|
|
|
ClientName: "",
|
2022-01-26 10:49:23 +10:30
|
|
|
ProtocolVersion: ProtocolVersion,
|
2022-01-16 19:46:29 +10:30
|
|
|
AuthToken: c.authToken,
|
2022-01-16 12:58:11 +10:30
|
|
|
}
|
|
|
|
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
|
|
|
|
}
|