Initial Stuff
This commit is contained in:
@@ -1,2 +1,5 @@
|
|||||||
# darkstorm-server
|
# Darkstorm Server
|
||||||
Experimenting with a Go server for personal uses
|
|
||||||
|
Experimenting with a Go server for personal uses. Combines a simple website server with a tcp forwarder.
|
||||||
|
|
||||||
|
Configure which ports go to which addresses via /etc/darkstorm-server.conf in the form `port address`.
|
||||||
|
|||||||
@@ -0,0 +1,39 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"log"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
var quitChan chan string = make(chan string)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
go tcpLinker()
|
||||||
|
go webserver()
|
||||||
|
for failure := <-quitChan; ; failure = <-quitChan {
|
||||||
|
switch failure {
|
||||||
|
case "tcp conf":
|
||||||
|
continue
|
||||||
|
case "tcp err":
|
||||||
|
go tcpLinkerRestart()
|
||||||
|
case "web arg":
|
||||||
|
continue
|
||||||
|
case "web err":
|
||||||
|
go websiteRestart()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func tcpLinkerRestart() {
|
||||||
|
log.Println("TCP linker failed. Restarting in 5 seconds...")
|
||||||
|
time.Sleep(5 * time.Second)
|
||||||
|
log.Println("Restarting tcp linker")
|
||||||
|
tcpLinker()
|
||||||
|
}
|
||||||
|
|
||||||
|
func websiteRestart() {
|
||||||
|
log.Println("Website failed. Restarting in 5 seconds...")
|
||||||
|
time.Sleep(5 * time.Second)
|
||||||
|
log.Println("Restarting website")
|
||||||
|
webserver()
|
||||||
|
}
|
||||||
@@ -0,0 +1,136 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"errors"
|
||||||
|
"io"
|
||||||
|
"log"
|
||||||
|
"net"
|
||||||
|
"os"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func tcpLinker() {
|
||||||
|
links, err := parseConf()
|
||||||
|
if links == nil {
|
||||||
|
log.Println("No values in config file or file not present (/etc/darkstorm-server.conf). tcp linker signing off")
|
||||||
|
quitChan <- "tcp conf"
|
||||||
|
return
|
||||||
|
} else if err != nil {
|
||||||
|
log.Println("Error while trying to parse config file:", err)
|
||||||
|
quitChan <- "tcp conf"
|
||||||
|
return
|
||||||
|
}
|
||||||
|
fails := make(map[int]int) //logs how many fails per 5 seconds
|
||||||
|
failChan := make(chan int, 20)
|
||||||
|
open := make(map[int]bool)
|
||||||
|
for port, addr := range links {
|
||||||
|
open[port] = true
|
||||||
|
go link(port, addr, failChan)
|
||||||
|
}
|
||||||
|
failWaiting:
|
||||||
|
for portFail := <-failChan; ; portFail = <-failChan {
|
||||||
|
if fails[portFail] == 0 {
|
||||||
|
go func() {
|
||||||
|
time.Sleep(5 * time.Second)
|
||||||
|
fails[portFail] = 0
|
||||||
|
}()
|
||||||
|
} else if fails[portFail] == 4 {
|
||||||
|
log.Println("Port", portFail, "has failed 5 time is as many seconds. Not restarting port...")
|
||||||
|
open[portFail] = false
|
||||||
|
for _, b := range open {
|
||||||
|
if b {
|
||||||
|
continue failWaiting
|
||||||
|
}
|
||||||
|
}
|
||||||
|
log.Println("All ports dead. Attempting restart...")
|
||||||
|
quitChan <- "tcp err"
|
||||||
|
return
|
||||||
|
}
|
||||||
|
fails[portFail]++
|
||||||
|
log.Println("Restarting linking for port", portFail)
|
||||||
|
go link(portFail, links[portFail], failChan)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func link(port int, addr string, failChan chan int) {
|
||||||
|
listen, err := net.Listen("tcp", ":"+strconv.Itoa(port))
|
||||||
|
defer listen.Close()
|
||||||
|
if err != nil {
|
||||||
|
log.Println("Error while trying to listen to port ", port, ":", err)
|
||||||
|
failChan <- port
|
||||||
|
return
|
||||||
|
}
|
||||||
|
for {
|
||||||
|
con, err := listen.Accept()
|
||||||
|
defer con.Close()
|
||||||
|
if err != nil {
|
||||||
|
log.Println("Error while trying to accept connection to port ", port, ":", err)
|
||||||
|
failChan <- port
|
||||||
|
return
|
||||||
|
}
|
||||||
|
ext, err := net.Dial("tcp", addr)
|
||||||
|
defer ext.Close()
|
||||||
|
if err != nil {
|
||||||
|
log.Println("Error while trying to dial", addr, ":", err)
|
||||||
|
failChan <- port
|
||||||
|
return
|
||||||
|
}
|
||||||
|
_, err = io.Copy(ext, con)
|
||||||
|
if err != nil {
|
||||||
|
log.Println("Error while trying to copy data to", addr, ":", err)
|
||||||
|
failChan <- port
|
||||||
|
return
|
||||||
|
}
|
||||||
|
_, err = io.Copy(con, ext)
|
||||||
|
if err != nil {
|
||||||
|
log.Println("Error while trying to copy data to port", port, ":", err)
|
||||||
|
failChan <- port
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseConf() (links map[int]string, err error) {
|
||||||
|
conf, err := os.Open("/etc/darkstorm-server.conf")
|
||||||
|
if os.IsNotExist(err) {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
lineNum := 0
|
||||||
|
links = make(map[int]string)
|
||||||
|
rdr := bufio.NewReader(conf)
|
||||||
|
for {
|
||||||
|
lineNum++
|
||||||
|
var origLine string
|
||||||
|
origLine, err = rdr.ReadString('\n')
|
||||||
|
if err != nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
line := strings.ReplaceAll(origLine, "\t", " ")
|
||||||
|
for strings.Contains(line, " ") {
|
||||||
|
line = strings.Replace(line, " ", " ", -1)
|
||||||
|
}
|
||||||
|
line = strings.TrimSpace(line)
|
||||||
|
if line == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
split := strings.Split(line, " ")
|
||||||
|
if len(split) != 2 {
|
||||||
|
return nil, errors.New("invalid line #" + strconv.Itoa(lineNum))
|
||||||
|
}
|
||||||
|
var i int
|
||||||
|
i, err = strconv.Atoi(split[0])
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.New("invalid line #" + strconv.Itoa(lineNum))
|
||||||
|
}
|
||||||
|
links[i] = split[1]
|
||||||
|
}
|
||||||
|
err = nil
|
||||||
|
if len(links) > 0 {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"flag"
|
||||||
|
"log"
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
|
||||||
|
func webserver() {
|
||||||
|
flag.Parse()
|
||||||
|
path := flag.Arg(0)
|
||||||
|
keyPath := flag.Arg(0)
|
||||||
|
if path == "" {
|
||||||
|
log.Println("No argument given for website file path. website signing off...")
|
||||||
|
quitChan <- "web arg"
|
||||||
|
return
|
||||||
|
} else if keyPath == "" {
|
||||||
|
log.Println("No argument given for key files. website signing off...")
|
||||||
|
quitChan <- "web arg"
|
||||||
|
return
|
||||||
|
}
|
||||||
|
http.Handle("/", http.FileServer(http.Dir(path)))
|
||||||
|
err := http.ListenAndServeTLS(":443", keyPath+"/cert.pem", keyPath+"/key.pem", nil)
|
||||||
|
log.Println("Error while serving website:", err)
|
||||||
|
quitChan <- "web err"
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user