def __init__(self, host, port, conn_handler, connect_error_handler, timeout=None): self.host = host self.port = port self.conn_handler = conn_handler self.connect_error_handler = connect_error_handler self._timeout_ev = None self._conn_handled = False self._error_sent = False # TODO: socket.getaddrinfo(); needs to be non-blocking. if event: sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.setblocking(0) event.write(sock, self.handle_connect, sock).add() try: err = sock.connect_ex( (host, port)) # FIXME: check for DNS errors, etc. except socket.error, why: self.handle_error(why) return if err != errno.EINPROGRESS: # FIXME: others? self.handle_error(err)
def __init__(self, host, port, conn_handler, connect_error_handler, timeout=None): self.host = host self.port = port self.conn_handler = conn_handler self.connect_error_handler = connect_error_handler self._timeout_ev = None self._conn_handled = False self._error_sent = False sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.setblocking(0) event.write(sock, self.handle_connect, sock).add() try: err = sock.connect_ex((host, port)) except socket.error, why: self.handle_error(why) return
def notify_write(self): """ Set a read event on the socket, if one doesn't already exist. Used by the counterpart to notify that data is available for writing """ if self._ssl_sock == None: return if self._write_buf.len() > 0: self._write_hdler = event.write(self._ssl_sock, self._write_data)
def add_write(self): """Allow this instance to send data when it's possible. """ we = self._ev_write if we: if we.pending(): return self._ev_write = None self._ev_write = event.write(self.fileno(), self.handle_write) return
def add_write(self): """Allow this instance to send data when it's possible. """ we = getattr(self, '_ev_write', None) if we: if we.pending(): return self._ev_write = None self._ev_write = event.write(self._fileno, self._write_cb) return
def __init__(self, host, port, conn_handler, connect_error_handler, timeout=None): self.host = host self.port = port self.conn_handler = conn_handler self.connect_error_handler = connect_error_handler self._timeout_ev = None self._conn_handled = False self._error_sent = False # TODO: socket.getaddrinfo(); needs to be non-blocking. if event: sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.setblocking(0) event.write(sock, self.handle_connect, sock).add() try: err = sock.connect_ex((host, port)) # FIXME: check for DNS errors, etc. except socket.error, why: self.handle_error(why) return if err != errno.EINPROGRESS: # FIXME: others? self.handle_error(err)
def add_descriptor(self, fileno, read=None, write=None, exc=None): if read: evt = event.read(fileno, read, fileno) self.readers[fileno] = evt, read if write: evt = event.write(fileno, write, fileno) self.writers[fileno] = evt, write if exc: self.excs[fileno] = exc return fileno
def wrapped_func(self, *args): try: func(self, *args) except ssl.SSLError, err: self._clear_hdlers() if err.args[0] == ssl.SSL_ERROR_WANT_READ: self._read_hdler = event.read(self._ssl_sock, wrapped_func, self, *args) elif err.args[0] == ssl.SSL_ERROR_WANT_WRITE: self._write_hdler = event.write(self._ssl_sock, wrapped_func, self, *args) else: traceback.print_exc() self.close() self._counterpart.close()
class _TcpConnection(asyncore.dispatcher): "Base class for a TCP connection." write_bufsize = 16 read_bufsize = 1024 * 4 def __init__(self, sock, is_server, host, port, use_ssl, certfile, keyfile, connect_error_handler=None): self.use_ssl = use_ssl self.socket = sock if is_server: if self.use_ssl: try: self.socket = ssl.wrap_socket( sock, server_side=True, certfile=certfile, keyfile=keyfile, do_handshake_on_connect=False) self.socket.do_handshake() except ssl.SSLError, err: if err.args[0] == ssl.SSL_ERROR_WANT_READ: select.select([self.socket], [], []) elif err.args[0] == ssl.SSL_ERROR_WANT_WRITE: select.select([], [self.socket], []) else: raise self.host = host self.port = port self.connect_error_handler = connect_error_handler self.read_cb = None self.close_cb = None self._close_cb_called = False self.pause_cb = None self.tcp_connected = True # always handed a connected socket (we assume) self._paused = False # TODO: should be paused by default self._closing = False self._write_buffer = [] if event: self._revent = event.read(self.socket, self.handle_read) self._wevent = event.write(self.socket, self.handle_write) else: # asyncore asyncore.dispatcher.__init__(self, self.socket)
def __init__(self, sock, host, port, connect_error_handler=None): self.socket = sock self.host = host self.port = port self.connect_error_handler = connect_error_handler self.read_cb = None self.close_cb = None self._close_cb_called = False self.pause_cb = None self.tcp_connected = True self._paused = False self._closing = False self.write_buffer = [] self._revent = event.read(sock, self.handle_read) self._wevent = event.write(sock, self.handle_write)
def add(self, evtype, fileno, real_cb, real_tb, mac): # this is stupid: pyevent won't call a callback unless it's a function, # so we have to force it to be one here if isinstance(real_cb, types.BuiltinMethodType): def cb(_d): real_cb(_d) else: cb = real_cb if evtype is READ: evt = event.read(fileno, cb, fileno) elif evtype is WRITE: evt = event.write(fileno, cb, fileno) return super(Hub, self).add(evtype, fileno, evt, real_tb, mac)
def send_data(self, data): "Send the data over this connection." def _handle_write(): try: sent = self._sock.send(self._to_be_sent) except socket.error, e: print e, e.args[0] self._sock.close() self.handle_close(error=e.args[0]) return if sent < len(self._to_be_sent): # all the data to be sent has not been sent yet. # so reschedule a new write event to send the rest of the data. self._to_be_sent = self._to_be_sent[sent:] ev = event.write(self._sock, _handle_write) ev.add()
def __init__(self, sock, addr): self.service = None self.application = None self.sock = sock self.remote_addr = addr self._rev = event.read(self.sock, eventbase.event_read_handler, self) self._wev = event.write(self.sock, eventbase.event_write_handler, self) self._renable = False self._wenable = False # Mix-Ins self._sighand = {} self._setup_mixins() self.closed = False self.emit('prot.new_connection')
def add(self, evtype, fileno, real_cb): # this is stupid: pyevent won't call a callback unless it's a function, # so we have to force it to be one here if isinstance(real_cb, types.BuiltinMethodType): def cb(_d): real_cb(_d) else: cb = real_cb if evtype is READ: evt = event.read(fileno, cb, fileno) elif evtype is WRITE: evt = event.write(fileno, cb, fileno) listener = FdListener(evtype, fileno, evt) self.listeners[evtype].setdefault(fileno, []).append(listener) return listener
def __init__(self, sock, host, port): self.socket = sock self.host = host self.port = port self.read_cb = None self.close_cb = None self._close_cb_called = False self.pause_cb = None self.tcp_connected = True # we assume a connected socket self._paused = False # TODO: should be paused by default self._closing = False self._write_buffer = [] if event: self._revent = event.read(sock, self.handle_read) self._wevent = event.write(sock, self.handle_write) else: # asyncore asyncore.dispatcher.__init__(self, sock)
def __init__( self, family=socket.AF_INET, type=socket.SOCK_STREAM, \ protocol=socket.IPPROTO_IP, read_cb=None, accept_cb=None, \ close_cb=None, error_cb=None, output_empty_cb=None, sock=None, \ debug=False, logger=None, max_read_buffer=0, **kwargs): """ Initialize the socket. If no read_cb defined, socket will only be used for reading. If this socket will be used for accepting new connections, set read_cb here and it will be passed to new sockets. You can also set accept_cb and be notified with an EventSocket object on accept(). The error_cb will be called if there are any errors on the socket. The args to it will be this socket, an error message, and an optional exception. The close_cb will be called when this socket closes, with this socket as its argument. If needed, you can wrap an existing socket by setting the sock argument to a socket object. """ self._debug = debug self._logger = logger if self._debug and not self._logger: print 'WARNING: to debug EventSocket, must provide a logger' self._debug = False # There various events we may or may not schedule self._read_event = None self._write_event = None self._accept_event = None self._connect_event = None self._pending_read_cb_event = None # Cache the peername so we can include it in logs even if the socket # is closed. Note that connect() and bind() have to be the ones to do # that work. self._peername = 'unknown' if sock: self._sock = sock try: self._peername = "%s:%d"%self._sock.getpeername() # Like connect(), only initialize these if the socket is already connected. self._read_event = event.read( self._sock, self._protected_cb, self._read_cb ) self._write_event = event.write( self._sock, self._protected_cb, self._write_cb ) except socket.error, e: # unconnected pass
def _connect_cb(self, timeout_at, *args, **kwargs): ''' Local support for synch and asynch connect. Required because `event.timeout` doesn't support kwargs. They are spec'd though so that we can branch how exceptions are handled. ''' err = self._sock.connect_ex( *args ) if not err: self._peername = "%s:%d"%self._sock.getpeername() self._read_event = event.read( self._sock, self._protected_cb, self._read_cb ) self._write_event = event.write( self._sock, self._protected_cb, self._write_cb ) if self._connect_event: self._connect_event.delete() self._connect_event = None elif err in (errno.EINPROGRESS,errno.EALREADY): # Only track timeout if we're about to re-schedule. Should only receive # these on a non-blocking socket. if isinstance(timeout_at,float) and time.time()>timeout_at: self._error_msg = 'timeout connecting to %s'%str(args) self.close() return if self._connect_event: self._connect_event.delete() # Checking every 100ms seems to be a reasonable amount of frequency. If # requested this too can be configurable. self._connect_event = event.timeout(0.1, self._connect_cb, timeout_at, *args) else: if self._connect_event: self._connect_event.delete() self._error_msg = os.strerror(err) serr = socket.error( err, self._error_msg ) if kwargs.get('immediate_raise'): raise serr else: self._handle_error( serr )
print e, e.args[0] self._sock.close() self.handle_close(error=e.args[0]) return if sent < len(self._to_be_sent): # all the data to be sent has not been sent yet. # so reschedule a new write event to send the rest of the data. self._to_be_sent = self._to_be_sent[sent:] ev = event.write(self._sock, _handle_write) ev.add() # append data to the write buffer self._to_be_sent += data # schedule a write event ev = event.write(self._sock, _handle_write) ev.add() def handle_close(self, error=None): """Callback func called when the socket closes. User is expected to override this method and do any clean-up.""" if error is not None: print "Connection closed due to error (errno = %d)" % error else: print "Connection closed." class BaseServer(object): def __init__(self, addr=('', 8080), connection_handler=BaseConnectionHandler): self.addr, self.port = addr
def send(self, data, *args): event.write(self.sock, self.handle_send, data) return self.write_channel.receive()
def start(self, start_read=True): """ Begin scheduling events to handle data on the socket """ if start_read: self._read_hdler = event.read(self._ssl_sock, self.handshake) else: self._write_hdler = event.write(self._ssl_sock, self.handshake)
def _reschedule(self): self._clear_hdlers() if self._write_buf.len() > 0: self._write_hdler = event.write(self._ssl_sock, self._write_data) if self._read_buf.len() < recvbuf_max: self._read_hdler = event.read(self._ssl_sock, self._read_data)