Implementing upload server

This commit is contained in:
Denis-Cosmin Nutiu 2017-11-26 23:03:15 +02:00
parent 99ef1b0ea0
commit 34ab765a5c
7 changed files with 132 additions and 17 deletions

View file

@ -11,6 +11,12 @@ The server accepts the following commands:
//todo
#### The upload server
If the upload server is running, the user will be able to put files
on the **absoluteServePath**. After the file is uploaded successfully,
if the timeout is not reached, the user will get back the filename.
#### Sending commands via netcat
To grab a file the following command can be send:
@ -32,13 +38,19 @@ Sample Configuration File:
```
{
"address": "localhost",
"port": "8080",
"port": 8080,
"maxDirDepth": 30,
"absoluteServePath": "/Users/denis/Dropbox/Pictures/CuteAvatars",
"pic": {
"color": false,
"x": 0,
"y": 0
"color": true,
"x": 197,
"y": 50
},
"upload": {
"enabled": false,
"timeout": 5,
"address": "localhost",
"port": 8081
}
}
```
@ -53,7 +65,8 @@ The **config.json** file contains the following settings:
4. absoluteServePath - The path from where to serve the files.
5. pic - The X and Y max size for the pic command. A value of 0 means original size
5. pic - The X and Y max size for the pic command. A value of 0 means original size.
6. upload - Settings for the upload server.
If one of the settings are changed, the server will reload the configuration.
Except for the absoluteServePath.

View file

@ -5,14 +5,60 @@ import (
"io"
"io/ioutil"
"log"
"math/rand"
"os"
"strconv"
"strings"
"bufio"
"time"
"github.com/spf13/viper"
"github.com/zyxar/image2ascii/ascii"
)
func randSeq(n int) string {
var letters = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")
b := make([]rune, n)
for i := range b {
b[i] = letters[rand.Intn(len(letters))]
}
return string(b)
}
// UploadFile uploads a file to the server
func UploadFile(c Client) (string, error) {
input := bufio.NewScanner(c.Connection())
start := time.Now()
timeout := time.Duration(viper.GetInt("upload.timeout")) * time.Second
var filename = randSeq(10)
var _, err = os.Stat(MakePathFromStringStack(c.Stack()) + filename)
// Make sure that the filename is random.
for !os.IsNotExist(err) {
filename = randSeq(10)
_, err = os.Stat(MakePathFromStringStack(c.Stack()) + filename)
}
f, err := os.Create(MakePathFromStringStack(c.Stack()) + filename)
if err != nil {
return filename, err
}
defer f.Close()
for input.Scan() {
if time.Since(start) >= timeout {
log.Println(c.Connection().RemoteAddr().String() + " has reached timeout!")
break
}
f.WriteString(input.Text() + "\n")
}
return filename, nil
}
// SendAsciiPic sends an image as ascii text to the client.
func SendAsciiPic(c Client, path string) error {
f, err := os.Open(MakePathFromStringStack(c.Stack()) + path)

View file

@ -28,17 +28,20 @@ func loadConfigFromFile() error {
// setDefaultConfiguration will set the default configuration settings.
func setDefaultConfiguration() {
viper.SetDefault("address", "localhost")
viper.SetDefault("port", "8080")
viper.SetDefault("port", 8080)
viper.SetDefault("configPath", ConfigPath)
viper.SetDefault("maxDirDepth", 30)
viper.SetDefault("absoluteServePath", "./")
viper.SetDefault("pic.x", 0)
viper.SetDefault("pic.y", 0)
viper.SetDefault("pic.color", false)
viper.SetDefault("upload.enabled", false)
viper.SetDefault("upload.address", "localhost")
viper.SetDefault("upload.port", 8081)
}
// InitializedConfiguration initializes the configuration for the application.
func InitializedConfiguration(callback func(e fsnotify.Event)) {
// InitializeConfiguration initializes the configuration for the application.
func InitializeConfiguration() {
flag.StringVar(&ConfigPath, "config", ".", "Set the location of the config file.")
flag.Parse()
@ -46,5 +49,8 @@ func InitializedConfiguration(callback func(e fsnotify.Event)) {
loadConfigFromFile()
viper.WatchConfig()
viper.OnConfigChange(callback)
}
func ConfigChangeCallback(cb func(event fsnotify.Event)) {
viper.OnConfigChange(cb)
}

View file

@ -8,15 +8,15 @@ import (
func TestLoadConfigFromFile(t *testing.T) {
// SetDefaultConfiguration must be called BEFORE LoadConfigFromFile.
InitializedConfiguration()
InitializeConfiguration()
Address := viper.GetString("address")
if Address == "" {
t.Error("TestLoadConfigFromFile: Can't get Address!")
}
Port := viper.GetString("port")
if Port == "" {
Port := viper.GetInt("port")
if Port == 0 {
t.Error("TestLoadConfigFromFile: Can't get Port!")
}

View file

@ -88,18 +88,21 @@ func HandleConnection(client Client) {
log.Println(client.Connection().RemoteAddr(), "has disconnected.")
}
func StartFtpServer() {
config.InitializedConfiguration(func(e fsnotify.Event) {
log.Println("Configuration reloaded!")
func Init() {
config.InitializeConfiguration()
config.ConfigChangeCallback(func(event fsnotify.Event) {
log.Println("Configuration reloaded successfully!")
})
}
func StartFtpServer() {
Addr := viper.GetString("address")
Port := viper.GetString("port")
Port := viper.GetInt("port")
DirDepth := viper.GetInt("maxDirDepth")
BasePath = viper.GetString("absoluteServePath")
// Start the server
listener, err := net.Listen("tcp", Addr+":"+Port)
listener, err := net.Listen("tcp", fmt.Sprintf("%s:%d", Addr, Port))
if err != nil {
log.Fatal(err)
}
@ -122,3 +125,45 @@ func StartFtpServer() {
go HandleConnection(&client)
}
}
func StartUploadServer() {
if viper.GetBool("upload.enabled") == false {
log.Println("Uploading not enabled. To enable modify the config file and restart the server")
return
}
Addr := viper.GetString("upload.address")
Port := viper.GetInt("upload.port")
listener, err := net.Listen("tcp", fmt.Sprintf("%s:%d", Addr, Port))
if err != nil {
log.Fatal(err)
}
log.Println("Upload server running on:", Addr, "port", Port)
for {
conn, err := listener.Accept()
if err != nil {
log.Print(err)
continue
}
client := FTPClient{}
client.SetStack(MakeStringStack(1))
client.SetConnection(conn)
log.Println(conn.RemoteAddr().String() + " is uploading something.")
filename, err := UploadFile(&client)
if err == nil {
io.WriteString(conn, filename)
} else {
log.Print(conn.RemoteAddr().String())
log.Println(err)
}
log.Println(conn.RemoteAddr().String() + "'s upload finished.")
}
}

View file

@ -14,6 +14,8 @@ func TestMakePathFromStringStack(t *testing.T) {
st.Push("folder two")
st.Push("trinity")
BasePath = "./"
path := MakePathFromStringStack(st)
expected := fmt.Sprintf("%s%s/%s/%s/", BasePath, "first", "folder two", "trinity")

View file

@ -5,5 +5,8 @@ import (
)
func main() {
server.Init()
go server.StartUploadServer()
server.StartFtpServer()
}