channel-switch: use sys/ioctl.h instead of stropts.h
[rofl0r-MacGeiger.git] / httpsrv.rb
blobe5ecb2773082e6ef3df6995176e41e04bae59628
1 require 'socket'
2 require 'json'
3 require 'stringio'
5 $docroot = "./web"
6 $port = 8080
8 $macgeigerport = 9876
10 $wifis = Hash.new
11 $gt_socket = nil
12 def wifi_gather
13         begin
14                 socket = TCPSocket.new 'localhost', $macgeigerport
15                 $gt_socket = socket
16         rescue Errno::EADDRNOTAVAIL => e
17                 puts e.message
18                 puts "maybe you need to start macgeiger first?"
19                 exit(1)
20         end
21         out = false
22         loop do
23                 begin
24                         socket.puts "LIST\n"
25                 rescue IOError
26                         break
27                 end
28                 loop do
29                         line = socket.gets
30                         if line == nil then
31                                 out = true
32                                 break
33                         elsif line == "END\n" then
34                                 break
35                         end
36                         wifi_hash = JSON.parse(line)
37                         #if wifis.key?(wifi_hash["bssid"])
38                         $wifis[wifi_hash["bssid"]] = line.chomp
39                 end
40                 break if out
41                 sleep 1
42         end
43         socket.close
44 end
46 def select_mac(mac)
47         socket = TCPSocket.new 'localhost', $macgeigerport
48         socket.puts "SELECT " + mac
49         socket.close
50 end
52 def unselect_mac()
53         socket = TCPSocket.new 'localhost', $macgeigerport
54         socket.puts "UNSELECT"
55         socket.close
56 end
58 def http_resp(skt, status, io, content_type)
59         io.rewind
60         skt.print "HTTP/1.1 #{status}\r\nContent-Type: #{content_type}\r\n" +
61                 "Content-Length: #{io.size}\r\nConnection: keep-alive\r\n"+
62                 "\r\n"
63         IO.copy_stream(io, skt)
64 end
66 CONTENT_TYPE_MAPPING = {
67         'html' => 'text/html',
68         'txt' => 'text/plain',
69         'png' => 'image/png',
70         'jpg' => 'image/jpeg',
71         'css' => 'text/css',
72         'js' => 'text/javascript',
73         'json' => 'application/json',
76 def content_type(path)
77   ext = File.extname(path).split(".").last
78   CONTENT_TYPE_MAPPING.fetch(ext, 'application/octet-stream')
79 end
82 def serve_static(socket, url)
83         url = '/index.html' if url == '/'
84         ct = content_type(url)
85         path = $docroot + url
86         if !(File.exist?(path) && !File.directory?(path)) || url.include?("..")
87                 io = StringIO.new
88                 io.puts "File not found"
89                 http_resp socket, "404 Not Found", io, "text/plain"
90         else
91                 File.open(path, "rb") do |file|
92                         http_resp socket, "200 OK", file, ct
93                 end
94         end
95 end
97 def serve_full(skt)
98         io = StringIO.new
99         io.puts '{"wifis" : ['
100         #thanks to json's stupid decision that no trailing commas are accepted!
101         n = $wifis.size
102         i = 0
103         $wifis.each do |wifi, json|
104                 io.print json
105                 i += 1
106                 if i != n then
107                         io.print ","
108                 end
109                 io.print "\n"
110         end
111         io.print "]}\n"
112         http_resp(skt, "200 OK", io, "application/json")
115 def serve_empty(skt)
116         io = StringIO.new
117         http_resp(skt, "200 OK", io, "text/html")
120 def serve_update(skt)
121         skt.puts "full"
124 def get_path(str)
125         x = str.split(" ")
126         if x[0] == "GET" then
127                 return x[1]
128         end
129         return nil
132 class Client
133         def initialize
134                 @running = false
135                 @socket = nil
136                 @th  = nil
137         end
139         def assign_thread(th)
140                 @th = th
141         end
143         def running?
144                 @running
145         end
147         def jointhr
148                 @th.join
149         end
151         def interrupt
152                 @socket.close
153         end
155         def run(socket)
156                 @running = true
157                 @socket = socket
158                 loop do
159                         begin
160                                 line = socket.gets
161                         rescue IOError
162                                 break
163                         end
164                         if line == nil then
165                                 break
166                         end
167                         url = get_path(line)
168                         if url == nil then
169                         elsif url == "/api/unselect" then
170                                 unselect_mac()
171                                 serve_empty(@socket)
172                         elsif url.start_with?("/api/select/") then
173                                 mac = url.split("/").last
174                                 select_mac (mac)
175                                 serve_empty(@socket)
176                         elsif url.start_with?("/api/") then
177                                 case url
178                                 when "/api/full"
179                                         serve_full(@socket)
180                                 when "/api/update"
181                                         serve_update(@socket)
182                                 else
183                                         puts url
184                                 end
185                         else
186                                 serve_static(@socket, url)
187                         end
188                 end
189                 @socket.close
190                 @running = false
191         end
194 def collect_clients
195         $clients.each do |client|
196                 if not client.running? then
197                         client.jointhr
198                 end
199         end
202 gt = Thread.new { wifi_gather }
204 server = TCPServer.new $port
206 $clients = []
208 begin
209         while session = server.accept
210                 collect_clients
211                 client = Client.new
212                 client.assign_thread ( Thread.new {client.run(session)} )
213                 $clients << client
214         end
215 rescue Interrupt
218 $clients.each do |client|
219         client.interrupt if client.running?
221 collect_clients
222 $gt_socket.close
223 gt.join