master
1package main
2
3import (
4 "flag"
5 "github.com/BurntSushi/toml"
6 "io/ioutil"
7 "log"
8 "math/rand"
9 "net/http"
10 "os"
11 "strconv"
12 "time"
13)
14
15// SERVER_CONFIG defines default for the server
16type SERVER_CONFIG struct {
17 // LISTEN_ADDRESS defines the local address on which to listen
18 LISTEN_ADDRESS string
19 //LISTEN_PORT defines the the port on which to listen
20 LISTEN_PORT int
21 // PERMIT_BLANK_PASSWORD determines if a password should be provided with the user names
22 PERMIT_BLANK_PASSWORD bool
23 // PRIVATE_KEY defines the path to the server's private key for signing https connections
24 PRIVATE_KEY string
25 // PRIVATE_CERT defines the path to the server certificate
26 PRIVATE_CERT string
27 // USE_HTTPS determines if the server should use HTTPS
28 USE_HTTPS bool
29 // QUESTIONS contains the path to the questions directory
30 QUESTIONS string
31 // USER_TESTS stores the test results of users
32 USER_TESTS string
33 // DB_ADDRESS contains the address of the database
34 DB_ADDRESS string
35 // DB_PORT contains the port on which to connect to the database
36 DB_PORT int
37}
38
39// defaultSERVER_CONFIG is used when no SERVER_CONFIGuration file is given
40const defaultServerConfig = `
41LISTEN_ADDRESS = "127.0.0.1"
42LISTEN_PORT = 80
43PERMIT_BLANK_PASSWORD = true
44USE_HTTPS = false
45PRIVATE_KEY = "~/.ssh/question.priv"
46PRIVATE_CERT = "~/.ssh/server.crt"
47QUESTIONS = "/path/to/questions"
48USER_TESTS = "/path/to/tests"
49`
50
51// the running configuration for the server
52var serverConfig SERVER_CONFIG
53
54//loadServerConfiguration loads the configuration file
55// cfgFile : the file that contains the configuration
56func loadServerConfiguration(cfgFile string) SERVER_CONFIG {
57 var contents string
58 var config SERVER_CONFIG
59 if cfgFile == "" {
60 contents = defaultServerConfig
61 } else {
62 buffer, err := ioutil.ReadFile(cfgFile)
63 if err != nil {
64 log.Fatalf("Could not read configuration file: %+v\n", err.Error())
65 os.Exit(EXIT_CODE.FILE_IO_ERROR)
66 }
67 contents = string(buffer)
68 }
69 if _, err := toml.Decode(contents, &config); err != nil {
70 log.Fatalf("Could not parse configuration file: %+v\n", err.Error())
71 os.Exit(EXIT_CODE.BAD_CONFIG)
72 }
73 return config
74}
75
76// Listen binds the listening server and starts the listening loop
77// serverConfig : contains the configuration to be used
78func Listen(serverConfig SERVER_CONFIG) {
79 // register the server handlers
80 for _, handler := range handlers {
81 http.HandleFunc(handler.Request, handler.HandleFunction)
82 }
83 if serverConfig.USE_HTTPS {
84 // check
85 // https://gist.github.com/denji/12b3a568f092ab951456
86 log.Fatal(http.ListenAndServeTLS(
87 serverConfig.LISTEN_ADDRESS+":"+
88 strconv.Itoa(serverConfig.LISTEN_PORT),
89 serverConfig.PRIVATE_CERT, serverConfig.PRIVATE_KEY,
90 nil))
91 } else {
92 log.Fatal(http.ListenAndServe(
93 serverConfig.LISTEN_ADDRESS+":"+
94 strconv.Itoa(serverConfig.LISTEN_PORT),
95 nil))
96 }
97}
98
99func ExecuteServer() {
100 var confFile string
101 flag.StringVar(&confFile, "file", "", "define a specific configuration file to read")
102 flag.StringVar(&confFile, "f", "", "define a specific configuration file to read")
103 flag.Parse()
104 serverConfig = loadServerConfiguration(confFile)
105 log.Printf("Configuration: %+v\n", serverConfig)
106 var err error
107 DBsession, err = InitDBSession()
108 if err != nil {
109 log.Printf("Fatal error connecting to DB: %+v", err)
110 return
111 }
112 log.Printf("Loaded %d categories from %s.", len(categories), serverConfig.QUESTIONS)
113 for _, cat := range categories {
114 log.Printf("Cat: %s", cat)
115 }
116 rand.Seed(time.Now().Unix())
117 Listen(serverConfig)
118}