Esempio n. 1
0
File: tcp.py Progetto: j4cbo/chiral
	def _read_line_coro(self, max_len, delimiter):
		"""Helper coroutine created by `read_line` if data is not immediately available."""
		while True:
			# Wait for the socket to be readable
			yield reactor.wait_for_readable(self.remote_sock)

			# Read more data
			try:
				new_data = self.remote_sock.recv(max_len)
			except socket.error, exc:
				if exc[0] in _AGAIN:
					# Nope, still not readable.
					continue
				else:
					raise exc

			if not new_data:
				raise ConnectionClosedException()

			self._buffer += new_data

			# Check if the delimiter is already in the buffer.
			if delimiter in self._buffer[:max_len]:
				out, self._buffer = self._buffer.split(delimiter, 1)
				raise StopIteration(out)

			# If not, and the buffer's longer than our expected line,
			# we've had an overflow
			if len(self._buffer) > max_len:
				raise ConnectionOverflowException()
Esempio n. 2
0
File: tcp.py Progetto: j4cbo/chiral
	def recv(self, buflen):
		"""
		Read data from the socket.

		This behaves analogously to the ``recv`` system call, but will read data from
		the internal buffer if available.
		"""

		if self._buffer:
			if len(self._buffer) > buflen:
				out = self._buffer[:buflen]
				self._buffer = self._buffer[buflen:]
			else:
				out = self._buffer
				self._buffer = ""

			raise StopIteration(out)
			
		while True:
			# Try reading the data.
			try:
				res = self.remote_sock.recv(buflen)
			except socket.error, exc:
				# If we would have blocked, try again later.
				if exc[0] not in _AGAIN:
					raise exc
			else:
				raise StopIteration(res)

			yield reactor.wait_for_readable(self.remote_sock)
Esempio n. 3
0
File: tcp.py Progetto: j4cbo/chiral
	def _sendall_coro(self, data):
		"""Helper coroutine created by `sendall` if not all data could be sent."""
		while data:

			yield reactor.wait_for_readable(self.remote_sock)

			try:
				res = self.remote_sock.send(data)
			except socket.error, exc:
				# If the write would block, just loop around and try later.
				if exc[0] not in _AGAIN:
					raise exc

			data = data[res:]
Esempio n. 4
0
File: tcp.py Progetto: j4cbo/chiral
	def read_exactly(self, length, read_increment = 32768):
		"""
		Read and return exactly ``length`` bytes.

		:param length: Number of bytes to return.
		:param read_increment: Number of bytes to low-level read from the socket at a time.
		"""

		# If we have enough bytes already, just return them
		if len(self._buffer) >= length:
			out = self._buffer[:length]
			self._buffer = self._buffer[length:]
			raise StopIteration(out)

		while True:
			# If not, attempt to recv()
			bytes_left = length - len(self._buffer)

			try:
				new_data = self.remote_sock.recv(min(bytes_left, read_increment))
			except socket.error, exc:
				# Reraise any unexpected errors.
				if exc[0] not in _AGAIN:
					raise exc
			else:
				# We successfully recv()'d; add the data to the buffer
				# and then check if it's enough.

				if not new_data:
					raise ConnectionClosedException()

				self._buffer += new_data
				if len(self._buffer) >= length:
					out = self._buffer[:length]
					self._buffer = self._buffer[length:]
					raise StopIteration(out)

			# Wait for readability, then try the recv again.
			yield reactor.wait_for_readable(self.remote_sock)
Esempio n. 5
0
File: tcp.py Progetto: j4cbo/chiral
	def acceptor(self):
		"""Main coroutine function.

		Continously calls accept() and creates new connection objects.
		"""

		# Continuously accept new connections
		while True:

			# Keep trying to accept() until we get a socket
			while True:
				try:
					client_socket, client_addr = self.master_socket.accept()
				except socket.error, exc:
					if exc[0] not in _AGAIN:
						print "Error in accept(): %s" % exc
					yield reactor.wait_for_readable(self.master_socket)
				else:
					break

			# Create a new TCPConnection for the socket 
			new_conn = self.connection_class(client_addr, client_socket, self)
			self.connections[id(new_conn)] = new_conn
			new_conn.start()