diff options
Diffstat (limited to 'inform/server.go')
-rw-r--r-- | inform/server.go | 92 |
1 files changed, 92 insertions, 0 deletions
diff --git a/inform/server.go b/inform/server.go new file mode 100644 index 0000000..7e33a86 --- /dev/null +++ b/inform/server.go | |||
@@ -0,0 +1,92 @@ | |||
1 | package inform | ||
2 | |||
3 | import ( | ||
4 | "fmt" | ||
5 | "log" | ||
6 | "net/http" | ||
7 | "time" | ||
8 | ) | ||
9 | |||
10 | type StateTree struct { | ||
11 | states map[string]map[int]int | ||
12 | } | ||
13 | |||
14 | func NewStateTree() *StateTree { | ||
15 | return &StateTree{make(map[string]map[int]int)} | ||
16 | } | ||
17 | |||
18 | func (t *StateTree) ensureNode(device string, port int) { | ||
19 | _, ok := t.states[device] | ||
20 | if !ok { | ||
21 | t.states[device] = make(map[int]int) | ||
22 | } | ||
23 | |||
24 | _, ok = t.states[device][port] | ||
25 | if !ok { | ||
26 | t.states[device][port] = 0 | ||
27 | } | ||
28 | } | ||
29 | |||
30 | func (t *StateTree) GetState(device string, port int) int { | ||
31 | t.ensureNode(device, port) | ||
32 | return t.states[device][port] | ||
33 | } | ||
34 | |||
35 | func (t *StateTree) SetState(device string, port, value int) { | ||
36 | t.ensureNode(device, port) | ||
37 | t.states[device][port] = value | ||
38 | } | ||
39 | |||
40 | func Log(handler http.Handler) http.Handler { | ||
41 | return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { | ||
42 | handler.ServeHTTP(w, r) | ||
43 | t := time.Now().Format("02/Jan/2006 15:04:05") | ||
44 | log.Printf("%s - - [%s] \"%s %s %s\"", r.RemoteAddr, t, r.Method, r.URL, r.Proto) | ||
45 | // Addr - - [D/M/Y H:M:S] "Method RequestURI Proto" Code Size | ||
46 | // 127.0.0.1 - - [24/Sep/2016 14:30:35] "GET / HTTP/1.1" 200 - | ||
47 | }) | ||
48 | } | ||
49 | |||
50 | type InformHandler struct { | ||
51 | Codec *Codec | ||
52 | StateTree *StateTree | ||
53 | } | ||
54 | |||
55 | func (h *InformHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { | ||
56 | if r.Method != http.MethodPost { | ||
57 | http.Error(w, "405 Method Not Allowed", http.StatusMethodNotAllowed) | ||
58 | return | ||
59 | } | ||
60 | |||
61 | if r.URL != nil && r.URL.Path != "/inform" { | ||
62 | http.Error(w, "404 Not Found", http.StatusNotFound) | ||
63 | return | ||
64 | } | ||
65 | |||
66 | msg, err := h.Codec.Unmarshal(r.Body) | ||
67 | if err != nil { | ||
68 | http.Error(w, "Bad Request", http.StatusBadRequest) | ||
69 | return | ||
70 | } | ||
71 | |||
72 | pl := NewInformWrapper() | ||
73 | copy(pl.MacAddr, msg.MacAddr) | ||
74 | pl.SetEncrypted(true) | ||
75 | |||
76 | // TODO: compare current state to tree and update | ||
77 | |||
78 | res, err := h.Codec.Marshal(pl) | ||
79 | if err != nil { | ||
80 | http.Error(w, "Server Error", 500) | ||
81 | return | ||
82 | } | ||
83 | |||
84 | fmt.Fprintf(w, "%s", res) | ||
85 | } | ||
86 | |||
87 | func NewServer(handler *InformHandler) *http.Server { | ||
88 | return &http.Server{ | ||
89 | Addr: ":6080", | ||
90 | Handler: Log(handler), | ||
91 | } | ||
92 | } | ||