def _read(fdptr, data, dataLength): """ The SecureTransport SSL read callback. @param fdptr: reference value added via SSLSetConnection @type fdptr: ffi(int *) @param data: buffer to read data into @type data: ffi(void *) @param dataLength: length of the buffer to read into, and on return the actual length of data read @type dataLength: ffi(size_t *) """ # Get the associated L{Connection} object engine_id = ffi.cast("int *", fdptr)[0] engine = Connection.engines[engine_id] # If there are bytes pending in the L{Connection}s buffer, read as much # of those as possible, or return errSSLWouldBlock dlen = dataLength[0] rdata = ffi.buffer(data, dlen) if engine.getBytes(rdata, dlen) is None: dataLength[0] = 0 return security.errSSLWouldBlock return 0
def _write(fdptr, data, dataLength): """ The SecureTransport SSL write callback. @param fdptr: reference value added via SSLSetConnection @type fdptr: ffi(int *) @param data: buffer to write @type data: ffi(const void *) @param dataLength: length of the data to write, and on return the actual length of data written @type dataLength: ffi(size_t *) """ # Get the associated L{Connection} object engine_id = ffi.cast("int *", fdptr)[0] engine = Connection.engines[engine_id] # We always write everything in one go dlen = dataLength[0] wdata = ffi.buffer(data, dlen) engine.protocol.transport.write(wdata[:]) return 0
def _sslread(self, bytes): """ Wrapper for SecureTransport SSLRead method. @param bytes: maximum length of data to read @type bytes: L{int} @return: the data read @rtype: L{ffi.buffer} """ read = ffi.new("char[]", bytes) processed = ffi.new("size_t *") err = security.SSLRead(self.ctx, read, bytes, processed) if err == 0: response = ffi.buffer(read, processed[0]) return response elif err == security.errSSLWouldBlock: raise WantReadError elif err == security.errSSLClosedGraceful: raise ZeroReturnError else: self.shutdown() raise Error(err)