         socket: L2CAPSocket,
         maximumTransmissionUnit: ATTMaximumTransmissionUnit = .default,
         maximumPreparedWrites: Int = 50,
-        log: ((String) -> ())? = nil
+        log: ((String) -> ())? = nil,
+        willRead: ((_ uuid: BluetoothUUID, _ handle: UInt16, _ value: Data, _ offset: Int) -> ATTError?)? = nil,
+        willWrite: ((_ uuid: BluetoothUUID, _ handle: UInt16, _ value: Data, _ newValue: Data) -> ATTError?)? = nil,
+        didWrite: ((_ uuid: BluetoothUUID, _ handle: UInt16, _ value: Data) -> Void)? = nil
     ) async {
         // set initial MTU and register handlers
         self.maximumPreparedWrites = maximumPreparedWrites
         self.preferredMaximumTransmissionUnit = maximumTransmissionUnit
         self.connection = await ATTConnection(socket: socket, log: log)
+        self.log = log
+        self.willRead = willRead
+        self.willWrite = willWrite
+        self.didWrite = didWrite
         // async register handlers
         await self.registerATTHandlers()
     }

public actor GATTServer {
    
    // MARK: - Properties
    
    public var log: ((String) -> ())?
    
    public var maximumTransmissionUnit: ATTMaximumTransmissionUnit {
        get async {
            return await self.connection.maximumTransmissionUnit

    
    public var database = GATTDatabase()
    
    internal let log: ((String) -> ())?
    
    internal let willRead: ((_ uuid: BluetoothUUID, _ handle: UInt16, _ value: Data, _ offset: Int) -> ATTError?)?
    
    internal let willWrite: ((_ uuid: BluetoothUUID, _ handle: UInt16, _ value: Data, _ newValue: Data) -> ATTError?)?
    
    internal let didWrite: ((_ uuid: BluetoothUUID, _ handle: UInt16, _ value: Data) -> Void)?
    
    // Don't modify
    internal let connection: ATTConnection
    
    internal private(set) var preparedWrites = [PreparedWrite]()
    
    // MARK: - Initialization
    
