Как мне обработать CFSocketCallBackType.dataCallback в Swift?

Вся документация и примеры говорят, что если сокет CFSocketCallBack выноска дается .dataCallback как его второй параметр (callbackType), это означает, что четвертый (data) можно привести к CFData объект, содержащий все данные, предварительно прочитанные из сокета.

Однако, когда я пытаюсь сделать это, это терпит неудачу:

private func myCallout(socket: CFSocket?,
                       callBackType: CFSocketCallBackType,
                       address: CFData?,
                       callBackTypeMetaData: UnsafeRawPointer?,
                       info: UnsafeMutableRawPointer?) -> Void {

    // Behavior inferred from Developer
    // https://developer.apple.com/documentation/corefoundation/cfsocketcallback

    guard
        let info = info,
        let socket = socket
        else {
        return assertionFailure("Socket may have gone out of scope before response")
    }

    // <REDACTED>


    if callBackType == .dataCallBack {
        guard let data = callBackTypeMetaData?.load(as: CFData.self) else {
            return assertionFailure("Data Callback's metadata was not a CFData object")
        }

        foo(data as Data) // Crashes here
    }

    // <REDACTED>
}

Крушение, которое я получаю, таково:

Thread 1: EXC_BREAKPOINT (code=EXC_I386_BPT, subcode=0x0).

В отладчике, когда я набираю это:

(lldb) po callBackTypeMetaData!.load(as: CFData.self)

он просто печатает адрес указателя (также довольно высокий; только два значимых 0 с). Однако, когда я набираю это:

(lldb) po callBackTypeMetaData!.load(as: CFData.self) as Data

Это печатает это:

error: Execution was interrupted, reason: EXC_BREAKPOINT (code=EXC_I386_BPT, subcode=0x0).
The process has been returned to the state before expression evaluation.

Таким образом, кажется, что я не совсем CFData, но это достаточно близко, чтобы казаться похожим на это на поверхности, пока что-то фактически не пытается прочитать это как таковое.

Итак, что здесь происходит, где мои данные и как я могу это исправить?

1 ответ

Решение
data = callBackTypeMetaData!.load(as: CFData.self)

читает CFData указатель из области памяти, которая callBackTypeMetaData! указывает на. То, что вы хотите, это "переосмыслить" необработанный указатель как CFData (или же NSData) указатель:

if callBackType == .dataCallBack {
    if let rawPointer = callBackTypeMetaData  {
        let data = Unmanaged<NSData>.fromOpaque(rawPointer).takeUnretainedValue() as Data
        // ...
    }
}
Другие вопросы по тегам