OLD | NEW |
| (Empty) |
1 import traceback | |
2 | |
3 cdef class PyCFSocket | |
4 | |
5 cdef void socketCallBack(CFSocketRef s, CFSocketCallBackType _type, CFDataRef ad
dress, void *data, void *info): | |
6 cdef PyCFSocket socket | |
7 cdef int res | |
8 cdef int mask | |
9 socket = (<PyCFSocket>info) | |
10 #print "fileno = %r" % (socket.fileno,) | |
11 try: | |
12 if _type == kCFSocketReadCallBack: | |
13 if socket.readcallback: | |
14 socket.readcallback() | |
15 elif _type == kCFSocketWriteCallBack: | |
16 if socket.writecallback: | |
17 socket.writecallback() | |
18 elif _type == kCFSocketConnectCallBack: | |
19 if data == NULL: | |
20 res = 0 | |
21 else: | |
22 res = (<int*>data)[0] | |
23 if socket.connectcallback: | |
24 socket.connectcallback(res) | |
25 except: | |
26 traceback.print_exc() | |
27 | |
28 cdef void gilSocketCallBack(CFSocketRef s, CFSocketCallBackType _type, CFDataRef
address, void *data, void *info): | |
29 cdef PyGILState_STATE gil | |
30 gil = PyGILState_Ensure() | |
31 socketCallBack(s, _type, address, data, info) | |
32 PyGILState_Release(gil) | |
33 | |
34 cdef class PyCFSocket: | |
35 cdef public object readcallback | |
36 cdef public object writecallback | |
37 cdef public object connectcallback | |
38 cdef public object reading | |
39 cdef public object writing | |
40 cdef CFSocketRef cf | |
41 cdef CFRunLoopSourceRef source | |
42 cdef readonly CFSocketNativeHandle fileno | |
43 cdef CFSocketContext context | |
44 | |
45 def __new__(self, CFSocketNativeHandle fileno, readcallback=None, writecallb
ack=None, connectcallback=None): | |
46 #print "new socket %r" % (fileno,) | |
47 self.fileno = fileno | |
48 self.readcallback = readcallback | |
49 self.writecallback = writecallback | |
50 self.connectcallback = connectcallback | |
51 self.context.version = 0 | |
52 self.context.info = <void *>self | |
53 self.context.retain = NULL | |
54 self.context.release = NULL | |
55 self.context.copyDescription = NULL | |
56 self.reading = False | |
57 self.writing = False | |
58 self.cf = CFSocketCreateWithNative(kCFAllocatorDefault, fileno, kCFSocke
tConnectCallBack | kCFSocketReadCallBack | kCFSocketWriteCallBack, <CFSocketCall
Back>&gilSocketCallBack, &self.context) | |
59 if self.cf == NULL: | |
60 raise ValueError("Invalid Socket") | |
61 self.source = CFSocketCreateRunLoopSource(kCFAllocatorDefault, self.cf,
10000) | |
62 if self.source == NULL: | |
63 raise ValueError("Couldn't create runloop source") | |
64 #print "made new socket" | |
65 | |
66 def update(self): | |
67 cdef int mask | |
68 cdef int offmask | |
69 cdef int automask | |
70 mask = kCFSocketConnectCallBack | kCFSocketAcceptCallBack | |
71 offmask = 0 | |
72 automask = kCFSocketAutomaticallyReenableAcceptCallBack | |
73 if self.reading: | |
74 mask = mask | kCFSocketReadCallBack | |
75 automask = automask | kCFSocketAutomaticallyReenableReadCallBack | |
76 else: | |
77 offmask = offmask | kCFSocketReadCallBack | |
78 if self.writing: | |
79 mask = mask | kCFSocketWriteCallBack | |
80 automask = automask | kCFSocketAutomaticallyReenableWriteCallBack | |
81 else: | |
82 offmask = offmask | kCFSocketWriteCallBack | |
83 CFSocketDisableCallBacks(self.cf, offmask) | |
84 CFSocketEnableCallBacks(self.cf, mask) | |
85 CFSocketSetSocketFlags(self.cf, automask) | |
86 | |
87 | |
88 def startReading(self): | |
89 self.reading = True | |
90 self.update() | |
91 | |
92 def stopReading(self): | |
93 self.reading = False | |
94 self.update() | |
95 | |
96 def startWriting(self): | |
97 self.writing = True | |
98 self.update() | |
99 | |
100 def stopWriting(self): | |
101 self.writing = False | |
102 self.update() | |
103 | |
104 def __dealloc__(self): | |
105 #print "PyCFSocket(%r).__dealloc__()" % (self.fileno,) | |
106 if self.source != NULL: | |
107 CFRelease(self.source) | |
108 if self.cf != NULL: | |
109 CFSocketInvalidate(self.cf) | |
110 CFRelease(self.cf) | |
111 #print "__dealloc__()" | |
OLD | NEW |