@@ -6,27 +6,32 @@ import (
6
6
"net"
7
7
"os"
8
8
"io"
9
+ "io/ioutil"
9
10
"strings"
10
11
"strconv"
11
12
"sort"
13
+ "time"
12
14
)
13
-
15
+ var lastEntries []string
16
+ func init (){
17
+
18
+ }
14
19
/* A Simple function to verify error */
15
20
func CheckError (err error ) {
16
21
if err != nil {
17
22
fmt .Println ("Error: " , err )
18
23
os .Exit (0 )
19
24
}
25
+
20
26
}
21
27
22
- func readConfig (path string ) (m map [string ]int ) {
28
+ func readConfig (path string ) (m map [string ]int , tableHeader string ) {
23
29
//Open File
24
30
file , err := os .Open (path )
25
31
CheckError (err )
26
32
defer file .Close ()
27
-
28
33
m = make (map [string ]int )
29
-
34
+ s := make ([] string , 4 )
30
35
//Start Reading..
31
36
reader := bufio .NewReader (file )
32
37
for {
@@ -36,10 +41,19 @@ func readConfig (path string) (m map[string]int) {
36
41
}
37
42
CheckError (err )
38
43
key := strings .TrimSpace (line )
44
+ s = append (s , key )
39
45
m [key ] = 0
40
46
}
47
+ //do some work on the html
48
+ sort .Strings (s )
49
+ tableHeader = "<tr> <th>Zeitstempel</th>"
50
+ for i := range s {
51
+ if (len (s [i ])> 0 ){
52
+ tableHeader += "<th>" + s [i ]+ "</th>"
53
+ }
54
+ }
55
+ tableHeader += "</tr>"
41
56
return
42
-
43
57
}
44
58
45
59
func msgDigest (c chan string , m map [string ]int ) {
@@ -51,27 +65,73 @@ func msgDigest(c chan string, m map[string]int) {
51
65
key := msgStr [0 ]
52
66
value , err := strconv .Atoi (msgStr [1 ])
53
67
if (err != nil ) {
54
- fmt .Println ("recieved bad msg 0 " )
68
+ fmt .Println ("received bad msg" )
55
69
fmt .Println (msg )
56
70
continue
57
71
}
58
72
59
73
if _ , ok := m [key ]; ok {
60
74
m [key ] = value
61
- printStock (m )
75
+ genHTMLBody (m )
62
76
} else {
63
- fmt .Println ("recieved bad msg" )
77
+ fmt .Println ("received bad msg" )
64
78
fmt .Println (msgStr )
65
79
continue
66
80
}
67
81
} else {
68
- fmt .Println ("recieved bad msg" )
82
+ fmt .Println ("received bad msg" )
69
83
fmt .Println (msgStr )
70
84
continue
71
85
}
72
86
}
73
87
}
74
88
89
+ func startUdpServer (fridgeStock map [string ]int ){
90
+ port := ":8080"
91
+ fmt .Println ("Preparing UDP-Server..." )
92
+ // Lets prepare an address at any address at port
93
+ ServerAddr ,err := net .ResolveUDPAddr ("udp" , port )
94
+ CheckError (err )
95
+
96
+ fmt .Println ("Listening on " , GetLocalIP (), port )
97
+ /* Now listen at selected port */
98
+ ServerConn , err := net .ListenUDP ("udp" , ServerAddr )
99
+ CheckError (err )
100
+ defer ServerConn .Close ()
101
+
102
+ messages := make (chan string )
103
+ go msgDigest (messages ,fridgeStock )
104
+
105
+ buf := make ([]byte , 1024 )
106
+
107
+ for {
108
+ n ,_ ,err := ServerConn .ReadFromUDP (buf )
109
+ CheckError (err )
110
+ messages <- string (buf [0 :n ])
111
+
112
+ }
113
+ }
114
+ func genHTMLBody (m map [string ]int ){
115
+ var keys []string
116
+ keys = append (keys , " %%<tr> <td>" + time .Now ().Format ("2006-01-02 15:04:05" )+ "</td>" )
117
+ for k := range m {
118
+ v := strconv .Itoa (m [k ])
119
+ keys = append (keys , k + " %% <td>" + v + "</td>" )
120
+ }
121
+ sort .Strings (keys )
122
+ tableRow := ""
123
+ for v := range keys {
124
+ splitStr := strings .Split (keys [v ], "%%" )
125
+ tableRow += splitStr [1 ]
126
+ }
127
+ tableRow += "</tr>"
128
+ if (len (lastEntries ) >= 40 ){
129
+ //throw away eldest entry
130
+ lastEntries = lastEntries [1 :]
131
+ }
132
+ lastEntries = append (lastEntries , tableRow )
133
+ return
134
+ }
75
135
func printStock (m map [string ]int ){
76
136
var keys []string
77
137
for k := range m {
@@ -82,6 +142,77 @@ func printStock(m map[string]int){
82
142
fmt .Println (keys )
83
143
}
84
144
145
+ const http404 string = "HTTP/1.1 400 Bad Request \r \n Content-Length: 50\r \n Content-Type: text/html\r \n \r \n <html><body><h1>400 Bad Request</h1></body></html>"
146
+ const http408 string = "HTTP/1.1 408 Request Time-out \r \n Content-Length: 55\r \n Content-Type: text/html\r \n \r \n <html><body><h1>408 Request Time-out</h1></body></html>"
147
+
148
+ type htmlRenderer func () []byte
149
+
150
+ func handleWebRequest (conn net.Conn , tableHeader string , method string , subUrl string , rend htmlRenderer ){
151
+ // Make a buffer to hold incoming data.
152
+ buf := make ([]byte , 1024 )
153
+ // Read the incoming connection into the buffer.
154
+ _ , err := conn .Read (buf )
155
+ if err != nil {
156
+ fmt .Println ("Error reading:" , err .Error ())
157
+ }
158
+ request := string (buf )
159
+ //check if message is a complete http request, else start timeout
160
+ retry , timeout := 0 , 5
161
+ for ! strings .Contains (request ,"\r \n \r \n " ){
162
+ _ , err := conn .Read (buf )
163
+ if err != nil {
164
+ fmt .Println ("Error reading:" , err .Error ())
165
+ }
166
+ request = string (buf )
167
+ if (retry >= timeout ){
168
+ conn .Write ([]byte (http408 ))
169
+ conn .Close ()
170
+ return
171
+ }
172
+ time .Sleep (time .Second * 1 )
173
+ retry ++
174
+ }
175
+ requestLines := strings .Split (request ,"\r \n " )
176
+
177
+ //check if the request is valid
178
+ if (! strings .Contains (strings .ToUpper (requestLines [0 ]), method + " " + subUrl + " HTTP/1.1" )){
179
+ conn .Write ([]byte (http404 ))
180
+ conn .Close ()
181
+ return
182
+ }
183
+
184
+ rendHtml := rend ()
185
+ httpHeader := "HTTP/1.1 200 OK \r \n Content-Length: " + strconv .Itoa (len (rendHtml ))+ "\r \n Content-Type: text/html\r \n \r \n "
186
+ conn .Write (append ([]byte (httpHeader ), rendHtml ... ))
187
+ conn .Close ()
188
+ }
189
+
190
+
191
+ func startHttpServer (fridgeStock map [string ]int , tableHeader string ){
192
+ //Web-interface in the making
193
+ fmt .Println ("Starting Http-Server" )
194
+ ln , err := net .Listen ("tcp" , ":80" )
195
+
196
+ CheckError (err )
197
+ for {
198
+ conn , err := ln .Accept ()
199
+ CheckError (err )
200
+ go handleWebRequest (conn , tableHeader , "GET" , "/STOCK" , func () []byte {
201
+ // Combine the HTML fragments
202
+ fh , _ := ioutil .ReadFile ("./stock_head" )
203
+ ff , _ := ioutil .ReadFile ("./stock_foot" )
204
+ bth := []byte (tableHeader )
205
+ f := append (fh , bth ... )
206
+ for i := len (lastEntries )- 1 ; i >= 0 ; i -- {
207
+ btc := []byte (lastEntries [i ])
208
+ f = append (f , btc ... )
209
+ }
210
+ f = append (f , ff ... )
211
+ return f
212
+ })
213
+ }
214
+ }
215
+
85
216
func GetLocalIP () string {
86
217
addrs , err := net .InterfaceAddrs ()
87
218
if err != nil {
@@ -99,33 +230,11 @@ func GetLocalIP() string {
99
230
}
100
231
101
232
func main () {
102
-
103
- port , configPath := ":8080" ,"./config.json"
104
-
105
- fmt .Println ("Reading Config..." )
106
- fridgeStock := readConfig (configPath )
107
-
108
- fmt .Println ("Preparing Server..." )
109
- /* Lets prepare a address at any address at port */
110
- ServerAddr ,err := net .ResolveUDPAddr ("udp" , port )
111
- CheckError (err )
112
-
113
-
114
- fmt .Println ("Listening on port " , GetLocalIP (), port )
115
- /* Now listen at selected port */
116
- ServerConn , err := net .ListenUDP ("udp" , ServerAddr )
117
- CheckError (err )
118
- defer ServerConn .Close ()
119
-
120
- messages := make (chan string )
121
- go msgDigest (messages ,fridgeStock )
122
-
123
- buf := make ([]byte , 1024 )
124
-
125
- for {
126
- n ,_ ,err := ServerConn .ReadFromUDP (buf )
127
- CheckError (err )
128
- messages <- string (buf [0 :n ])
129
-
130
- }
233
+ configPath := "./config.json"
234
+ fridgeStock , tableHeader := readConfig (configPath )
235
+ block := make (chan bool )
236
+ go startUdpServer (fridgeStock )
237
+ go startHttpServer (fridgeStock , tableHeader )
238
+ <- block
131
239
}
240
+
0 commit comments