/* * Copyright (c) 2015 Dmitry Bakhvalov * * SPDX-FileCopyrightText: 2024 Hiredict Contributors * SPDX-FileCopyrightText: 2024 Dmitry Bakhvalov * * SPDX-License-Identifier: BSD-3-Clause * SPDX-License-Identifier: LGPL-3.0-or-later * */ #ifndef __HIREDICT_MACOSX_H__ #define __HIREDICT_MACOSX_H__ #include #include "../hiredict.h" #include "../async.h" typedef struct { redictAsyncContext *context; CFSocketRef socketRef; CFRunLoopSourceRef sourceRef; } RedictRunLoop; static int freeRedictRunLoop(RedictRunLoop* redictRunLoop) { if( redictRunLoop != NULL ) { if( redictRunLoop->sourceRef != NULL ) { CFRunLoopSourceInvalidate(redictRunLoop->sourceRef); CFRelease(redictRunLoop->sourceRef); } if( redictRunLoop->socketRef != NULL ) { CFSocketInvalidate(redictRunLoop->socketRef); CFRelease(redictRunLoop->socketRef); } hi_free(redictRunLoop); } return REDICT_ERR; } static void redictMacOSAddRead(void *privdata) { RedictRunLoop *redictRunLoop = (RedictRunLoop*)privdata; CFSocketEnableCallBacks(redictRunLoop->socketRef, kCFSocketReadCallBack); } static void redictMacOSDelRead(void *privdata) { RedictRunLoop *redictRunLoop = (RedictRunLoop*)privdata; CFSocketDisableCallBacks(redictRunLoop->socketRef, kCFSocketReadCallBack); } static void redictMacOSAddWrite(void *privdata) { RedictRunLoop *redictRunLoop = (RedictRunLoop*)privdata; CFSocketEnableCallBacks(redictRunLoop->socketRef, kCFSocketWriteCallBack); } static void redictMacOSDelWrite(void *privdata) { RedictRunLoop *redictRunLoop = (RedictRunLoop*)privdata; CFSocketDisableCallBacks(redictRunLoop->socketRef, kCFSocketWriteCallBack); } static void redictMacOSCleanup(void *privdata) { RedictRunLoop *redictRunLoop = (RedictRunLoop*)privdata; freeRedictRunLoop(redictRunLoop); } static void redictMacOSAsyncCallback(CFSocketRef __unused s, CFSocketCallBackType callbackType, CFDataRef __unused address, const void __unused *data, void *info) { redictAsyncContext* context = (redictAsyncContext*) info; switch (callbackType) { case kCFSocketReadCallBack: redictAsyncHandleRead(context); break; case kCFSocketWriteCallBack: redictAsyncHandleWrite(context); break; default: break; } } static int redictMacOSAttach(redictAsyncContext *redictAsyncCtx, CFRunLoopRef runLoop) { redictContext *redictCtx = &(redictAsyncCtx->c); /* Nothing should be attached when something is already attached */ if( redictAsyncCtx->ev.data != NULL ) return REDICT_ERR; RedictRunLoop* redictRunLoop = (RedictRunLoop*) hi_calloc(1, sizeof(RedictRunLoop)); if (redictRunLoop == NULL) return REDICT_ERR; /* Setup redict stuff */ redictRunLoop->context = redictAsyncCtx; redictAsyncCtx->ev.addRead = redictMacOSAddRead; redictAsyncCtx->ev.delRead = redictMacOSDelRead; redictAsyncCtx->ev.addWrite = redictMacOSAddWrite; redictAsyncCtx->ev.delWrite = redictMacOSDelWrite; redictAsyncCtx->ev.cleanup = redictMacOSCleanup; redictAsyncCtx->ev.data = redictRunLoop; /* Initialize and install read/write events */ CFSocketContext socketCtx = { 0, redictAsyncCtx, NULL, NULL, NULL }; redictRunLoop->socketRef = CFSocketCreateWithNative(NULL, redictCtx->fd, kCFSocketReadCallBack | kCFSocketWriteCallBack, redictMacOSAsyncCallback, &socketCtx); if( !redictRunLoop->socketRef ) return freeRedictRunLoop(redictRunLoop); redictRunLoop->sourceRef = CFSocketCreateRunLoopSource(NULL, redictRunLoop->socketRef, 0); if( !redictRunLoop->sourceRef ) return freeRedictRunLoop(redictRunLoop); CFRunLoopAddSource(runLoop, redictRunLoop->sourceRef, kCFRunLoopDefaultMode); return REDICT_OK; } #endif