def _SendQueuedData(self): """Send data that is sitting in the unsent data queue.""" while self._unsent_data and not self._stopping: try: send_data = utils.CreateSubprotocolDataFrame( self._unsent_data[0]) # We need to append to _unconfirmed_data before calling Send(), because # otherwise we could receive the ack for the sent data before we do the # append, which we would interpret as an invalid ack. This does mean # there's a small window of time where we'll accept acks of data that # hasn't truly been sent if a badly behaving server sends such acks, but # that's not really a problem, because we'll behave identically to as if # the ack was received after the data was sent (so no data or control # flow corruption), and we don't have a goal of giving an error every # time the server misbehaves. self._unconfirmed_data.append(self._unsent_data.popleft()) self._websocket_helper.Send(send_data) except helper.WebSocketConnectionClosed: break except EnvironmentError as e: log.info('Unable to send WebSocket data [%s]', str(e)) break except: # pylint: disable=bare-except log.info('Error while attempting to send [%d] bytes', len(send_data), exc_info=True) break # We need to check _input_eof before _unsent_data to avoid a race # condition with setting _input_eof simultaneously with this check. if self._input_eof and not self._unsent_data: self._sent_all.set()
def _SendData(self, bytes_to_send): first_to_send = bytes_to_send[:utils.SUBPROTOCOL_MAX_DATA_FRAME_SIZE] bytes_to_send = bytes_to_send[utils.SUBPROTOCOL_MAX_DATA_FRAME_SIZE:] if first_to_send: send_data = utils.CreateSubprotocolDataFrame(first_to_send) self._SendBytes(send_data) return bytes_to_send
def _SendQueuedData(self): """Send data that is sitting in the unsent data queue.""" try: while not self._stopping: self._MaybeSendAck() # This is a blocking call in case the queue is empty. The timeout is # there so we can unblock and send acks if no message arrive after a few # seconds try: if not self._data_to_resend.empty(): data = self._data_to_resend.get() else: data = self._unsent_data.get( timeout=MAX_WEBSOCKET_SEND_WAIT_TIME_SEC) except queue.Empty: # Throws empty if timeout reached if self._IsClosed(): raise helper.WebSocketConnectionClosed break # When EOF is reached, EOF error will be put in the queue. # When close is called. ConnectionAborted error is put in the queue. if data is EOFError or data is StoppingError: # Now we tell the thread to quit as there's no more data to send. self._stopping = True if data is EOFError: self._input_eof = True break # We need to append to _unconfirmed_data before calling Send(), because # otherwise we could receive the ack for the sent data before we do the # append, which we would interpret as an invalid ack. This does mean # there's a small window of time where we'll accept acks of data that # hasn't truly been sent if a badly behaving server sends such acks, but # that's not really a problem, because we'll behave identically to as if # the ack was received after the data was sent (so no data or control # flow corruption), and we don't have a goal of giving an error every # time the server misbehaves. # It's also important in case we take the data out of the unset data # queue but we can't send it up because the connection was closed. By # adding it to unconfirmed, we will resend it later. self._unconfirmed_data.append(data) send_data = utils.CreateSubprotocolDataFrame(data) self._websocket_helper.Send(send_data) finally: if (self._input_eof and self._data_to_resend.empty() and self._unsent_data.empty()): self._sent_all.set()
def Send(self, bytes_to_send): """Send bytes over WebSocket connection.""" if not self._websocket_open: self.WaitForOpenOrRaiseError() if not self._websocket: raise UnexpectedConnectionCloseError( 'WebSocket unexpectedly closed') while bytes_to_send: first_to_send = bytes_to_send[:utils. SUBPROTOCOL_MAX_DATA_FRAME_SIZE] bytes_to_send = bytes_to_send[utils. SUBPROTOCOL_MAX_DATA_FRAME_SIZE:] send_data = utils.CreateSubprotocolDataFrame(first_to_send) self._websocket.send(send_data, opcode=websocket.ABNF.OPCODE_BINARY)
def _SendQueuedData(self): """Send data that is sitting in the unsent data queue.""" while self._unsent_data and not self._stopping: try: send_data = utils.CreateSubprotocolDataFrame(self._unsent_data[0]) self._websocket_helper.Send(send_data) self._unconfirmed_data.append(self._unsent_data.popleft()) except helper.WebSocketConnectionClosed: break except EnvironmentError as e: log.info('Unable to send WebSocket data [%s]', str(e)) break except: # pylint: disable=bare-except log.info('Error while attempting to send [%d] bytes', len(send_data), exc_info=True) break
def testCreateSubprotocolDataFrame(self, bytes_to_send, expected_bytes): self.assertEqual(utils.CreateSubprotocolDataFrame(bytes_to_send), expected_bytes)