1 //
2 // Created by Дмитрий Бахвалов on 13.07.15.
3 // Copyright (c) 2015 Dmitry Bakhvalov. All rights reserved.
4 //
5
6 #ifndef __HIREDIS_MACOSX_H__
7 #define __HIREDIS_MACOSX_H__
8
9 #include <CoreFoundation/CoreFoundation.h>
10
11 #include "../hiredis.h"
12 #include "../async.h"
13
14 typedef struct {
15 redisAsyncContext *context;
16 CFSocketRef socketRef;
17 CFRunLoopSourceRef sourceRef;
18 } RedisRunLoop;
19
freeRedisRunLoop(RedisRunLoop * redisRunLoop)20 static int freeRedisRunLoop(RedisRunLoop* redisRunLoop) {
21 if( redisRunLoop != NULL ) {
22 if( redisRunLoop->sourceRef != NULL ) {
23 CFRunLoopSourceInvalidate(redisRunLoop->sourceRef);
24 CFRelease(redisRunLoop->sourceRef);
25 }
26 if( redisRunLoop->socketRef != NULL ) {
27 CFSocketInvalidate(redisRunLoop->socketRef);
28 CFRelease(redisRunLoop->socketRef);
29 }
30 free(redisRunLoop);
31 }
32 return REDIS_ERR;
33 }
34
redisMacOSAddRead(void * privdata)35 static void redisMacOSAddRead(void *privdata) {
36 RedisRunLoop *redisRunLoop = (RedisRunLoop*)privdata;
37 CFSocketEnableCallBacks(redisRunLoop->socketRef, kCFSocketReadCallBack);
38 }
39
redisMacOSDelRead(void * privdata)40 static void redisMacOSDelRead(void *privdata) {
41 RedisRunLoop *redisRunLoop = (RedisRunLoop*)privdata;
42 CFSocketDisableCallBacks(redisRunLoop->socketRef, kCFSocketReadCallBack);
43 }
44
redisMacOSAddWrite(void * privdata)45 static void redisMacOSAddWrite(void *privdata) {
46 RedisRunLoop *redisRunLoop = (RedisRunLoop*)privdata;
47 CFSocketEnableCallBacks(redisRunLoop->socketRef, kCFSocketWriteCallBack);
48 }
49
redisMacOSDelWrite(void * privdata)50 static void redisMacOSDelWrite(void *privdata) {
51 RedisRunLoop *redisRunLoop = (RedisRunLoop*)privdata;
52 CFSocketDisableCallBacks(redisRunLoop->socketRef, kCFSocketWriteCallBack);
53 }
54
redisMacOSCleanup(void * privdata)55 static void redisMacOSCleanup(void *privdata) {
56 RedisRunLoop *redisRunLoop = (RedisRunLoop*)privdata;
57 freeRedisRunLoop(redisRunLoop);
58 }
59
redisMacOSAsyncCallback(CFSocketRef __unused s,CFSocketCallBackType callbackType,CFDataRef __unused address,const void __unused * data,void * info)60 static void redisMacOSAsyncCallback(CFSocketRef __unused s, CFSocketCallBackType callbackType, CFDataRef __unused address, const void __unused *data, void *info) {
61 redisAsyncContext* context = (redisAsyncContext*) info;
62
63 switch (callbackType) {
64 case kCFSocketReadCallBack:
65 redisAsyncHandleRead(context);
66 break;
67
68 case kCFSocketWriteCallBack:
69 redisAsyncHandleWrite(context);
70 break;
71
72 default:
73 break;
74 }
75 }
76
redisMacOSAttach(redisAsyncContext * redisAsyncCtx,CFRunLoopRef runLoop)77 static int redisMacOSAttach(redisAsyncContext *redisAsyncCtx, CFRunLoopRef runLoop) {
78 redisContext *redisCtx = &(redisAsyncCtx->c);
79
80 /* Nothing should be attached when something is already attached */
81 if( redisAsyncCtx->ev.data != NULL ) return REDIS_ERR;
82
83 RedisRunLoop* redisRunLoop = (RedisRunLoop*) calloc(1, sizeof(RedisRunLoop));
84 if( !redisRunLoop ) return REDIS_ERR;
85
86 /* Setup redis stuff */
87 redisRunLoop->context = redisAsyncCtx;
88
89 redisAsyncCtx->ev.addRead = redisMacOSAddRead;
90 redisAsyncCtx->ev.delRead = redisMacOSDelRead;
91 redisAsyncCtx->ev.addWrite = redisMacOSAddWrite;
92 redisAsyncCtx->ev.delWrite = redisMacOSDelWrite;
93 redisAsyncCtx->ev.cleanup = redisMacOSCleanup;
94 redisAsyncCtx->ev.data = redisRunLoop;
95
96 /* Initialize and install read/write events */
97 CFSocketContext socketCtx = { 0, redisAsyncCtx, NULL, NULL, NULL };
98
99 redisRunLoop->socketRef = CFSocketCreateWithNative(NULL, redisCtx->fd,
100 kCFSocketReadCallBack | kCFSocketWriteCallBack,
101 redisMacOSAsyncCallback,
102 &socketCtx);
103 if( !redisRunLoop->socketRef ) return freeRedisRunLoop(redisRunLoop);
104
105 redisRunLoop->sourceRef = CFSocketCreateRunLoopSource(NULL, redisRunLoop->socketRef, 0);
106 if( !redisRunLoop->sourceRef ) return freeRedisRunLoop(redisRunLoop);
107
108 CFRunLoopAddSource(runLoop, redisRunLoop->sourceRef, kCFRunLoopDefaultMode);
109
110 return REDIS_OK;
111 }
112
113 #endif
114
115