forked from bskari/pi-rc
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathhost_files.py
executable file
·140 lines (123 loc) · 4.65 KB
/
host_files.py
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
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
"""Hosts files from the local directory using SSL."""
from __future__ import print_function
import socket
import ssl
import subprocess
import sys
# pylint: disable=C0411
if sys.version_info.major < 3:
import SimpleHTTPServer
import SocketServer
import urllib
Server = SocketServer.TCPServer
SimpleHTTPRequestHandler = SimpleHTTPServer.SimpleHTTPRequestHandler
urlopen = urllib.urlopen
decode = lambda s: s.decode('string_escape')
else:
from http.server import SimpleHTTPRequestHandler, HTTPServer # pylint: disable=E0401
Server = HTTPServer # pylint: disable=C0103
import urllib.request
urlopen = urllib.request.urlopen
decode = lambda s: bytes(s, 'utf-8').decode('unicode-escape')
class PostCommandsRequestHandler(SimpleHTTPRequestHandler): # pylint: disable=R0903
"""Serves files over GET and handles commands send over POST."""
def do_POST(self): # pylint: disable=C0103
"""Handles POST requests."""
if not self.path.endswith('/'):
# Redirect browser - doing basically what Apache does
self.send_response(301)
self.send_header('Location', self.path + '/')
self.end_headers()
elif self.path == '/command/':
# Forward this request on to the C server, because doing SSL in C
# sounds hard
content_length = int(self.headers.get('Content-Length'))
post_data = self.rfile.read(content_length)
print(post_data)
try:
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect(('localhost', 12345))
sock.sendall(post_data)
except Exception as exc:
print('{}, sending 500'.format(exc))
self.send_response(500)
self.send_header('Content-type', 'text/plain; charset=utf-8')
self.end_headers()
# Firefox keeps expecting to get XML back. If we send back
# plain text, it doesn't error out, but it generates a console
# warning, so let's just play nice
self.wfile.write('<p>Unable to contact pi_pcm; is it running?</p>')
return
finally:
sock.close()
self.send_response(200)
self.end_headers()
elif self.path == '/save/':
content_length = int(self.headers.get('Content-Length'))
post_data = decode(self.rfile.read(content_length)[1:-1])
with open('parameters.json', 'w') as parameters_file:
parameters_file.write(post_data)
self.send_response(200)
self.end_headers()
else:
self.send_response(404)
self.end_headers()
def main():
"""Main."""
# The URL fetching stuff inherits this timeout
socket.setdefaulttimeout(0.25)
# Prevent "address already in use" errors
Server.allow_reuse_address = True
base_cert_file_name = 'www.pi-rc.com'
try:
with open(base_cert_file_name + '.cert'):
pass
except IOError:
print(
'''Chrome requires HTTPS to access the webcam. This script can serve HTTPS
requests, but requires that a self-signed certificate be generated first. When
you access this page, you will get a warning - just click through it. This
script will now generate a self-signed certificate.'''
)
subprocess.call((
'openssl',
'req',
'-new',
'-newkey',
'rsa:4096',
'-days',
'365',
'-nodes',
'-x509',
'-subj',
'/C=US/ST=Denial/L=Springfield/O=Dis/CN={}'.format(base_cert_file_name),
'-keyout',
'{}.key'.format(base_cert_file_name),
'-out',
'{}.cert'.format(base_cert_file_name)
))
print('Starting server')
port = 4443
server_address = ('0.0.0.0', port)
httpd = Server(server_address, PostCommandsRequestHandler)
httpd.socket = ssl.wrap_socket(
httpd.socket,
server_side=True,
certfile='{}.cert'.format(base_cert_file_name),
keyfile='{}.key'.format(base_cert_file_name),
ssl_version=ssl.PROTOCOL_TLSv1
)
try:
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
skari_org = '149.154.158.78'
# This won't actually make a connection
sock.connect((skari_org, 1))
ip = sock.getsockname()[0]
except socket.gaierror:
ip = 'localhost'
finally:
sock.close()
print('Running server on https://{}:{}/'.format(ip, port))
httpd.serve_forever()
if __name__ == '__main__':
main()