Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(80)

Side by Side Diff: tools/usb_gadget/server.py

Issue 412243002: [usb_gadget p09] Software updates over HTTP. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 6 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « tools/usb_gadget/package.py ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 # Copyright 2014 The Chromium Authors. All rights reserved. 1 # Copyright 2014 The Chromium Authors. All rights reserved.
2 # Use of this source code is governed by a BSD-style license that can be 2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file. 3 # found in the LICENSE file.
4 4
5 """WSGI application to manage a USB gadget. 5 """WSGI application to manage a USB gadget.
6 """ 6 """
7 7
8 import datetime
9 import hashlib
8 import re 10 import re
11 import subprocess
9 import sys 12 import sys
13 import time
14 import urllib2
10 15
11 from tornado import httpserver 16 from tornado import httpserver
17 from tornado import ioloop
12 from tornado import web 18 from tornado import web
13 19
14 import default_gadget 20 import default_gadget
15 21
16 VERSION_PATTERN = re.compile(r'.*usb_gadget-([a-z0-9]{32})\.zip') 22 VERSION_PATTERN = re.compile(r'.*usb_gadget-([a-z0-9]{32})\.zip')
17 23
18 address = None 24 address = None
19 chip = None 25 chip = None
20 claimed_by = None 26 claimed_by = None
21 default = default_gadget.DefaultGadget() 27 default = default_gadget.DefaultGadget()
22 gadget = None 28 gadget = None
29 hardware = None
30 interface = None
31 port = None
23 32
24 33
25 def SwitchGadget(new_gadget): 34 def SwitchGadget(new_gadget):
26 if chip.IsConfigured(): 35 if chip.IsConfigured():
27 chip.Destroy() 36 chip.Destroy()
28 37
29 global gadget 38 global gadget
30 gadget = new_gadget 39 gadget = new_gadget
31 gadget.AddStringDescriptor(3, address) 40 gadget.AddStringDescriptor(3, address)
32 chip.Create(gadget) 41 chip.Create(gadget)
33 42
34 43
35 class VersionHandler(web.RequestHandler): 44 class VersionHandler(web.RequestHandler):
36 45
37 def get(self): 46 def get(self):
38 version = 'unpackaged' 47 version = 'unpackaged'
39 for path in sys.path: 48 for path in sys.path:
40 match = VERSION_PATTERN.match(path) 49 match = VERSION_PATTERN.match(path)
41 if match: 50 if match:
42 version = match.group(1) 51 version = match.group(1)
43 break 52 break
44 53
45 self.write(version) 54 self.write(version)
46 55
47 56
57 class UpdateHandler(web.RequestHandler):
58
59 def post(self):
60 fileinfo = self.request.files['file'][0]
61
62 match = VERSION_PATTERN.match(fileinfo['filename'])
63 if match is None:
64 self.write('Filename must contain MD5 hash.')
65 self.set_status(400)
66 return
67
68 content = fileinfo['body']
69 md5sum = hashlib.md5(content).hexdigest()
70 if md5sum != match.group(1):
71 self.write('File hash does not match.')
72 self.set_status(400)
73 return
74
75 filename = 'usb_gadget-{}.zip'.format(md5sum)
76 with open(filename, 'wb') as f:
77 f.write(content)
78
79 args = ['/usr/bin/python', filename,
80 '--interface', interface,
81 '--port', str(port),
82 '--hardware', hardware]
83 if claimed_by is not None:
84 args.extend(['--start-claimed', claimed_by])
85
86 print 'Reloading with version {}...'.format(md5sum)
87
88 global http_server
89 if chip.IsConfigured():
90 chip.Destroy()
91 http_server.stop()
92
93 child = subprocess.Popen(args, close_fds=True)
94
95 while True:
96 child.poll()
97 if child.returncode is not None:
98 self.write('New package exited with error {}.'
99 .format(child.returncode))
100 self.set_status(500)
101
102 http_server = httpserver.HTTPServer(app)
103 http_server.listen(port)
104 SwitchGadget(gadget)
105 return
106
107 try:
108 f = urllib2.urlopen('http://{}/version'.format(address))
109 if f.getcode() == 200:
110 # Update complete, wait 1 second to make sure buffers are flushed.
111 io_loop = ioloop.IOLoop.instance()
112 io_loop.add_timeout(datetime.timedelta(seconds=1), io_loop.stop)
113 return
114 except urllib2.URLError:
115 pass
116 time.sleep(0.1)
117
118
48 class ClaimHandler(web.RequestHandler): 119 class ClaimHandler(web.RequestHandler):
49 120
50 def post(self): 121 def post(self):
51 global claimed_by 122 global claimed_by
52 123
53 if claimed_by is None: 124 if claimed_by is None:
54 claimed_by = self.get_argument('session_id') 125 claimed_by = self.get_argument('session_id')
55 else: 126 else:
56 self.write('Device is already claimed by "{}".'.format(claimed_by)) 127 self.write('Device is already claimed by "{}".'.format(claimed_by))
57 self.set_status(403) 128 self.set_status(403)
(...skipping 23 matching lines...) Expand all
81 152
82 class ReconnectHandler(web.RequestHandler): 153 class ReconnectHandler(web.RequestHandler):
83 154
84 def post(self): 155 def post(self):
85 if not chip.IsConfigured(): 156 if not chip.IsConfigured():
86 chip.Create(gadget) 157 chip.Create(gadget)
87 158
88 159
89 app = web.Application([ 160 app = web.Application([
90 (r'/version', VersionHandler), 161 (r'/version', VersionHandler),
162 (r'/update', UpdateHandler),
91 (r'/claim', ClaimHandler), 163 (r'/claim', ClaimHandler),
92 (r'/unclaim', UnclaimHandler), 164 (r'/unclaim', UnclaimHandler),
93 (r'/unconfigure', UnconfigureHandler), 165 (r'/unconfigure', UnconfigureHandler),
94 (r'/disconnect', DisconnectHandler), 166 (r'/disconnect', DisconnectHandler),
95 (r'/reconnect', ReconnectHandler), 167 (r'/reconnect', ReconnectHandler),
96 ]) 168 ])
97 169
98 http_server = httpserver.HTTPServer(app) 170 http_server = httpserver.HTTPServer(app)
OLDNEW
« no previous file with comments | « tools/usb_gadget/package.py ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698