From d90eab464d3b7ea309ded6342497a41af68c5743 Mon Sep 17 00:00:00 2001 From: Justin Hawkins Date: Sat, 15 Jan 2022 14:04:13 +1030 Subject: [PATCH] Basics of receiving files --- client.go | 52 +++++++++++++++++++++++++++++++++++++++++- main.go | 9 ++++---- secure/secure.go | 39 ++++++++++++++++++++++++++++---- server.go | 59 ++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 149 insertions(+), 10 deletions(-) diff --git a/client.go b/client.go index 82db5fa..81f72c9 100644 --- a/client.go +++ b/client.go @@ -18,6 +18,7 @@ type Client struct { address string port int list bool + receive bool } func (c *Client) Connect() error { @@ -31,7 +32,7 @@ func (c *Client) Connect() error { } defer conn.Close() - fmt.Printf("Connection on %s\n", address) + log.Printf("Connection on %s\n", address) sharedKey := secure.Handshake(conn) secureConnection := secure.SecureConnection{Conn: conn, SharedKey: sharedKey, Buffer: &bytes.Buffer{}} @@ -67,6 +68,55 @@ func (c *Client) Connect() error { conn.Close() log.Printf("done listing") + } else if c.receive { + log.Printf("receiving a file") + // list mode + msg := secure.PacketStart{ + OperationType: secure.OperationTypeReceive, + ClientName: "Justin Hawkins", + ProtocolVersion: "v1.0", + AuthToken: "abc123", + } + err := enc.Encode(msg) + if err != nil { + panic(err) + } + + req := secure.PacketReceiveDataStartRequest{ + Id: 234, + } + 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) + } + + log.Printf("server said %v", res) + if res.Status == secure.ReceiveDataStartResponseOK { + for { + res := secure.PacketReceiveDataNext{} + err = dec.Decode(&res) + if err != nil { + panic(err) + } + // log.Printf("got %d bytes, last is %t", res.Size, res.Last) + // print(res.Data) + os.Stdout.Write(res.Data[:res.Size]) + if res.Last { + break + } + } + log.Printf("finished") + } else { + panic("don't handle this yet") + } + + conn.Close() } else { // must be send mode diff --git a/main.go b/main.go index bc5b171..658afe9 100644 --- a/main.go +++ b/main.go @@ -8,20 +8,21 @@ import ( func main() { log.SetFlags(log.Lshortfile) - port := flag.Int("p", 9000, "Port to run server/client on.") + port := flag.Int("port", 9000, "Port to run server/client on.") addr := flag.String("a", "61.245.149.58", "address to connect to.") isServer := flag.Bool("s", false, "Set if running the server.") isList := flag.Bool("l", false, "Set if requesting a list") + isReceive := flag.Bool("p", false, "Set if receiving a file") flag.Parse() if *isServer { - fmt.Printf("Server running on %d\n", *port) + log.Printf("Server running on %d\n", *port) s := Server{port: *port} s.Run() } else { - fmt.Printf("Client running on %d\n", *port) - c := Client{port: *port, address: *addr, list: *isList} + log.Printf("Client running on %d\n", *port) + c := Client{port: *port, address: *addr, list: *isList, receive: *isReceive} err := c.Connect() if err != nil { fmt.Print(err) diff --git a/secure/secure.go b/secure/secure.go index 6986765..d7a9352 100644 --- a/secure/secure.go +++ b/secure/secure.go @@ -178,6 +178,7 @@ type OperationTypeEnum byte const ( OperationTypeSend OperationTypeEnum = iota OperationTypeList + OperationTypeReceive ) // PacketStart is sent from the client to the server at the beginning @@ -193,6 +194,39 @@ type PacketSendDataStart struct { Filename string TotalSize uint32 } +type PacketSendDataNext struct { + Size uint16 + Data []byte +} + +// PacketReceiveDataStart is sent from the server to the client when +// the client asks for a file to be sent to them. +type PacketReceiveDataStartRequest struct { + Id uint32 +} + +type PacketReceiveDataStartResponseEnum byte + +const ( + // File transfer can begin + ReceiveDataStartResponseOK PacketReceiveDataStartResponseEnum = iota + // No such file by index + ReceiveDataStartResponseNotFound +) + +// PacketReceiveDataStartResponse is the response to the above packet. +type PacketReceiveDataStartResponse struct { + Status PacketReceiveDataStartResponseEnum + Filename string + Kind string + TotalSize uint32 +} + +type PacketReceiveDataNext struct { + Size uint16 + Data []byte + Last bool +} type PacketListData struct { Id uint32 @@ -200,8 +234,3 @@ type PacketListData struct { FileSize uint32 Kind string } - -type PacketSendDataNext struct { - Size uint16 - Data []byte -} diff --git a/server.go b/server.go index a7445e8..feb027e 100644 --- a/server.go +++ b/server.go @@ -147,6 +147,65 @@ func handleConnection(conn *net.TCPConn) { log.Printf("done receiving file") return + } else if start.OperationType == secure.OperationTypeReceive { + log.Printf("client requesting file receive") + // wait for them to send the request + req := secure.PacketReceiveDataStartRequest{} + err := dec.Decode(&req) + if err != nil { + log.Printf("error expecting PacketReceiveDataStartRequest: %v", err) + return + } + + log.Printf("The asked for %v", req) + res := secure.PacketReceiveDataStartResponse{ + Status: secure.ReceiveDataStartResponseOK, + Filename: "abcdef", + Kind: "", + TotalSize: 12340, + } + err = enc.Encode(res) + if err != nil { + log.Printf("error sending PacketReceiveDataStartResponse: %v", err) + return + } + + log.Printf("%#v", ngfs) + + // now just start sending the file in batches + buf := make([]byte, 2048) + filename := ngfs[0].StorePath + log.Printf("opening %s", filename) + f, err := os.Open(filename) + for { + n, err := f.Read(buf) + eof := false + + if err != nil && err != io.EOF { + log.Printf("error reading data: %v", err) + break + } + if err == io.EOF { + eof = true + } + + chunk := secure.PacketReceiveDataNext{ + Size: uint16(n), + Data: buf[:n], + Last: eof, + } + err = enc.Encode(chunk) + if err != nil { + log.Printf("error sending chunk: %v", err) + } + + if eof { + break + } + } + log.Printf("sending done") + return + } else if start.OperationType == secure.OperationTypeList { log.Printf("client requesting file list")