rest.py

changeset 94
2c93636202a5
parent 93
125f3c97071e
child 95
af912f53649c
equal deleted inserted replaced
93:125f3c97071e 94:2c93636202a5
5 import asyncore 5 import asyncore
6 import base64 6 import base64
7 import re 7 import re
8 import json 8 import json
9 import urllib 9 import urllib
10 import irc 10 import irc as Irc
11 from datetime import datetime, timedelta 11 from datetime import datetime, timedelta
12 from configfile import Config 12 from configfile import Config
13 13
14 g_credentials = None 14 g_credentials = None
15 g_portnumber = None 15 g_portnumber = None
22 def is_throttled (address): 22 def is_throttled (address):
23 i = 0 23 i = 0
24 24
25 while i < len (g_throttle): 25 while i < len (g_throttle):
26 if g_throttle[i][1] <= datetime.utcnow(): 26 if g_throttle[i][1] <= datetime.utcnow():
27 print 'Throttle of %s expired' % g_throttle[i][0][0] 27 print 'Throttle of %s expired' % g_throttle[i][0]
28 item = g_throttle.pop (i) # expired 28 item = g_throttle.pop (i) # expired
29 29
30 if item[0][0] == address[0]: 30 if item[0] == address:
31 return False # this address expired 31 return False # this address expired
32 32
33 continue 33 continue
34 34
35 if g_throttle[i][0][0] == address[0]: 35 if g_throttle[i][0] == address:
36 return True # is throttled 36 return True # is throttled
37 37
38 i += 1 38 i += 1
39 39
40 return False # not throttled 40 return False # not throttled
51 51
52 Irc.broadcast ('Throttling %s:%s for 30 seconds' % address) 52 Irc.broadcast ('Throttling %s:%s for 30 seconds' % address)
53 53
54 def handle_rest_http (data, address): 54 def handle_rest_http (data, address):
55 global g_credentials 55 global g_credentials
56 displayaddress = '%s:%s' % address 56 displayaddress = address
57 authrex = re.compile (r'^authorization: Basic (.+)$') 57 authrex = re.compile (r'^authorization: Basic (.+)$')
58 payloadrex = re.compile (r'^payload=(.+)$') 58 payloadrex = re.compile (r'^payload=(.+)$')
59 authenticated = False 59 authenticated = False
60 payload = '' 60 payload = ''
61 61
64 64
65 # Authenticate and find the payload 65 # Authenticate and find the payload
66 for line in data: 66 for line in data:
67 match = authrex.match (line) 67 match = authrex.match (line)
68 68
69 if match and match.group (1) == g_credentials) 69 if match and match.group (1) == g_credentials:
70 authenticated = True 70 authenticated = True
71 continue 71 continue
72 72
73 match = payloadrex.match (line) 73 match = payloadrex.match (line)
74 if match: 74 if match:
82 jsonstring = urllib.unquote_plus (payload).decode ('utf-8') 82 jsonstring = urllib.unquote_plus (payload).decode ('utf-8')
83 83
84 try: 84 try:
85 jsondata = json.loads (jsonstring) 85 jsondata = json.loads (jsonstring)
86 repodata = jsondata['repository'] 86 repodata = jsondata['repository']
87 repopath = '%s/%s' % (repodata['owner'], repodata['name'] 87 repopath = '%s/%s' % (repodata['owner'], repodata['name'])
88 88
89 if repopath not in valid_repos: 89 if repopath not in valid_repos:
90 raise ValueError ('unknown repository %s' % repopath) 90 raise ValueError ('unknown repository %s' % repopath)
91 91
92 if 'commits' in jsondata: 92 if 'commits' in jsondata:
106 throttle (address) 106 throttle (address)
107 return 107 return
108 108
109 class RESTConnection (asyncore.dispatcher): 109 class RESTConnection (asyncore.dispatcher):
110 httpdata = '' 110 httpdata = ''
111 address=None
112 writebuffer = '' 111 writebuffer = ''
112 address = None
113 113
114 def __init__ (self, conn, address): 114 def __init__ (self, conn, address):
115 asyncore.dispatcher.__init__ (self, conn) 115 asyncore.dispatcher.__init__ (self, conn)
116 self.socket = ssl.wrap_socket (conn, server_side=True, keyfile='key.pem', 116 self.socket = ssl.wrap_socket (conn, server_side=True, keyfile='key.pem',
117 certfile='cert.pem', do_handshake_on_connect=False) 117 certfile='cert.pem', do_handshake_on_connect=False)
118 self.socket.setblocking (0) 118 self.socket.setblocking (0)
119 self.address = address 119 self.address = address
120 print 'Initialized connection handler for %s' % type (address)
120 121
121 while True: 122 while True:
122 try: 123 try:
123 self.socket.do_handshake() 124 self.socket.do_handshake()
124 break 125 break
126 if err.args[0] == ssl.SSL_ERROR_WANT_READ: 127 if err.args[0] == ssl.SSL_ERROR_WANT_READ:
127 select.select([self.socket], [], []) 128 select.select([self.socket], [], [])
128 elif err.args[0] == ssl.SSL_ERROR_WANT_WRITE: 129 elif err.args[0] == ssl.SSL_ERROR_WANT_WRITE:
129 select.select([], [self.socket], []) 130 select.select([], [self.socket], [])
130 else: 131 else:
131 Irc.broadcast ('%s:%s: SSL error: %s' % (self.address[0], self.address[1], err)) 132 Irc.broadcast ('%s:%s: SSL error: %s' % (self.address[0], err))
132 throttle (self.address) 133 throttle (self.address[0])
133 self.close() 134 self.close()
134 return 135 return
135 136
136 def write (self, msg): 137 def write (self, msg):
137 self.writebuffer += msg 138 self.writebuffer += msg
147 148
148 def handle_read (self): 149 def handle_read (self):
149 while 1: 150 while 1:
150 try: 151 try:
151 data = self.recv (4096) 152 data = self.recv (4096)
152 except ssl.SSLError, err: 153 except:
153 # EOF 154 # EOF
154 self.finish() 155 self.finish()
155 return 156 return
156 157
157 self.httpdata += data.replace ('\r', '') 158 self.httpdata += data.replace ('\r', '')
158 159
159 def finish (self): 160 def finish (self):
160 handle_rest_http (self.httpdata.split ('\n'), self.address) 161 handle_rest_http (self.httpdata.split ('\n'), self.address[0])
161 self.close() 162 self.close()
162 163
163 def handle_write (self): 164 def handle_write (self):
164 self.send (self.writebuffer) 165 self.send (self.writebuffer)
165 self.writebuffer='' 166 self.writebuffer=''
174 if g_portnumber == None: 175 if g_portnumber == None:
175 g_portnumber = Config.get_node ('rest').get_value ('port') 176 g_portnumber = Config.get_node ('rest').get_value ('port')
176 177
177 asyncore.dispatcher.__init__ (self) 178 asyncore.dispatcher.__init__ (self)
178 self.create_socket (socket.AF_INET, socket.SOCK_STREAM) 179 self.create_socket (socket.AF_INET, socket.SOCK_STREAM)
180 self.setsockopt (socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
179 self.bind (('', g_portnumber)) 181 self.bind (('', g_portnumber))
180 self.listen (5) 182 self.listen (5)
181 print 'REST server initialized' 183 print 'REST server initialized'
182 184
183 def handle_accept (self): 185 def handle_accept (self):
187 # throttled 189 # throttled
188 sock.close() 190 sock.close()
189 return 191 return
190 192
191 Irc.broadcast ('REST connection from %s:%s' % address) 193 Irc.broadcast ('REST connection from %s:%s' % address)
192 RESTConnection (sock, address) 194 conn = RESTConnection (sock, address)
195
196 if conn.address == None:
197 conn.__init__ (sock, address) # eh?
193 198
194 def handle_error (self): 199 def handle_error (self):
195 return 200 return

mercurial