def main(): errprint('%s start running' % __file__) s = initServer(1) while True: conn, content = listen(s) processHtml(conn, content) conn.close()
def parseHeader(content, context): [header, body] = content.split('\r\n\r\n', 1) tmp = header.split('\r\n', 1) if len(tmp) != 2: errprint('Invalid response') context['status'] = ERROR return [status_line, header_content] = tmp [version, status, message] = status_line.split(' ', 2) status = int(status) header_dict = {'version': version, 'status': status, 'message': message} context['header'] = header_dict for h in header_content.split('\r\n'): hl = h.split(': ', 1) header_dict[hl[0]] = hl[1] if status == 200: context['status'] = SUCCEED content_type = header_dict.get('Content-Type', '') if len(content_type) < 9 or content_type.find('text/html') < 0: context['status'] = ERROR elif status == 301 or status == 302: context['status'] = REDIRECT elif status >= 400: context['status'] = ERROR_BUT_DISPLAY else: context['status'] = ERROR
def listen(server): inputs = [server] outputs = [] messages = {} while inputs: readable, writable, exceptional = select.select( inputs, outputs, inputs) for s in readable: if s is server: readServer(inputs, messages, s) else: try: while True: data = s.recv(1024) print(data, len(data)) if data: readData(messages, data, s) if not data or (len(messages[s]) >= 4 and messages[s][-4:] == '\r\n\r\n'): closeRead(inputs, outputs, s) break execute(messages, s) closeWrite(outputs, messages, s) except socket.error: errprint('Socket blocked') for s in exceptional: closeServer(inputs, outputs, messages, s)
def execute(messages, s): try: content = messages[s] http_server1.processHtml(s, content) return 0 except: errprint('Unexpected error') return -1
def closeServer(inputs, outputs, messages, s): errprint('%s goes wrong', (s.getpeername())) if s in inputs: inputs.remove(s) if s in outputs: outputs.remove(s) s.close() del messages[s]
def _on_channel_open(self, channel): errprint("Channel opened") self.channel = channel self.channel.add_on_close_callback(self._on_channel_closed) self.channel.exchange_declare(exchange=common.EXCHANGE, exchange_type='topic', callback=self._on_exchange_declared) self.connection.ioloop.call_later(self.POLL_PERIOD, self._check_stdin)
def processHtml(conn, content): header_dict = parseHeader(content) if header_dict is not None: f = openFile(header_dict['pathname']) if f is not None: sendFile(conn, f) errprint("Success") else: sendError(conn) errprint("Not found")
def get(urls): if urls is None: errprint('There is no URL to get') return -1 for url in urls: context, response = connect(url) status = context['status'] if context.get('header', None) is not None: print(context['header']['status'], context['header']['message']) if status == SUCCEED or status == ERROR_BUT_DISPLAY: print(response)
def sendFile(conn, f): try: header = successHeader() conn.send(header) while True: data = f.read(1024) if data == '': break conn.send(data) except IOError as e: errprint('Unexpeced error during sending file', e.message) return None
def parseSysParam(): if len(sys.argv) > 2: errprint('Invalid command') return -1 if len(sys.argv) == 1: return DEFAULT_PORT try: port = int(sys.argv[1]) except ValueError: errprint('Port is not a number') return -1 return port
def sendFile(conn, f): try: header = 'HTTP/1.0 200 OK\r\n' header += header2str(DEFAULT_HEADER) conn.send(header) while True: data = f.read(1024) if data == '': break conn.send(data) except IOError as e: errprint('Unexpeced error during sending file', e.message) return None
def writeSocket(messages, s): content = messages[s].get('file_content', None) if content is None: errprint('The connecting doesn\'t have content') messages[s]['status'] = ERROR return messages[s]['status'] = WRITING_SOCKET try: while not content.empty(): con = content.queue[0] s.send(con) content.get() if content.empty(): messages[s]['status'] = FINISHED except socket.error: errprint('Block during writing socket') messages[s]['status'] = BLOCK
def readFile(messages, inputs, outputs, f): if messages[f]['status'] != BLOCK and messages[f]['status'] != READING_FILE: errprint('Invalid status in file %s' % f.name) messages[f]['status'] = ERROR return messages[f]['status'] = READING_FILE try: while True: data = f.read(1024) if data == '' or data == '\n' or data == '\r\n' \ or (len(data) >= 2 and data[-2:] == '\n\n') or (len(data) >= 4 and data[-4:] == '\r\n\r\n'): finishReadingFile(messages, inputs, outputs, f) break readFileData(messages, data, f) except IOError: errprint('The file %s is blocked' % f.name) messages[f]['status'] = BLOCK
def getContent(host, port, filename): print(host, port, filename) request_header = 'GET ' + filename + ' HTTP/1.0\r\n' request_header += 'Host: ' + host + ':' + str(port) + '\r\n\r\n' s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) try: s.connect((host, port)) s.send(request_header) response = '' while True: data = s.recv(1024) if not data: break response += data s.close() except: errprint('Unexpected error during the downloading: ', sys.exc_info()) return None return response
def readSocket(messages, inputs, s): if messages[s]['status'] != BLOCK and messages[s][ 'status'] != READING_SCOKET: errprint('Invalid status in socket %s' % s.getpeername()) messages[s]['status'] = ERROR return messages[s]['status'] = READING_SCOKET try: while True: data = s.recv(1024) if data: readSocketData(messages, data, s) if not data or (len(messages[s]['content']) >= 4 and messages[s]['content'][-4:] == '\r\n\r\n'): inputs.remove(s) openFile(inputs, messages, s) break except socket.error: errprint('The socket %s is blocked' % (s.getpeername(), )) messages[s]['status'] = BLOCK
def openFile(inputs, messages, s): errprint('Finish reading, start to read file') messages[s]['file_content'] = Queue.Queue() messages[s]['file_content'].put(http_server1.successHeader()) header_dict = http_server1.parseHeader(messages[s]['content']) if header_dict is None: errprint('Error during parsing header') messages[s]['status'] = ERROR return f = http_server1.openFile(header_dict.get('pathname', None)) if f is None: errprint( 'Server3: Can not find the file, return the \"Not Found\" page') f = http_server1.openFile(http_server1.ERROR_PATH) messages[s]['file_content'].put(http_server1.errorHeader()) # Set the file to be non-blocking and add connection to the socket and the file fcntl.fcntl(f, fcntl.F_SETFL, os.O_NONBLOCK) messages[s]['status'] = READING_FILE messages[s]['file'] = f messages[f] = { 'status': READING_FILE, 'content': Queue.Queue(), 'socket': s, 'type': FILE } inputs.append(f)
def connect(url, context=None, count=0): # The program may redirect infinitely, so I set the maximum redirect times to 15 if context is None: context = {'status': UNDEFINED} while True: if count > 15: errprint('Redirect too much times') return context, 'Error' parseURL(url, context) status = context['status'] host = context.get('host', None) port = context.get('port', -1) filename = context.get('filename', '/') if status != SUCCEED: errprint("Unexpected error in the URL") return context, 'Error' response = getContent(host, port, filename) if response is None: context['status'] = ERROR return context, 'Error' parseHeader(response, context) status = context['status'] # Not redirect if status != REDIRECT: return context, response # Redirect errprint('Redirect to: ' + context['header']['Location']) url = context['header']['Location'] count += 1 del (context['header'])
def parseHeader(content): try: [header, body] = content.split('\r\n\r\n', 1) tmp = header.split('\r\n', 1) if len(tmp) < 1: errprint('Invalid header') return None command_line = tmp[0] [method, pathname, version] = command_line.split(' ', 2) header_dict = { 'method': method, 'pathname': pathname, 'version': version } errprint('pathname', pathname) if len(tmp) < 2: return header_dict header_content = tmp[1] for h in header_content.split('\r\n'): hl = h.split(' ', 1) header_dict[hl[0][:-1]] = hl[1] except: errprint('Invalid header with unknown error') return None return header_dict
def callback(ch, method, properties, body): injury, name = body.decode().split(maxsplit=1) if injury != skill: errprint("'{}' handler received unexpected message!".format(skill)) errprint("performing {} test on {}".format(injury, name)) time.sleep(random.uniform(3, 7)) errprint("{} test on {} done".format(injury, name)) reply_to = properties.reply_to response = "{} {} done".format(name, injury) ch.basic_ack(delivery_tag=method.delivery_tag) ch.basic_publish(exchange=common.EXCHANGE, routing_key=reply_to, body=response)
def parseURL(url_str, context): url_str = url_str.lower() infos = url_str.split(':') if len(infos) != 2 and len(infos) != 3: errprint('Invalid URL format') context['status'] = ERROR return -1 [http, url] = infos[:2] port = DEFAULT_PORT filename = '/' if http != 'http': errprint('Invalid protocol') context['status'] = ERROR return -1 if url[:2] != '//': errprint('Invalid URL') context['status'] = ERROR return -1 url = url[2:] url = url.split('/', 1)[0] tmp = url_str.split('//', 1)[1].split('/', 1) if len(tmp) > 1: filename = '/' + tmp[1] if len(infos) == 3: port = infos[2].split('/')[0] try: port = int(port) except ValueError: errprint('Invalid port number') context['status'] = ERROR return -1 context['status'] = SUCCEED context['host'] = url context['port'] = port context['filename'] = filename return 0
def openFile(pathname): if pathname is None or not isinstance(pathname, str): errprint('Invalid pathname') return None if pathname == '/': pathname = DEFAULT_PATH tmp = pathname.split('.', 1) if len(tmp) < 2 or (tmp[1] != 'html' and tmp[1] != 'htm'): errprint('Invalid pathname') return None try: pathname = pathname.lower() f = open(ROOT_DIR + pathname, 'r') except: errprint('Unexpected error during open file') return None return f
def _on_channel_closed(self, channel, reason): self.channel = None errprint("Channel closed because of ", reason)
def _on_exchange_declared(self, frame): errprint("Exchange declared") self._declare_queues()
def _on_connected(self, connection): errprint("Connection created") self.connection.channel(on_open_callback=self._on_channel_open)
return callback def on_info(ch, method, properties, body): print("[INFO] {}".format(body.decode())) if __name__ == '__main__': _connection, channel = common.connect() channel.queue_declare('', exclusive=True) channel.queue_bind(exchange=common.EXCHANGE, queue='', routing_key='info') channel.basic_consume(queue='', on_message_callback=on_info, auto_ack=True) for skill in sys.argv[1:3]: errprint("Binding skill {}".format(skill)) routing_key = 'request.#.{}'.format(skill) queue_name = 'requests.{}'.format(skill) channel.queue_declare(queue_name) channel.queue_bind(exchange=common.EXCHANGE, queue=queue_name, routing_key=routing_key) channel.basic_qos(prefetch_count=1) channel.basic_consume(queue=queue_name, on_message_callback=make_skill_callback(skill), auto_ack=False) try: channel.start_consuming()
def closeWrite(outputs, messages, s): errprint('Finish writing, end') #outputs.remove(s) s.close() del messages[s]
def readServer(inputs, messages, s): recv, addr = s.accept() errprint('A new socket') recv.setblocking(0) messages[recv] = '' inputs.append(recv)
def listen(server): inputs = [server] outputs = [] messages = {} while inputs: readable, writable, exceptional = select.select( inputs, outputs, inputs) for s in readable: if s is server: readServer(inputs, messages, s) elif messages[s]['type'] == SOCKET: errprint('Reading socket') readSocket(messages, inputs, s) if messages.get( s, None) is not None and messages[s]['status'] == ERROR: closeStream(inputs, outputs, messages, s) continue elif messages[s]['type'] == FILE: errprint('Reading file') readFile(messages, inputs, outputs, s) if messages.get( s, None) is not None and messages[s]['status'] == ERROR: closeStream(inputs, outputs, messages, s) continue else: errprint('Unknown stream status') closeStream(inputs, outputs, messages, s) for s in writable: if messages[s]['type'] != SOCKET: errprint('Wrong type of output stream') closeStream(inputs, outputs, messages, s) errprint('Respond to the client') writeSocket(messages, s) if messages[s]['status'] == ERROR: errprint('Unknown error during writing socket') if messages[s]['status'] == FINISHED: errprint('Finish writing, end') closeStream(inputs, outputs, messages, s) for s in exceptional: errprint('Exceptional stream') closeStream(inputs, outputs, messages, s)
def main(): errprint('%s start running' % __file__) s = http_server1.initServer(5) s.setblocking(0) listen(s)
def readServer(inputs, messages, s): recv, addr = s.accept() errprint('A new socket') recv.setblocking(0) messages[recv] = {'status': READING_SCOKET, 'content': '', 'type': SOCKET} inputs.append(recv)