提供回调函数作为特定的pointertype

时间:2013-10-22 15:16:03

标签: objective-c pointers networking ssl

我目前正在使用Mac上的Objective-C中的服务器,该服务器侦听特定端口以获取传入数据。它已经可以在两个方向上基于NSStream进行未加密的数据传输。

在下一步中,我想通过SSL / TLS保护连接。目前,我正在关注他们在this页面上的文档中描述的方法。在 Overview 中,他们描述了构建SSL连接的典型序列。

我现在失败的地方是我必须提供表格

的指针
typedef OSStatus (*SSLReadFunc) (
   SSLConnectionRef connection,
   void *data,
   size_t *dataLength
);

在一个为SSL-Connection设置I / O函数的方法中,负责对象可以调用这些方法来读取和写入我的流。我已经写了两个方法

// Called by the secure transport to write data on the stream
-(OSStatus)sslWriteCallbackFunction:(SSLContextRef)context data:(const void *)data dataLength:(size_t)dataLength sizeOfProcessedData:(size_t *)processed{
    processed = (size_t *)[_writeStream write:data maxLength:dataLength];
    if (processed < 0)
        return errSSLProtocol;
    else if (processed==0)
        return 0;
    else
        return errSSLWouldBlock;
}

// Called by the secure transport to read data from the stream
-(OSStatus) sslReadCallbackFunction:(SSLContextRef)context data:(const void *)data dataLength:(size_t)dataLength{
    uint8_t buffer[dataLength];
    NSInteger err = [_readStream read:buffer maxLength:dataLength];

    if (err < 0)
        // Error
        return errSSLProtocol;
    else if (err==0)
        // All bytes have been read
        return 0;
    else
        // err corresponds to the number of bytes read, so there are still bytes available
        dataLength = err;
        return errSSLWouldBlock;
} 

并希望在签名

的方法中设置它们
OSStatus SSLSetIOFuncs (
   SSLContextRef context,
   SSLReadFunc readFunc,
   SSLWriteFunc writeFunc
);

分别通过sslReadCallbackFunction和write方法传递方法readFunc

现在,我如何创建指向上述形式的两种方法之一的指针。我已经尝试了很多,如果有人可以帮助我或指出正确的方向,我将非常感激。我使用选择器,方法名前面的&,使用self的方法,....

感谢任何帮助,请注意我是Objective-C的新手;)

1 个答案:

答案 0 :(得分:0)

API需要一个指向具有给定签名的C函数的指针,而不是Objective-C方法。如果你仍然想要处理方法而不是函数的回调,你需要使用“trampoline”函数。这是一个简单调用Objective-C方法的小函数。通常,回调函数包括您提供给API并传递给函数的用户上下文指针。这很方便,因为您可以传递self并使用它来轻松地向正确的ObjC实例发送消息。像这样:

OSStatus MySSLReadCallbackFunction(SSLConnectionRef connection, void *data, size_t *ioDataLength)
{
    MySSLClass *obj = (__bridge MySSLClass *)connection
    return [obj sslReadFromConnection:connection intoBuffer:data length:ioDataLength];
}

// In the function that sets this stuff up:
SSLSetConnection(context, (__bridge void *)self);
SSLSetIOFuncs(context, MySSLReadCallbackFunction, MySSLWriteCallbackFunction);

Mark Dalrymple在他的博客上有关于这个一般问题的good post

请注意,正如该文章的评论中所提到的, 可以获得指向实现ObjC方法的底层C函数的指针。但是,实现ObjC方法的函数有两个“隐藏”参数(self_cmd),所以你不能强迫它们为这样的API设置正确的签名。