# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # __all__ = [ "read_socket_input", "write_socket_output" ] import socket, errno, logging from connection import Connection LOG = logging.getLogger(__name__) """helper methods that provide boilerplate socket I/O and Connection processing. """ def read_socket_input(connection, socket_obj): """Read from the network layer and processes all data read. Can support both blocking and non-blocking sockets. Returns the number of input bytes processed, or EOS if input processing is done. Any exceptions raised by the socket are re-raised. """ count = connection.needs_input if count <= 0: return count # 0 or EOS try: sock_data = socket_obj.recv(count) except socket.timeout, e: LOG.debug("Socket timeout exception %s", str(e)) raise # caller must handle except socket.error, e: LOG.debug("Socket error exception %s", str(e)) err = e.args[0] # ignore non-fatal errors if (err != errno.EAGAIN and err != errno.EWOULDBLOCK and err != errno.EINTR): # otherwise, unrecoverable: connection.close_input() raise # caller must handle except Exception, e: # beats me... assume fatal LOG.debug("unknown socket exception %s", str(e)) connection.close_input() raise # caller must handle if sock_data: count = connection.process_input( sock_data ) else: LOG.debug("Socket closed") count = Connection.EOS connection.close_input() return count def write_socket_output(connection, socket_obj): """Write data to the network layer. Can support both blocking and non-blocking sockets. """ count = connection.has_output if count <= 0: return count # 0 or EOS data = connection.output_data() try: count = socket_obj.send(data) except socket.timeout, e: LOG.debug("Socket timeout exception %s", str(e)) raise # caller must handle except socket.error, e: LOG.debug("Socket error exception %s", str(e)) err = e.args[0] # ignore non-fatal errors if (err != errno.EAGAIN and err != errno.EWOULDBLOCK and err != errno.EINTR): # otherwise, unrecoverable connection.close_output() raise except Exception, e: # beats me... assume fatal LOG.debug("unknown socket exception %s", str(e)) connection.close_output() raise if count > 0: connection.output_written(count) elif data: LOG.debug("Socket closed") count = Connection.EOS connection.close_output() return count