parent
ac53b8c101
commit
9ef34d9294
8 changed files with 294 additions and 1 deletions
@ -0,0 +1,4 @@ |
|||||||
|
{ |
||||||
|
"Address": ":8080", |
||||||
|
"AdminSecret": "netadmin" |
||||||
|
} |
@ -0,0 +1,7 @@ |
|||||||
|
module daydev.org/shipsgs |
||||||
|
|
||||||
|
go 1.17 |
||||||
|
|
||||||
|
require github.com/xlab/closer v1.1.0 |
||||||
|
|
||||||
|
require github.com/cristalhq/aconfig v0.18.3 // indirect |
@ -0,0 +1,61 @@ |
|||||||
|
package config |
||||||
|
|
||||||
|
import ( |
||||||
|
"encoding/json" |
||||||
|
"io/ioutil" |
||||||
|
"log" |
||||||
|
"os" |
||||||
|
) |
||||||
|
|
||||||
|
const ConfigPath string = "config.json" |
||||||
|
|
||||||
|
type S_Config struct { |
||||||
|
Address string `json:"Address"` |
||||||
|
AdminSecret string `json:"AdminSecret"` |
||||||
|
} |
||||||
|
|
||||||
|
var Config S_Config |
||||||
|
|
||||||
|
func initialize() error { |
||||||
|
configExists, err := os.Open(ConfigPath) |
||||||
|
|
||||||
|
if err != nil { |
||||||
|
log.Println("management.initialize: new deployment: building config") |
||||||
|
|
||||||
|
configNew, err := os.OpenFile("config.json", os.O_CREATE|os.O_WRONLY, 0644) |
||||||
|
if err == nil { |
||||||
|
Config.Address = ":8080" |
||||||
|
Config.AdminSecret = "netadmin" |
||||||
|
|
||||||
|
configByte, err := json.MarshalIndent(Config, "", " ") |
||||||
|
if err != nil { |
||||||
|
log.Fatal("config.initialize: could not Marshall Settings: ", err) |
||||||
|
return err |
||||||
|
} |
||||||
|
configNew.Write(configByte) |
||||||
|
} else { |
||||||
|
log.Fatal("config.initialize: could not create new config.json file: ", err) |
||||||
|
return err |
||||||
|
} |
||||||
|
|
||||||
|
defer configNew.Close() |
||||||
|
} else { |
||||||
|
configByte, err := ioutil.ReadAll(configExists) |
||||||
|
if err != nil { |
||||||
|
log.Fatal("config.initialize: could not read config: ", err) |
||||||
|
return err |
||||||
|
} |
||||||
|
|
||||||
|
json.Unmarshal(configByte, &Config) |
||||||
|
|
||||||
|
defer configExists.Close() |
||||||
|
} |
||||||
|
|
||||||
|
return nil |
||||||
|
} |
||||||
|
|
||||||
|
func ReadConfig() { |
||||||
|
// If doesnt exist, write default config
|
||||||
|
|
||||||
|
initialize() |
||||||
|
} |
@ -0,0 +1,17 @@ |
|||||||
|
package player |
||||||
|
|
||||||
|
type Player struct { |
||||||
|
Name string `json:"Name"` |
||||||
|
Password string `json:"Password"` |
||||||
|
|
||||||
|
AuthString string `json:"AuthString"` |
||||||
|
|
||||||
|
Level string `json:"Level"` // hidden from user, for balancing purposes
|
||||||
|
|
||||||
|
Kills int `json:"Kills"` |
||||||
|
Killed int `json:"Killed"` |
||||||
|
|
||||||
|
Won int `json:"Won"` |
||||||
|
Lost int `json:"Lost"` |
||||||
|
WinRate int `json:"WinRate"` |
||||||
|
} |
@ -0,0 +1,38 @@ |
|||||||
|
package server |
||||||
|
|
||||||
|
import ( |
||||||
|
"context" |
||||||
|
"fmt" |
||||||
|
"log" |
||||||
|
"net/http" |
||||||
|
) |
||||||
|
|
||||||
|
func index(w http.ResponseWriter, r *http.Request) { |
||||||
|
fmt.Fprintf(w, "index") |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
func wsEndpoint(w http.ResponseWriter, r *http.Request) { |
||||||
|
fmt.Fprintf(w, "hello") |
||||||
|
} |
||||||
|
|
||||||
|
func setupRoutes() { |
||||||
|
http.HandleFunc("/", index) |
||||||
|
http.HandleFunc("/ws", wsEndpoint) |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
func SetupAndRun(port string, sighup *chan bool) { |
||||||
|
setupRoutes() |
||||||
|
|
||||||
|
srv := &http.Server{Addr: port} |
||||||
|
|
||||||
|
go func() { |
||||||
|
<-*sighup |
||||||
|
log.Println("Shutting down the webserver") |
||||||
|
srv.Shutdown(context.TODO()) |
||||||
|
}() |
||||||
|
|
||||||
|
log.Fatal(srv.ListenAndServe()) |
||||||
|
|
||||||
|
} |
@ -0,0 +1,107 @@ |
|||||||
|
package utils |
||||||
|
|
||||||
|
import ( |
||||||
|
"encoding/json" |
||||||
|
"io" |
||||||
|
"os" |
||||||
|
"runtime/debug" |
||||||
|
"sync" |
||||||
|
"time" |
||||||
|
) |
||||||
|
|
||||||
|
// Define a Level type to represent the severity level for a log entry.
|
||||||
|
type Level int8 |
||||||
|
|
||||||
|
// Initialize constants which represent a specific severity level. We use the iota
|
||||||
|
// keyword as a shortcut to
|
||||||
|
const ( |
||||||
|
LevelInfo Level = iota |
||||||
|
LevelError |
||||||
|
LevelFatal |
||||||
|
LevelOff |
||||||
|
) |
||||||
|
|
||||||
|
// assign successive integer values to the constants.
|
||||||
|
// Has the value 0. // Has the value 1. // Has the value 2. // Has the value 3.
|
||||||
|
// Return a human-friendly string for the severity level.
|
||||||
|
func (l Level) String() string { |
||||||
|
switch l { |
||||||
|
case LevelInfo: |
||||||
|
return "INFO" |
||||||
|
case LevelError: |
||||||
|
return "ERROR" |
||||||
|
case LevelFatal: |
||||||
|
return "FATAL" |
||||||
|
default: |
||||||
|
return "" |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// Define a custom Logger type. This holds the output destination that the log entries // will be written to, the minimum severity level that log entries will be written for, // plus a mutex for coordinating the writes.
|
||||||
|
type Logger struct { |
||||||
|
out io.Writer |
||||||
|
minLevel Level |
||||||
|
mu sync.Mutex |
||||||
|
} |
||||||
|
|
||||||
|
// Return a new Logger instance which writes log entries at or above a minimum severity // level to a specific output destination.
|
||||||
|
func New(out io.Writer, minLevel Level) *Logger { |
||||||
|
return &Logger{out: out, |
||||||
|
minLevel: minLevel} |
||||||
|
} |
||||||
|
|
||||||
|
// Declare some helper methods for writing log entries at the different levels. Notice // that these all accept a map as the second parameter which can contain any arbitrary // 'properties' that you want to appear in the log entry.
|
||||||
|
func (l *Logger) PrintInfo(message string, properties map[string]string) { |
||||||
|
l.print(LevelInfo, message, properties) |
||||||
|
} |
||||||
|
func (l *Logger) PrintError(err error, properties map[string]string) { |
||||||
|
l.print(LevelError, err.Error(), properties) |
||||||
|
} |
||||||
|
func (l *Logger) PrintFatal(err error, properties map[string]string) { |
||||||
|
l.print(LevelFatal, err.Error(), properties) |
||||||
|
os.Exit(1) // For entries at the FATAL level, we also terminate the application.
|
||||||
|
} |
||||||
|
|
||||||
|
// Print is an internal method for writing the log entry.
|
||||||
|
func (l *Logger) print(level Level, message string, properties map[string]string) (int, error) { // If the severity level of the log entry is below the minimum severity for the
|
||||||
|
// logger, then return with no further action.
|
||||||
|
if level < l.minLevel { |
||||||
|
return 0, nil |
||||||
|
} |
||||||
|
// Declare an anonymous struct holding the data for the log entry.
|
||||||
|
|
||||||
|
aux := struct { |
||||||
|
Level string `json:"level"` |
||||||
|
Time string `json:"time"` |
||||||
|
Message string `json:"message"` |
||||||
|
Properties map[string]string `json:"properties,omitempty"` |
||||||
|
Trace string `json:"trace,omitempty"` |
||||||
|
}{ |
||||||
|
Level: level.String(), |
||||||
|
Time: time.Now().UTC().Format(time.RFC3339), Message: message, |
||||||
|
Properties: properties, |
||||||
|
} |
||||||
|
// Include a stack trace for entries at the ERROR and FATAL levels.
|
||||||
|
if level >= LevelError { |
||||||
|
aux.Trace = string(debug.Stack()) |
||||||
|
} |
||||||
|
// Declare a line variable for holding the actual log entry text.
|
||||||
|
var line []byte |
||||||
|
// Marshal the anonymous struct to JSON and store it in the line variable. If there // was a problem creating the JSON, set the contents of the log entry to be that
|
||||||
|
// plain-text error message instead.
|
||||||
|
line, err := json.Marshal(aux) |
||||||
|
if err != nil { |
||||||
|
line = []byte(LevelError.String() + ": unable to marshal log message: " + err.Error()) |
||||||
|
} |
||||||
|
// Lock the mutex so that no two writes to the output destination cannot happen // concurrently. If we don't do this, it's possible that the text for two or more // log entries will be intermingled in the output.
|
||||||
|
l.mu.Lock() |
||||||
|
defer l.mu.Unlock() |
||||||
|
// Write the log entry followed by a newline.
|
||||||
|
return l.out.Write(append(line, '\n')) |
||||||
|
} |
||||||
|
|
||||||
|
// We also implement a Write() method on our Logger type so that it satisfies the
|
||||||
|
// io.Writer interface. This writes a log entry at the ERROR level with no additional // properties.
|
||||||
|
func (l *Logger) Write(message []byte) (n int, err error) { |
||||||
|
return l.print(LevelError, string(message), nil) |
||||||
|
} |
@ -0,0 +1,52 @@ |
|||||||
|
package main |
||||||
|
|
||||||
|
import ( |
||||||
|
"fmt" |
||||||
|
"log" |
||||||
|
"os" |
||||||
|
|
||||||
|
"daydev.org/shipsgs/internal/config" |
||||||
|
"daydev.org/shipsgs/internal/server" |
||||||
|
"daydev.org/shipsgs/internal/utils" |
||||||
|
"github.com/xlab/closer" |
||||||
|
) |
||||||
|
|
||||||
|
var Logger *utils.Logger |
||||||
|
var ch_sighup *chan bool |
||||||
|
|
||||||
|
func main() { |
||||||
|
logFile, err := os.OpenFile("runlog.log", os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644) |
||||||
|
if err != nil { |
||||||
|
fmt.Println(err) |
||||||
|
} else { |
||||||
|
log.SetOutput(logFile) |
||||||
|
} |
||||||
|
defer logFile.Close() |
||||||
|
|
||||||
|
closer.Bind(cleanup) |
||||||
|
|
||||||
|
sighup := make(chan bool) |
||||||
|
ch_sighup = &sighup |
||||||
|
|
||||||
|
//If debug - fill Stdout too - LOG to use?
|
||||||
|
//Logger = utils.New(os.Stdout, utils.LevelInfo)
|
||||||
|
|
||||||
|
config.ReadConfig() |
||||||
|
|
||||||
|
log.Println("Starting Healthy") |
||||||
|
|
||||||
|
//closer.Hold()
|
||||||
|
server.SetupAndRun(":8080", ch_sighup) |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
func cleanup() { |
||||||
|
fmt.Println("Shutting down ") |
||||||
|
|
||||||
|
*ch_sighup <- true |
||||||
|
|
||||||
|
Logger.PrintInfo("main", map[string]string{ |
||||||
|
"Info": "Closing Application Normally", |
||||||
|
}) |
||||||
|
|
||||||
|
} |
Loading…
Reference in new issue