aboutsummaryrefslogtreecommitdiff
path: root/inform/server.go
blob: 7e33a86d868578a272162f7de63500b4f12ccdf6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
package inform

import (
	"fmt"
	"log"
	"net/http"
	"time"
)

type StateTree struct {
	states map[string]map[int]int
}

func NewStateTree() *StateTree {
	return &StateTree{make(map[string]map[int]int)}
}

func (t *StateTree) ensureNode(device string, port int) {
	_, ok := t.states[device]
	if !ok {
		t.states[device] = make(map[int]int)
	}

	_, ok = t.states[device][port]
	if !ok {
		t.states[device][port] = 0
	}
}

func (t *StateTree) GetState(device string, port int) int {
	t.ensureNode(device, port)
	return t.states[device][port]
}

func (t *StateTree) SetState(device string, port, value int) {
	t.ensureNode(device, port)
	t.states[device][port] = value
}

func Log(handler http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		handler.ServeHTTP(w, r)
		t := time.Now().Format("02/Jan/2006 15:04:05")
		log.Printf("%s - - [%s] \"%s %s %s\"", r.RemoteAddr, t, r.Method, r.URL, r.Proto)
		// Addr - - [D/M/Y H:M:S] "Method RequestURI Proto" Code Size
		// 127.0.0.1 - - [24/Sep/2016 14:30:35] "GET / HTTP/1.1" 200 -
	})
}

type InformHandler struct {
	Codec     *Codec
	StateTree *StateTree
}

func (h *InformHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	if r.Method != http.MethodPost {
		http.Error(w, "405 Method Not Allowed", http.StatusMethodNotAllowed)
		return
	}

	if r.URL != nil && r.URL.Path != "/inform" {
		http.Error(w, "404 Not Found", http.StatusNotFound)
		return
	}

	msg, err := h.Codec.Unmarshal(r.Body)
	if err != nil {
		http.Error(w, "Bad Request", http.StatusBadRequest)
		return
	}

	pl := NewInformWrapper()
	copy(pl.MacAddr, msg.MacAddr)
	pl.SetEncrypted(true)

	// TODO: compare current state to tree and update

	res, err := h.Codec.Marshal(pl)
	if err != nil {
		http.Error(w, "Server Error", 500)
		return
	}

	fmt.Fprintf(w, "%s", res)
}

func NewServer(handler *InformHandler) *http.Server {
	return &http.Server{
		Addr:    ":6080",
		Handler: Log(handler),
	}
}