async def open(self, session, backoff_delay=0): # exponential backoff for consequent connections if necessary if backoff_delay: await sleep(backoff_delay) if self.verbose: self.print(Exchange.iso8601(Exchange.milliseconds()), 'connecting to', self.url, 'with timeout', self.connectionTimeout, 'ms') self.connectionStarted = Exchange.milliseconds() try: coroutine = self.create_connection(session) self.connection = await wait_for( coroutine, timeout=int(self.connectionTimeout / 1000)) self.connecting = False if self.verbose: self.print(Exchange.iso8601(Exchange.milliseconds()), 'connected') self.connected.resolve(self.url) # run both loops forever await gather(self.ping_loop(), self.receive_loop()) except TimeoutError as e: # connection timeout error = RequestTimeout('Connection timeout') if self.verbose: self.print(Exchange.iso8601(Exchange.milliseconds()), 'RequestTimeout', error) self.on_error(error) except Exception as e: # connection failed or rejected (ConnectionRefusedError, ClientConnectorError) error = NetworkError(e) if self.verbose: self.print(Exchange.iso8601(Exchange.milliseconds()), 'NetworkError', error) self.on_error(error)
def on_close(self, code): if self.verbose: self.print(Exchange.iso8601(Exchange.milliseconds()), 'on_close', code) if not self.error: self.reset(NetworkError(code)) self.on_close_callback(self, code) if not self.closed(): ensure_future(self.close(code))
def on_close(self, code): if self.verbose: self.print(Exchange.iso8601(Exchange.milliseconds()), 'on_close', code) if not self.error: self.reset( NetworkError( 'Connection closed by remote server, closing code ' + str(code))) self.on_close_callback(self, code) if not self.closed(): ensure_future(self.close(code))
async def receive_loop(self): if self.verbose: self.print(Exchange.iso8601(Exchange.milliseconds()), 'receive loop') while not self.closed(): try: message = await self.receive() # self.print(Exchange.iso8601(Exchange.milliseconds()), 'received', message) self.handle_message(message) except Exception as e: error = NetworkError(str(e)) if self.verbose: self.print(Exchange.iso8601(Exchange.milliseconds()), 'receive_loop', 'Exception', error) self.reset(error)
def handle_message(self, message): # self.print(Exchange.iso8601(Exchange.milliseconds()), message) if message.type == WSMsgType.TEXT: self.handle_text_or_binary_message(message.data) elif message.type == WSMsgType.BINARY: data = message.data if self.gunzip: data = gunzip(data) elif self.inflate: data = inflate(data) self.handle_text_or_binary_message(data) # autoping is responsible for automatically replying with pong # to a ping incoming from a server, we have to disable autoping # with aiohttp's websockets and respond with pong manually # otherwise aiohttp's websockets client won't trigger WSMsgType.PONG elif message.type == WSMsgType.PING: if self.verbose: self.print(Exchange.iso8601(Exchange.milliseconds()), 'ping', message) ensure_future(self.connection.pong()) elif message.type == WSMsgType.PONG: self.lastPong = Exchange.milliseconds() if self.verbose: self.print(Exchange.iso8601(Exchange.milliseconds()), 'pong', message) pass elif message.type == WSMsgType.CLOSE: if self.verbose: self.print(Exchange.iso8601(Exchange.milliseconds()), 'close', self.closed(), message) self.on_close(message.data) elif message.type == WSMsgType.CLOSED: if self.verbose: self.print(Exchange.iso8601(Exchange.milliseconds()), 'closed', self.closed(), message) self.on_close(1000) elif message.type == WSMsgType.ERROR: if self.verbose: self.print(Exchange.iso8601(Exchange.milliseconds()), 'error', message) error = NetworkError(str(message)) self.on_error(error)
def feed_eof(): self.on_error(NetworkError(1006))