Compare commits
17 Commits
Author | SHA1 | Date | |
---|---|---|---|
6956d7f2f6 | |||
1df08bff4c | |||
07b6f6b43c | |||
cf154d93b1 | |||
80f10a3949 | |||
|
a1e3c205f9 | ||
b2c6f313bc | |||
b9f4c25f39 | |||
531abdafde | |||
9f0d81e7f1 | |||
ed9d45d343 | |||
a7b0a5d113 | |||
91be76b82e | |||
95c4a1738b | |||
607466dd65 | |||
e3e80d450b | |||
e995d436c2 |
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
.DS_Store
|
||||||
|
dist/
|
||||||
|
release/
|
50
.goreleaser.yaml
Normal file
50
.goreleaser.yaml
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
version: 2
|
||||||
|
|
||||||
|
before:
|
||||||
|
hooks:
|
||||||
|
- go mod tidy
|
||||||
|
- go test ./...
|
||||||
|
|
||||||
|
builds:
|
||||||
|
- env:
|
||||||
|
- CGO_ENABLED=0
|
||||||
|
goos:
|
||||||
|
- linux
|
||||||
|
- windows
|
||||||
|
- darwin
|
||||||
|
- freebsd
|
||||||
|
goarch:
|
||||||
|
- arm
|
||||||
|
- arm64
|
||||||
|
- amd64
|
||||||
|
goarm:
|
||||||
|
- 6
|
||||||
|
- 7
|
||||||
|
ignore:
|
||||||
|
- goos: darwin
|
||||||
|
goarch: arm
|
||||||
|
- goos: windows
|
||||||
|
goarch: arm
|
||||||
|
- goos: windows
|
||||||
|
goarch: arm64
|
||||||
|
- goos: freebsd
|
||||||
|
goarch: arm
|
||||||
|
|
||||||
|
|
||||||
|
archives:
|
||||||
|
- formats: [tar.gz]
|
||||||
|
# this name template makes the OS and Arch compatible with the results of `uname`.
|
||||||
|
name_template: >-
|
||||||
|
{{ .ProjectName }}_
|
||||||
|
{{- title .Os }}_
|
||||||
|
{{- if eq .Arch "amd64" }}x86_64
|
||||||
|
{{- else if eq .Arch "386" }}i386
|
||||||
|
{{- else }}{{ .Arch }}{{ end }}
|
||||||
|
{{- if .Arm }}v{{ .Arm }}{{ end }}
|
||||||
|
# use zip for windows archives
|
||||||
|
format_overrides:
|
||||||
|
- goos: windows
|
||||||
|
formats: [zip]
|
||||||
|
|
||||||
|
changelog:
|
||||||
|
disable: true
|
13
.vscode/settings.json
vendored
13
.vscode/settings.json
vendored
@ -1,9 +1,20 @@
|
|||||||
{
|
{
|
||||||
"cSpell.words": [
|
"cSpell.words": [
|
||||||
|
"authtoken",
|
||||||
"Debugf",
|
"Debugf",
|
||||||
"Infof",
|
"Infof",
|
||||||
"isatty",
|
"isatty",
|
||||||
"netgiv",
|
"netgiv",
|
||||||
"pflag"
|
"ngfs",
|
||||||
|
"tardisx",
|
||||||
|
"ttys"
|
||||||
|
],
|
||||||
|
"cSpell.ignoreWords": [
|
||||||
|
"logrus",
|
||||||
|
"mattn",
|
||||||
|
"pflag",
|
||||||
|
"sigchan",
|
||||||
|
"sirupsen",
|
||||||
|
"verysecretvaluehere"
|
||||||
]
|
]
|
||||||
}
|
}
|
42
CHANGELOG.md
Normal file
42
CHANGELOG.md
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
# Changelog
|
||||||
|
|
||||||
|
All notable changes to this project will be documented in this file.
|
||||||
|
|
||||||
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
||||||
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||||
|
|
||||||
|
## v1.0.0 - 2025-04-26
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
* burn mode - remove copied files from the server (by [@jsnfwlr](https://github.com/jsnfwlr))
|
||||||
|
|
||||||
|
## v0.0.5 - 2025-04-26
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
* minor refactoring
|
||||||
|
* start using goreleaser
|
||||||
|
|
||||||
|
## v0.0.4 - 2022-01-26
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
* timestamps on list output
|
||||||
|
|
||||||
|
## v0.0.3 - 2022-01-25
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
* get authtoken from the terminal if not available elsewhere
|
||||||
|
|
||||||
|
## v0.0.2 - 2022-01-17
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
* add -p to paste from a file instead of stdin
|
||||||
|
|
||||||
|
## v0.0.1 - 2022-01-16
|
||||||
|
|
||||||
|
Initial version
|
||||||
|
|
33
README.md
33
README.md
@ -18,6 +18,9 @@ pipe) modes, allowing intuitive use like:
|
|||||||
Note that since netgiv uses a persistent server, there is no need to setup both ends
|
Note that since netgiv uses a persistent server, there is no need to setup both ends
|
||||||
of the pipeline in advance (compared to netcat or similar tools).
|
of the pipeline in advance (compared to netcat or similar tools).
|
||||||
|
|
||||||
|
This also means that you could "copy" once and "paste" multiple times, on
|
||||||
|
multiple different machines.
|
||||||
|
|
||||||
All data is encrypted in flight (though not in the temporary files on the server)
|
All data is encrypted in flight (though not in the temporary files on the server)
|
||||||
Access to the server is granted by an authentication token (preshared key) of your
|
Access to the server is granted by an authentication token (preshared key) of your
|
||||||
choice.
|
choice.
|
||||||
@ -29,10 +32,6 @@ choice.
|
|||||||
Grab the appropriate version from https://github.com/tardisx/netgiv/releases, unzip
|
Grab the appropriate version from https://github.com/tardisx/netgiv/releases, unzip
|
||||||
and place the binary somewhere on your $PATH.
|
and place the binary somewhere on your $PATH.
|
||||||
|
|
||||||
Copy and paste for the trusting & lazy:
|
|
||||||
|
|
||||||
curl -L https://github.com/tardisx/netgiv/releases/download/v0.0.3/netgiv-linux-v0.0.3.zip | funzip > netgiv && chmod a+x netgiv
|
|
||||||
|
|
||||||
### Compiling from source
|
### Compiling from source
|
||||||
|
|
||||||
go install github.com/tardisx/netgiv@latest
|
go install github.com/tardisx/netgiv@latest
|
||||||
@ -63,12 +62,19 @@ set.
|
|||||||
|
|
||||||
## Running
|
## Running
|
||||||
|
|
||||||
|
|
||||||
|
### Server
|
||||||
|
|
||||||
To run a server, just run:
|
To run a server, just run:
|
||||||
|
|
||||||
netgiv --server
|
netgiv --server
|
||||||
|
|
||||||
`netgiv` will run in the foreground and log accesses to it.
|
`netgiv` will run in the foreground and log accesses to it.
|
||||||
|
|
||||||
|
### Client
|
||||||
|
|
||||||
|
#### Copy
|
||||||
|
|
||||||
On any client, run:
|
On any client, run:
|
||||||
|
|
||||||
$ echo "Hello" | netgiv
|
$ echo "Hello" | netgiv
|
||||||
@ -79,6 +85,8 @@ To check for success, try:
|
|||||||
|
|
||||||
You should see "hello" echoed on your terminal.
|
You should see "hello" echoed on your terminal.
|
||||||
|
|
||||||
|
#### List
|
||||||
|
|
||||||
To check the list of files on the server:
|
To check the list of files on the server:
|
||||||
|
|
||||||
$ netgiv -l
|
$ netgiv -l
|
||||||
@ -89,6 +97,8 @@ To check the list of files on the server:
|
|||||||
|
|
||||||
Note that netgiv tries to identify each file based on file magic heuristics.
|
Note that netgiv tries to identify each file based on file magic heuristics.
|
||||||
|
|
||||||
|
#### Paste
|
||||||
|
|
||||||
If you would like to fetch (paste) a particular file:
|
If you would like to fetch (paste) a particular file:
|
||||||
|
|
||||||
netgiv -p 3 > file.mov
|
netgiv -p 3 > file.mov
|
||||||
@ -98,6 +108,14 @@ Where '3' comes from the information provided in the `-l` output.
|
|||||||
Note that providing no `-p` option is the same as `-p X` where X is the highest
|
Note that providing no `-p` option is the same as `-p X` where X is the highest
|
||||||
numbered upload (most recent).
|
numbered upload (most recent).
|
||||||
|
|
||||||
|
#### Burn
|
||||||
|
|
||||||
|
If you would like to remove/delete (burn) a particular file:
|
||||||
|
|
||||||
|
netgiv -b 3
|
||||||
|
|
||||||
|
Where '3' comes from the information provided in the `-l` output.
|
||||||
|
|
||||||
### Notes on output
|
### Notes on output
|
||||||
|
|
||||||
Since netgiv is designed to be used in a pipeline, it does not provide any
|
Since netgiv is designed to be used in a pipeline, it does not provide any
|
||||||
@ -129,8 +147,10 @@ to the client - the server must have a config file with an authtoken specified.
|
|||||||
|
|
||||||
## Temporary file storage
|
## Temporary file storage
|
||||||
|
|
||||||
The `netgiv` server will store files in your normal system temporary dir. They will
|
The `netgiv` server will store files in your normal system temporary dir. These files
|
||||||
be deleted when the server shuts down (SIGTERM). These files are *not* encrypted.
|
are *not* encrypted. They will be deleted when the server shuts down (SIGTERM). If you
|
||||||
|
want or need to remove the files before the server shuts down, you can use the
|
||||||
|
[burn](#burn) flag.
|
||||||
|
|
||||||
## Window support
|
## Window support
|
||||||
|
|
||||||
@ -140,3 +160,4 @@ pipes. Bug reports and suggestions for workarounds are welcome.
|
|||||||
# Acknowledgements
|
# Acknowledgements
|
||||||
|
|
||||||
* thanks to tengig for the name
|
* thanks to tengig for the name
|
||||||
|
* thanks to [@jsnfwlr](https://github.com/jsnfwlr) for the burn feature
|
||||||
|
@ -1,40 +0,0 @@
|
|||||||
#!/usr/bin/env perl
|
|
||||||
|
|
||||||
use strict;
|
|
||||||
use warnings;
|
|
||||||
|
|
||||||
open my $fh, "<", "main.go" || die $!;
|
|
||||||
|
|
||||||
my $version;
|
|
||||||
while (<$fh>) {
|
|
||||||
# CurrentVersion: "v0.04"
|
|
||||||
$version = $1 if /CurrentVersion\s*=\s*"(v[\d\.]+)"/;
|
|
||||||
}
|
|
||||||
close $fh;
|
|
||||||
|
|
||||||
die "no version?" unless defined $version;
|
|
||||||
|
|
||||||
# quit if tests fail
|
|
||||||
system("go test ./...") && die "not building release with failing tests";
|
|
||||||
|
|
||||||
# so lazy
|
|
||||||
system "rm", "-rf", "release", "dist";
|
|
||||||
system "mkdir", "release";
|
|
||||||
system "mkdir", "dist";
|
|
||||||
|
|
||||||
my %build = (
|
|
||||||
win => { env => { GOOS => 'windows', GOARCH => 'amd64' }, filename => 'netgiv.exe' },
|
|
||||||
linux => { env => { GOOS => 'linux', GOARCH => 'amd64' }, filename => 'netgiv' },
|
|
||||||
mac => { env => { GOOS => 'darwin', GOARCH => 'amd64' }, filename => 'netgiv' },
|
|
||||||
);
|
|
||||||
|
|
||||||
foreach my $type (keys %build) {
|
|
||||||
mkdir "release/$type";
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach my $type (keys %build) {
|
|
||||||
local $ENV{GOOS} = $build{$type}->{env}->{GOOS};
|
|
||||||
local $ENV{GOARCH} = $build{$type}->{env}->{GOARCH};
|
|
||||||
system "go", "build", "-o", "release/$type/" . $build{$type}->{filename};
|
|
||||||
system "zip", "-j", "dist/netgiv-$type-$version.zip", ( glob "release/$type/*" );
|
|
||||||
}
|
|
51
client.go
51
client.go
@ -22,6 +22,7 @@ type Client struct {
|
|||||||
port int
|
port int
|
||||||
list bool
|
list bool
|
||||||
send bool
|
send bool
|
||||||
|
burnNum int
|
||||||
receiveNum int
|
receiveNum int
|
||||||
authToken string
|
authToken string
|
||||||
}
|
}
|
||||||
@ -50,7 +51,8 @@ func (c *Client) Connect() error {
|
|||||||
enc := gob.NewEncoder(&secureConnection)
|
enc := gob.NewEncoder(&secureConnection)
|
||||||
dec := gob.NewDecoder(&secureConnection)
|
dec := gob.NewDecoder(&secureConnection)
|
||||||
|
|
||||||
if c.list {
|
switch {
|
||||||
|
case c.list:
|
||||||
log.Debugf("requesting file list")
|
log.Debugf("requesting file list")
|
||||||
|
|
||||||
err := c.connectToServer(secure.OperationTypeList, enc, dec)
|
err := c.connectToServer(secure.OperationTypeList, enc, dec)
|
||||||
@ -75,8 +77,7 @@ func (c *Client) Connect() error {
|
|||||||
fmt.Printf("total: %d files\n", numFiles)
|
fmt.Printf("total: %d files\n", numFiles)
|
||||||
conn.Close()
|
conn.Close()
|
||||||
log.Debugf("done listing")
|
log.Debugf("done listing")
|
||||||
|
case c.receiveNum >= 0:
|
||||||
} else if c.receiveNum >= 0 {
|
|
||||||
log.Debugf("receiving file %d", c.receiveNum)
|
log.Debugf("receiving file %d", c.receiveNum)
|
||||||
|
|
||||||
err := c.connectToServer(secure.OperationTypeReceive, enc, dec)
|
err := c.connectToServer(secure.OperationTypeReceive, enc, dec)
|
||||||
@ -98,7 +99,8 @@ func (c *Client) Connect() error {
|
|||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if res.Status == secure.ReceiveDataStartResponseOK {
|
switch res.Status {
|
||||||
|
case secure.ReceiveDataStartResponseOK:
|
||||||
for {
|
for {
|
||||||
res := secure.PacketReceiveDataNext{}
|
res := secure.PacketReceiveDataNext{}
|
||||||
err = dec.Decode(&res)
|
err = dec.Decode(&res)
|
||||||
@ -111,14 +113,14 @@ func (c *Client) Connect() error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
log.Debugf("finished")
|
log.Debugf("finished")
|
||||||
} else if res.Status == secure.ReceiveDataStartResponseNotFound {
|
case secure.ReceiveDataStartResponseNotFound:
|
||||||
log.Error("ngf not found")
|
log.Error("ngf not found")
|
||||||
} else {
|
default:
|
||||||
panic("unknown status")
|
panic("unknown status")
|
||||||
}
|
}
|
||||||
|
|
||||||
conn.Close()
|
conn.Close()
|
||||||
} else if c.send {
|
case c.send:
|
||||||
// send mode
|
// send mode
|
||||||
|
|
||||||
err := c.connectToServer(secure.OperationTypeSend, enc, dec)
|
err := c.connectToServer(secure.OperationTypeSend, enc, dec)
|
||||||
@ -169,16 +171,45 @@ func (c *Client) Connect() error {
|
|||||||
log.Debugf("Sent %s in %d chunks", humanize.Bytes(uint64(nBytes)), nChunks)
|
log.Debugf("Sent %s in %d chunks", humanize.Bytes(uint64(nBytes)), nChunks)
|
||||||
|
|
||||||
conn.Close()
|
conn.Close()
|
||||||
|
case c.burnNum >= 0:
|
||||||
|
log.Debugf("burning file %d", c.burnNum)
|
||||||
|
|
||||||
} else {
|
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:
|
||||||
panic("no client mode set")
|
panic("no client mode set")
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) connectToServer(op secure.OperationTypeEnum, enc *gob.Encoder, dec *gob.Decoder) error {
|
func (c *Client) connectToServer(op secure.OperationTypeEnum, enc *gob.Encoder, dec *gob.Decoder) error {
|
||||||
|
|
||||||
// list mode
|
// list mode
|
||||||
startPacket := secure.PacketStartRequest{
|
startPacket := secure.PacketStartRequest{
|
||||||
OperationType: op,
|
OperationType: op,
|
||||||
|
85
main.go
85
main.go
@ -13,41 +13,37 @@ import (
|
|||||||
"github.com/spf13/viper"
|
"github.com/spf13/viper"
|
||||||
)
|
)
|
||||||
|
|
||||||
var CurrentVersion = "v0.0.4"
|
|
||||||
|
|
||||||
const ProtocolVersion = "1.1"
|
const ProtocolVersion = "1.1"
|
||||||
|
|
||||||
type PasteValue struct {
|
type ListValue struct {
|
||||||
PasteRequired bool
|
Required bool
|
||||||
PasteNumber uint
|
Number uint
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *PasteValue) String() string {
|
func (v *ListValue) String() string {
|
||||||
if v.PasteRequired {
|
if v.Required {
|
||||||
return fmt.Sprintf("YES: %d", v.PasteNumber)
|
return fmt.Sprintf("YES: %d", v.Number)
|
||||||
}
|
}
|
||||||
return "0"
|
return "0"
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *PasteValue) Set(s string) error {
|
func (v *ListValue) Set(s string) error {
|
||||||
v.PasteRequired = true
|
v.Required = true
|
||||||
num, err := strconv.ParseUint(s, 10, 64)
|
num, err := strconv.ParseUint(s, 10, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
v.PasteNumber = uint(num)
|
v.Number = uint(num)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *PasteValue) Type() string {
|
func (v *ListValue) Type() string {
|
||||||
return "int"
|
return "int"
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func getAuthTokenFromTerminal() string {
|
func getAuthTokenFromTerminal() string {
|
||||||
tty, err := os.OpenFile("/dev/tty", os.O_RDWR, 0755)
|
tty, err := os.OpenFile("/dev/tty", os.O_RDWR, 0o755)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("cannot open /dev/tty to read authtoken: %v", err)
|
log.Printf("cannot open /dev/tty to read authtoken: %v", err)
|
||||||
return ""
|
return ""
|
||||||
@ -59,7 +55,9 @@ func getAuthTokenFromTerminal() string {
|
|||||||
log.Printf("cannot set /dev/tty to raw mode: %v", err)
|
log.Printf("cannot set /dev/tty to raw mode: %v", err)
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
defer term.Restore(fd, oldState)
|
defer func() {
|
||||||
|
_ = term.Restore(fd, oldState)
|
||||||
|
}()
|
||||||
|
|
||||||
t := term.NewTerminal(tty, "")
|
t := term.NewTerminal(tty, "")
|
||||||
pass, err := t.ReadPassword("Enter auth token: ")
|
pass, err := t.ReadPassword("Enter auth token: ")
|
||||||
@ -71,17 +69,27 @@ func getAuthTokenFromTerminal() string {
|
|||||||
return pass
|
return pass
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
version = "dev"
|
||||||
|
commit = "none"
|
||||||
|
date = "unknown"
|
||||||
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
isServer := flag.Bool("server", false, "Run netgiv in server mode")
|
isServer := flag.Bool("server", false, "Run netgiv in server mode")
|
||||||
|
|
||||||
// client mode flags
|
// client mode flags
|
||||||
isList := flag.BoolP("list", "l", false, "Returns a list of current items on the server")
|
isList := flag.BoolP("list", "l", false, "Returns a list of current items on the server")
|
||||||
isSend := flag.BoolP("copy", "c", false, "sending stdin to netgiv server (copy)")
|
isSend := flag.BoolP("copy", "c", false, "send stdin to netgiv server (copy)")
|
||||||
|
|
||||||
pasteFlag := PasteValue{}
|
pasteFlag := ListValue{}
|
||||||
flag.VarP(&pasteFlag, "paste", "p", "receive from netgiv server to stdout (paste), with optional number (see --list)")
|
flag.VarP(&pasteFlag, "paste", "p", "receive from netgiv server to stdout (paste), with optional id (see --list)")
|
||||||
flag.Lookup("paste").NoOptDefVal = "0"
|
flag.Lookup("paste").NoOptDefVal = "0"
|
||||||
|
|
||||||
|
burnFlag := ListValue{}
|
||||||
|
flag.VarP(&burnFlag, "burn", "b", "burn (remove/delete) the item on the netgiv server, with optional id (see --list)")
|
||||||
|
flag.Lookup("burn").NoOptDefVal = "0"
|
||||||
|
|
||||||
debug := flag.Bool("debug", false, "turn on debug logging")
|
debug := flag.Bool("debug", false, "turn on debug logging")
|
||||||
flag.String("address", "", "IP address/hostname of the netgiv server")
|
flag.String("address", "", "IP address/hostname of the netgiv server")
|
||||||
|
|
||||||
@ -91,14 +99,27 @@ func main() {
|
|||||||
flag.String("authtoken", "", "Authentication token")
|
flag.String("authtoken", "", "Authentication token")
|
||||||
flag.Int("port", 0, "Port")
|
flag.Int("port", 0, "Port")
|
||||||
|
|
||||||
|
versionFlag := flag.BoolP("version", "v", false, "show version and exit")
|
||||||
|
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
|
|
||||||
receiveNum := int(pasteFlag.PasteNumber)
|
if versionFlag != nil && *versionFlag {
|
||||||
if !pasteFlag.PasteRequired {
|
fmt.Print(versionInfo(true))
|
||||||
|
os.Exit(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
receiveNum := int(pasteFlag.Number)
|
||||||
|
if !pasteFlag.Required {
|
||||||
receiveNum = -1
|
receiveNum = -1
|
||||||
}
|
}
|
||||||
|
|
||||||
viper.AddConfigPath("$HOME/.netgiv/") // call multiple times to add many search paths
|
burnNum := int(burnFlag.Number)
|
||||||
|
if !burnFlag.Required {
|
||||||
|
burnNum = -1
|
||||||
|
}
|
||||||
|
|
||||||
|
viper.AddConfigPath("$HOME/.netgiv/")
|
||||||
|
viper.AddConfigPath("$HOME/.config/netgiv/") // calling multiple times adds to search paths
|
||||||
viper.SetConfigType("yaml")
|
viper.SetConfigType("yaml")
|
||||||
|
|
||||||
viper.SetDefault("port", 4512)
|
viper.SetDefault("port", 4512)
|
||||||
@ -112,11 +133,10 @@ func main() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
flag.Parse()
|
_ = viper.BindPFlags(flag.CommandLine)
|
||||||
viper.BindPFlags(flag.CommandLine)
|
|
||||||
|
|
||||||
viper.SetEnvPrefix("NETGIV")
|
viper.SetEnvPrefix("NETGIV")
|
||||||
viper.BindEnv("authtoken")
|
_ = viper.BindEnv("authtoken")
|
||||||
|
|
||||||
// pull the various things into local variables
|
// pull the various things into local variables
|
||||||
port := viper.GetInt("port") // retrieve value from viper
|
port := viper.GetInt("port") // retrieve value from viper
|
||||||
@ -170,11 +190,12 @@ environment variable. This may be preferable in some environments.
|
|||||||
log.Fatal("an address must be provided on the command line, or configuration")
|
log.Fatal("an address must be provided on the command line, or configuration")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
log.Debugf("protocol version: %s", ProtocolVersion)
|
||||||
if *isServer {
|
if *isServer {
|
||||||
s := Server{port: port, authToken: authtoken}
|
s := Server{port: port, authToken: authtoken}
|
||||||
s.Run()
|
s.Run()
|
||||||
} else {
|
} else {
|
||||||
if !*isList && !*isSend && receiveNum == -1 {
|
if !*isList && !*isSend && burnNum == -1 && receiveNum == -1 {
|
||||||
// try to work out the intent based on whether or not stdin/stdout
|
// try to work out the intent based on whether or not stdin/stdout
|
||||||
// are ttys
|
// are ttys
|
||||||
stdinTTY := isatty.IsTerminal(os.Stdin.Fd())
|
stdinTTY := isatty.IsTerminal(os.Stdin.Fd())
|
||||||
@ -193,10 +214,20 @@ environment variable. This may be preferable in some environments.
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
c := Client{port: port, address: address, list: *isList, send: *isSend, receiveNum: receiveNum, authToken: authtoken}
|
c := Client{port: port, address: address, list: *isList, send: *isSend, burnNum: burnNum, receiveNum: receiveNum, authToken: authtoken}
|
||||||
err := c.Connect()
|
err := c.Connect()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Print(err)
|
fmt.Print(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func versionInfo(verbose bool) string {
|
||||||
|
out := ""
|
||||||
|
out += fmt.Sprintf("netgiv %s, built at %s\n", version, date)
|
||||||
|
if verbose {
|
||||||
|
out += fmt.Sprintf("commit: %s\n", commit)
|
||||||
|
out += fmt.Sprintf("http://github.com/tardisx/netgiv\n")
|
||||||
|
}
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
@ -129,7 +129,7 @@ func (s *SecureConnection) Write(p []byte) (int, error) {
|
|||||||
var nonce [24]byte
|
var nonce [24]byte
|
||||||
|
|
||||||
// Create a new nonce for each message sent
|
// Create a new nonce for each message sent
|
||||||
rand.Read(nonce[:])
|
_, _ = rand.Read(nonce[:])
|
||||||
|
|
||||||
encryptedMessage := box.SealAfterPrecomputation(nil, p, &nonce, s.SharedKey)
|
encryptedMessage := box.SealAfterPrecomputation(nil, p, &nonce, s.SharedKey)
|
||||||
sm := SecureMessage{Msg: encryptedMessage, Nonce: nonce}
|
sm := SecureMessage{Msg: encryptedMessage, Nonce: nonce}
|
||||||
@ -145,10 +145,10 @@ func Handshake(conn *net.TCPConn) *[32]byte {
|
|||||||
|
|
||||||
publicKey, privateKey, _ := box.GenerateKey(rand.Reader)
|
publicKey, privateKey, _ := box.GenerateKey(rand.Reader)
|
||||||
|
|
||||||
conn.Write(publicKey[:])
|
_, _ = conn.Write(publicKey[:])
|
||||||
|
|
||||||
peerKeyArray := make([]byte, 32)
|
peerKeyArray := make([]byte, 32)
|
||||||
conn.Read(peerKeyArray)
|
_, _ = conn.Read(peerKeyArray)
|
||||||
copy(peerKey[:], peerKeyArray)
|
copy(peerKey[:], peerKeyArray)
|
||||||
|
|
||||||
box.Precompute(&sharedKey, &peerKey, privateKey)
|
box.Precompute(&sharedKey, &peerKey, privateKey)
|
||||||
@ -162,10 +162,11 @@ const (
|
|||||||
OperationTypeSend OperationTypeEnum = iota
|
OperationTypeSend OperationTypeEnum = iota
|
||||||
OperationTypeList
|
OperationTypeList
|
||||||
OperationTypeReceive
|
OperationTypeReceive
|
||||||
|
OperationTypeBurn
|
||||||
)
|
)
|
||||||
|
|
||||||
// PacketStartRequest is sent from the client to the server at the beginning
|
// PacketStartRequest is sent from the client to the server at the beginning
|
||||||
// to authenticate and annonce the requested particular operation
|
// to authenticate and announce the requested particular operation
|
||||||
type PacketStartRequest struct {
|
type PacketStartRequest struct {
|
||||||
OperationType OperationTypeEnum
|
OperationType OperationTypeEnum
|
||||||
ClientName string
|
ClientName string
|
||||||
@ -233,3 +234,20 @@ type PacketListData struct {
|
|||||||
Timestamp time.Time
|
Timestamp time.Time
|
||||||
Kind string
|
Kind string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type PacketBurnRequest struct {
|
||||||
|
Id uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
type PacketBurnResponse struct {
|
||||||
|
Status PacketBurnResponseEnum
|
||||||
|
}
|
||||||
|
|
||||||
|
type PacketBurnResponseEnum byte
|
||||||
|
|
||||||
|
const (
|
||||||
|
// File has been deleted
|
||||||
|
BurnResponseOK PacketBurnResponseEnum = iota
|
||||||
|
// No such file by index
|
||||||
|
BurnResponseNotFound
|
||||||
|
)
|
||||||
|
@ -13,7 +13,8 @@ func TestBasic(t *testing.T) {
|
|||||||
|
|
||||||
srcSecConn := SecureConnection{
|
srcSecConn := SecureConnection{
|
||||||
Conn: srcConn,
|
Conn: srcConn,
|
||||||
SharedKey: &[32]byte{0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7,
|
SharedKey: &[32]byte{
|
||||||
|
0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7,
|
||||||
0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7,
|
0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7,
|
||||||
0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7,
|
0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7,
|
||||||
0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7,
|
0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7,
|
||||||
@ -23,7 +24,8 @@ func TestBasic(t *testing.T) {
|
|||||||
|
|
||||||
dstSecConn := SecureConnection{
|
dstSecConn := SecureConnection{
|
||||||
Conn: dstConn,
|
Conn: dstConn,
|
||||||
SharedKey: &[32]byte{0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7,
|
SharedKey: &[32]byte{
|
||||||
|
0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7,
|
||||||
0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7,
|
0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7,
|
||||||
0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7,
|
0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7,
|
||||||
0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7,
|
0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7,
|
||||||
@ -45,7 +47,7 @@ func TestBasic(t *testing.T) {
|
|||||||
for _, b := range testData {
|
for _, b := range testData {
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
srcSecConn.Write(b)
|
_, _ = srcSecConn.Write(b)
|
||||||
}()
|
}()
|
||||||
|
|
||||||
time.Sleep(time.Second)
|
time.Sleep(time.Second)
|
||||||
@ -70,7 +72,8 @@ func TestPacketBasic(t *testing.T) {
|
|||||||
|
|
||||||
srcSecConn := SecureConnection{
|
srcSecConn := SecureConnection{
|
||||||
Conn: srcConn,
|
Conn: srcConn,
|
||||||
SharedKey: &[32]byte{0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7,
|
SharedKey: &[32]byte{
|
||||||
|
0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7,
|
||||||
0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7,
|
0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7,
|
||||||
0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7,
|
0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7,
|
||||||
0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7,
|
0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7,
|
||||||
@ -80,7 +83,8 @@ func TestPacketBasic(t *testing.T) {
|
|||||||
|
|
||||||
dstSecConn := SecureConnection{
|
dstSecConn := SecureConnection{
|
||||||
Conn: dstConn,
|
Conn: dstConn,
|
||||||
SharedKey: &[32]byte{0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7,
|
SharedKey: &[32]byte{
|
||||||
|
0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7,
|
||||||
0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7,
|
0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7,
|
||||||
0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7,
|
0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7,
|
||||||
0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7,
|
0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7,
|
||||||
@ -97,10 +101,12 @@ func TestPacketBasic(t *testing.T) {
|
|||||||
ProtocolVersion: "1.1",
|
ProtocolVersion: "1.1",
|
||||||
AuthToken: "abc123",
|
AuthToken: "abc123",
|
||||||
}
|
}
|
||||||
go func() { enc.Encode(packet) }()
|
go func() {
|
||||||
|
_ = enc.Encode(packet)
|
||||||
|
}()
|
||||||
|
|
||||||
recvPacket := PacketStartRequest{}
|
recvPacket := PacketStartRequest{}
|
||||||
dec.Decode(&recvPacket)
|
_ = dec.Decode(&recvPacket)
|
||||||
|
|
||||||
if recvPacket.OperationType != OperationTypeReceive {
|
if recvPacket.OperationType != OperationTypeReceive {
|
||||||
t.Error("bad OperationType")
|
t.Error("bad OperationType")
|
||||||
@ -117,7 +123,6 @@ func TestPacketBasic(t *testing.T) {
|
|||||||
if recvPacket.ProtocolVersion != "1.1" {
|
if recvPacket.ProtocolVersion != "1.1" {
|
||||||
t.Error("bad ProtocolVersion")
|
t.Error("bad ProtocolVersion")
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func BenchmarkPPS(b *testing.B) {
|
func BenchmarkPPS(b *testing.B) {
|
||||||
@ -125,7 +130,8 @@ func BenchmarkPPS(b *testing.B) {
|
|||||||
|
|
||||||
srcSecConn := SecureConnection{
|
srcSecConn := SecureConnection{
|
||||||
Conn: srcConn,
|
Conn: srcConn,
|
||||||
SharedKey: &[32]byte{0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7,
|
SharedKey: &[32]byte{
|
||||||
|
0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7,
|
||||||
0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7,
|
0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7,
|
||||||
0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7,
|
0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7,
|
||||||
0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7,
|
0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7,
|
||||||
@ -135,7 +141,8 @@ func BenchmarkPPS(b *testing.B) {
|
|||||||
|
|
||||||
dstSecConn := SecureConnection{
|
dstSecConn := SecureConnection{
|
||||||
Conn: dstConn,
|
Conn: dstConn,
|
||||||
SharedKey: &[32]byte{0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7,
|
SharedKey: &[32]byte{
|
||||||
|
0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7,
|
||||||
0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7,
|
0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7,
|
||||||
0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7,
|
0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7,
|
||||||
0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7,
|
0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7,
|
||||||
@ -153,12 +160,11 @@ func BenchmarkPPS(b *testing.B) {
|
|||||||
for i := 0; i < b.N; i++ {
|
for i := 0; i < b.N; i++ {
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
srcSecConn.Write(testdata)
|
_, _ = srcSecConn.Write(testdata)
|
||||||
}()
|
}()
|
||||||
|
|
||||||
out := make([]byte, 16384)
|
out := make([]byte, 16384)
|
||||||
n, err := dstSecConn.Read(out)
|
n, err := dstSecConn.Read(out)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
b.Errorf("got error %v", err)
|
b.Errorf("got error %v", err)
|
||||||
}
|
}
|
||||||
@ -169,5 +175,4 @@ func BenchmarkPPS(b *testing.B) {
|
|||||||
b.Errorf("%v not equal to %v", out[:n], testdata)
|
b.Errorf("%v not equal to %v", out[:n], testdata)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
108
server.go
108
server.go
@ -34,10 +34,15 @@ type NGF struct {
|
|||||||
Timestamp time.Time
|
Timestamp time.Time
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (ngf NGF) String() string {
|
||||||
|
return fmt.Sprintf("id: %d, stored: %s, size: %d, kind: %s", ngf.Id, ngf.StorePath, ngf.Size, ngf.Kind)
|
||||||
|
}
|
||||||
|
|
||||||
var ngfs []NGF
|
var ngfs []NGF
|
||||||
var globalId uint32
|
var globalId uint32
|
||||||
|
|
||||||
func (s *Server) Run() {
|
func (s *Server) Run() {
|
||||||
|
log.Info(versionInfo(false))
|
||||||
log.Infof("starting server on :%d", s.port)
|
log.Infof("starting server on :%d", s.port)
|
||||||
address := fmt.Sprintf(":%d", s.port)
|
address := fmt.Sprintf(":%d", s.port)
|
||||||
networkAddress, _ := net.ResolveTCPAddr("tcp", address)
|
networkAddress, _ := net.ResolveTCPAddr("tcp", address)
|
||||||
@ -58,7 +63,7 @@ func (s *Server) Run() {
|
|||||||
log.Printf("removing file: %s", ngf.StorePath)
|
log.Printf("removing file: %s", ngf.StorePath)
|
||||||
err := os.Remove(ngf.StorePath)
|
err := os.Remove(ngf.StorePath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("could not remove %s: %v", ngf.StorePath, err)
|
log.Errorf("could not remove %s: %v", ngf.StorePath, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
os.Exit(0)
|
os.Exit(0)
|
||||||
@ -68,7 +73,6 @@ func (s *Server) Run() {
|
|||||||
|
|
||||||
for {
|
for {
|
||||||
conn, err := listener.AcceptTCP()
|
conn, err := listener.AcceptTCP()
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Print(err)
|
fmt.Print(err)
|
||||||
}
|
}
|
||||||
@ -80,7 +84,7 @@ func (s *Server) Run() {
|
|||||||
func (s *Server) handleConnection(conn *net.TCPConn) {
|
func (s *Server) handleConnection(conn *net.TCPConn) {
|
||||||
defer conn.Close()
|
defer conn.Close()
|
||||||
|
|
||||||
conn.SetDeadline(time.Now().Add(time.Second * 5))
|
_ = conn.SetDeadline(time.Now().Add(time.Second * 5))
|
||||||
|
|
||||||
sharedKey := secure.Handshake(conn)
|
sharedKey := secure.Handshake(conn)
|
||||||
secureConnection := secure.SecureConnection{Conn: conn, SharedKey: sharedKey, Buffer: &bytes.Buffer{}}
|
secureConnection := secure.SecureConnection{Conn: conn, SharedKey: sharedKey, Buffer: &bytes.Buffer{}}
|
||||||
@ -111,24 +115,25 @@ func (s *Server) handleConnection(conn *net.TCPConn) {
|
|||||||
if start.ProtocolVersion != ProtocolVersion {
|
if start.ProtocolVersion != ProtocolVersion {
|
||||||
log.Errorf("bad protocol version")
|
log.Errorf("bad protocol version")
|
||||||
startResponse.Response = secure.PacketStartResponseEnumWrongProtocol
|
startResponse.Response = secure.PacketStartResponseEnumWrongProtocol
|
||||||
enc.Encode(startResponse)
|
_ = enc.Encode(startResponse)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if start.AuthToken != s.authToken {
|
if start.AuthToken != s.authToken {
|
||||||
log.Errorf("bad authtoken")
|
log.Errorf("bad authtoken")
|
||||||
startResponse.Response = secure.PacketStartResponseEnumBadAuthToken
|
startResponse.Response = secure.PacketStartResponseEnumBadAuthToken
|
||||||
enc.Encode(startResponse)
|
_ = enc.Encode(startResponse)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// otherwise we are good to continue, tell the client that
|
// otherwise we are good to continue, tell the client that
|
||||||
startResponse.Response = secure.PacketStartResponseEnumOK
|
startResponse.Response = secure.PacketStartResponseEnumOK
|
||||||
enc.Encode(startResponse)
|
_ = enc.Encode(startResponse)
|
||||||
|
|
||||||
conn.SetDeadline(time.Now().Add(time.Second * 5))
|
_ = conn.SetDeadline(time.Now().Add(time.Second * 5))
|
||||||
|
|
||||||
if start.OperationType == secure.OperationTypeSend {
|
switch start.OperationType {
|
||||||
|
case secure.OperationTypeSend:
|
||||||
log.Debugf("file incoming")
|
log.Debugf("file incoming")
|
||||||
|
|
||||||
sendStart := secure.PacketSendDataStart{}
|
sendStart := secure.PacketSendDataStart{}
|
||||||
@ -160,7 +165,7 @@ func (s *Server) handleConnection(conn *net.TCPConn) {
|
|||||||
sendData := secure.PacketSendDataNext{}
|
sendData := secure.PacketSendDataNext{}
|
||||||
determinedKind := false
|
determinedKind := false
|
||||||
for {
|
for {
|
||||||
conn.SetDeadline(time.Now().Add(time.Second * 5))
|
_ = conn.SetDeadline(time.Now().Add(time.Second * 5))
|
||||||
err = dec.Decode(&sendData)
|
err = dec.Decode(&sendData)
|
||||||
if err == io.EOF {
|
if err == io.EOF {
|
||||||
break
|
break
|
||||||
@ -190,7 +195,7 @@ func (s *Server) handleConnection(conn *net.TCPConn) {
|
|||||||
determinedKind = true
|
determinedKind = true
|
||||||
}
|
}
|
||||||
|
|
||||||
file.Write(sendData.Data)
|
_, _ = file.Write(sendData.Data)
|
||||||
}
|
}
|
||||||
info, err := file.Stat()
|
info, err := file.Stat()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -204,13 +209,13 @@ func (s *Server) handleConnection(conn *net.TCPConn) {
|
|||||||
log.Printf("done receiving file: %v", ngf)
|
log.Printf("done receiving file: %v", ngf)
|
||||||
|
|
||||||
return
|
return
|
||||||
} else if start.OperationType == secure.OperationTypeReceive {
|
case secure.OperationTypeReceive:
|
||||||
log.Printf("client requesting file receive")
|
log.Printf("client requesting file receive")
|
||||||
// wait for them to send the request
|
// wait for them to send the request
|
||||||
req := secure.PacketReceiveDataStartRequest{}
|
req := secure.PacketReceiveDataStartRequest{}
|
||||||
err := dec.Decode(&req)
|
err := dec.Decode(&req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("error expecting PacketReceiveDataStartRequest: %v", err)
|
log.Errorf("error expecting PacketReceiveDataStartRequest: %v", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -242,7 +247,7 @@ func (s *Server) handleConnection(conn *net.TCPConn) {
|
|||||||
}
|
}
|
||||||
err = enc.Encode(res)
|
err = enc.Encode(res)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("could not send NotFound: %v", err)
|
log.Errorf("could not send NotFound: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
@ -297,8 +302,7 @@ func (s *Server) handleConnection(conn *net.TCPConn) {
|
|||||||
}
|
}
|
||||||
log.Printf("sending done")
|
log.Printf("sending done")
|
||||||
return
|
return
|
||||||
|
case secure.OperationTypeList:
|
||||||
} else if start.OperationType == secure.OperationTypeList {
|
|
||||||
log.Debugf("client requesting file list")
|
log.Debugf("client requesting file list")
|
||||||
|
|
||||||
for _, ngf := range ngfs {
|
for _, ngf := range ngfs {
|
||||||
@ -308,15 +312,83 @@ func (s *Server) handleConnection(conn *net.TCPConn) {
|
|||||||
p.Id = ngf.Id
|
p.Id = ngf.Id
|
||||||
p.Filename = ngf.Filename
|
p.Filename = ngf.Filename
|
||||||
p.Timestamp = ngf.Timestamp
|
p.Timestamp = ngf.Timestamp
|
||||||
enc.Encode(p)
|
_ = enc.Encode(p)
|
||||||
}
|
}
|
||||||
log.Debugf("done sending list, closing connection")
|
log.Debugf("done sending list, closing connection")
|
||||||
|
|
||||||
return
|
return
|
||||||
|
case secure.OperationTypeBurn:
|
||||||
|
log.Debugf("client requesting burn")
|
||||||
|
// wait for them to send the request
|
||||||
|
req := secure.PacketBurnRequest{}
|
||||||
|
err := dec.Decode(&req)
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("error expecting PacketBurnRequest: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
} else {
|
log.Debugf("The client asked for %v to be burned", req)
|
||||||
|
|
||||||
|
// do we have this ngf by id?
|
||||||
|
var requestedNGF NGF
|
||||||
|
|
||||||
|
if len(ngfs) > 0 {
|
||||||
|
if req.Id == 0 {
|
||||||
|
// they want the most recent one
|
||||||
|
requestedNGF = ngfs[len(ngfs)-1]
|
||||||
|
} else {
|
||||||
|
for _, ngf := range ngfs {
|
||||||
|
if ngf.Id == req.Id {
|
||||||
|
requestedNGF = ngf
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Debugf("going to burn %v", requestedNGF)
|
||||||
|
|
||||||
|
if requestedNGF.Id == 0 {
|
||||||
|
// not found
|
||||||
|
log.Errorf("user requested burning %d, not found", req.Id)
|
||||||
|
res := secure.PacketBurnResponse{
|
||||||
|
Status: secure.BurnResponseNotFound,
|
||||||
|
}
|
||||||
|
err = enc.Encode(res)
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("could not send NotFound: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// remove the file
|
||||||
|
err = os.Remove(requestedNGF.StorePath)
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("could not remove file %s: %v", requestedNGF.StorePath, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// remove the ngf from the list
|
||||||
|
for i, ngf := range ngfs {
|
||||||
|
if ngf.Id == requestedNGF.Id {
|
||||||
|
ngfs = append(ngfs[:i], ngfs[i+1:]...)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
res := secure.PacketBurnResponse{
|
||||||
|
Status: secure.BurnResponseOK,
|
||||||
|
}
|
||||||
|
err = enc.Encode(res)
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("error sending PacketBurnResponse: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Printf("burn complete")
|
||||||
|
return
|
||||||
|
default:
|
||||||
log.Errorf("bad operation")
|
log.Errorf("bad operation")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user