RSS

(root)/iphone/tappity : 52 : tappity/source/Tappity.m

To get this branch, use:
bzr branch /browse/iphone/tappity

« back to all changes in this revision

Viewing changes to tappity/source/Tappity.m

Dömötör Gulyás
2009-10-31 12:32:32
Revision ID: dognotdog@gmail.com-20091031113232-lvx5g6lwnze2ugpu
moves networking into common class

Show diffs side-by-side

added added

removed removed

30
30
NSString* TapLocationKey = @"tapLocation";
31
31
 
32
32
 
33
 
@interface Tappity (Private)
34
 
- (void) dataReceived: (NSData*) data;
35
 
@end
36
 
 
37
33
@implementation Tappity
38
34
 
39
 
- (BOOL) threadActive: (id) key
40
 
{
41
 
        return [[activeThreads objectForKey: key] boolValue];
42
 
}
43
 
 
44
 
- (void) threadWillExit: (id) key
45
 
{
46
 
        @synchronized (self)
47
 
        {
48
 
                [activeThreads removeObjectForKey: key];
49
 
                
50
 
                if (![activeThreads count])
51
 
                {
52
 
                        close(commsSocket);
53
 
                        commsSocket = -1;
54
 
                        
55
 
                        
56
 
                }
57
 
        }
58
 
}
59
 
 
60
 
- (void) receivingThread: (id) info
61
 
{
62
 
        NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
63
 
 
64
 
        @synchronized(self)
65
 
        {
66
 
                [self retain];
67
 
        }
68
 
 
69
 
        while ([self threadActive: info])
70
 
        {
71
 
                struct timeval tv;
72
 
                fd_set readfds;
73
 
                fd_set writefds;
74
 
                fd_set errorfds;
75
 
                int socket = -1;
76
 
                int maxSocket = -1;
77
 
                
78
 
                @synchronized(self)
79
 
                {
80
 
                        socket = commsSocket;
81
 
                }
82
 
 
83
 
                tv.tv_sec = 1;
84
 
                tv.tv_usec = 0;
85
 
 
86
 
                FD_ZERO(&readfds);
87
 
                FD_ZERO(&writefds);
88
 
                FD_ZERO(&errorfds);
89
 
 
90
 
                FD_SET(socket, &readfds);
91
 
                FD_SET(socket, &errorfds);
92
 
                maxSocket = MAX(maxSocket, socket);
93
 
                
94
 
                if (maxSocket < 0)
95
 
                {
96
 
                        //printf("No sockets, sleeping for a bit...\n");
97
 
                        usleep(1000000);
98
 
                        continue;
99
 
                }
100
 
 
101
 
                if (select(maxSocket+1, &readfds, &writefds, &errorfds, &tv) < 0)
102
 
                {
103
 
                        perror("select");
104
 
                        break;
105
 
                }
106
 
 
107
 
                if (FD_ISSET(socket, &readfds))
108
 
                {
109
 
                        //NSLog(@"receiving...");
110
 
                        if (!expectedMessageSize)
111
 
                        {
112
 
                                uint32_t header[2] = {0,0};
113
 
                                int actuallyRead = 0;
114
 
                        
115
 
                                actuallyRead = recv(socket, header, 8, MSG_PEEK);
116
 
                                
117
 
                                if (actuallyRead == 8)
118
 
                                {
119
 
                                        actuallyRead = recv(socket, header, 8, 0);
120
 
                                        expectedMessageSize = ntohl(header[1]);
121
 
                                        currentMessageId = ntohl(header[0]);
122
 
                                        currentData = [[NSMutableData alloc] initWithLength: expectedMessageSize];
123
 
                                }
124
 
                                else if (actuallyRead == -1)
125
 
                                {
126
 
                                        //close(commsSocket);
127
 
                                        //self->commsSocket = 0;
128
 
                                        if (errno != ETIMEDOUT)
129
 
                                        {
130
 
                                                printf("Connection dropped with error.\n");
131
 
                                                break;
132
 
                                        }
133
 
                                }
134
 
                                else if (actuallyRead == 0)
135
 
                                {
136
 
                                        printf("remote socket closed.\n");
137
 
                                        break;
138
 
                                }
139
 
                        }
140
 
                        else
141
 
                        {
142
 
                                size_t readAmount = expectedMessageSize - currentlyRead;
143
 
                                int actuallyRead = 0;
144
 
                        
145
 
                                actuallyRead = recv(socket, [currentData mutableBytes] + currentlyRead, readAmount, 0);
146
 
                                if (actuallyRead == -1)
147
 
                                {
148
 
                                        printf("Connection dropped with error.\n");
149
 
                                        break;
150
 
                                }
151
 
                                else if (actuallyRead == 0)
152
 
                                {
153
 
                                        printf("remote socket closed.\n");
154
 
                                        break;
155
 
                                }
156
 
 
157
 
                                currentlyRead += actuallyRead;
158
 
                                
159
 
                                if (currentlyRead == expectedMessageSize)
160
 
                                {
161
 
                                        @synchronized(self)
162
 
                                        {
163
 
                                                expectedMessageSize = 0;
164
 
                                                /*
165
 
                                                if (!receivedPackets)
166
 
                                                        receivedPackets = [[NSMutableArray alloc] init];
167
 
                                                [receivedPackets addObject: currentData];
168
 
                                                [currentData release];
169
 
                                                */
170
 
                                                
171
 
                                        }
172
 
 
173
 
                                        if (receiveDataOnMainThread)
174
 
                                                [self performSelectorOnMainThread: @selector(dataReceived:) withObject: [NSDictionary dictionaryWithObjectsAndKeys: [NSNumber numberWithInt: currentMessageId], TapIdKey, currentData, TapDataKey, nil] waitUntilDone: NO];
175
 
                                        else
176
 
                                                [self dataReceived: [NSDictionary dictionaryWithObjectsAndKeys: [NSNumber numberWithInt: currentMessageId], TapIdKey, currentData, TapDataKey, nil]];
177
 
 
178
 
                                        currentData = nil;
179
 
                                        currentlyRead = 0;
180
 
                                }
181
 
                        }
182
 
 
183
 
                }
184
 
        }
185
 
        
186
 
        [self threadWillExit: info];
187
 
 
188
 
        @synchronized(self)
189
 
        {
190
 
                [self release];
191
 
        }
192
 
 
193
 
        [info release];
194
 
        [pool drain];
195
 
}
196
 
 
197
 
 
198
 
- (void) runThreadWithSelector: (SEL) selector
199
 
{
200
 
        @synchronized(self)
201
 
        {
202
 
                if (!activeThreads)
203
 
                        activeThreads = [[NSMutableDictionary alloc] init];
204
 
                id number = [NSNumber numberWithInt: threadIds++];
205
 
 
206
 
                [activeThreads setObject: [NSNumber numberWithBool: YES] forKey: number];
207
 
                [NSThread detachNewThreadSelector: selector toTarget: self withObject: [number retain]];
208
 
        }
209
 
}
210
 
 
211
 
- (void) sendData: (NSData*) tapData withIdentifier: (NSInteger) messageId
212
 
{               
213
 
        [sendLock lock];
214
 
 
215
 
        if (!sendQueue)
216
 
                sendQueue = [[NSMutableArray alloc] init];
217
 
 
218
 
        [sendQueue addObject: [NSDictionary dictionaryWithObjectsAndKeys: [NSNumber numberWithInteger: messageId], TapIdKey, tapData, TapDataKey, nil]];
219
 
        
220
 
        [sendLock signal];
221
 
        [sendLock unlock];
222
 
                
223
 
}
224
 
 
225
 
 
226
 
- (void) sendingThread: (id) info
227
 
{
228
 
        NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
229
 
 
230
 
        @synchronized(self)
231
 
        {
232
 
                [self retain];
233
 
        }
234
 
 
235
 
        while ([self threadActive: info])
236
 
        {
237
 
                [sendLock lock];
238
 
                        while (![sendQueue count])
239
 
                                [sendLock wait];
240
 
                                
241
 
                //NSLog(@"sending");
242
 
                
243
 
                NSDictionary* dict = [[sendQueue objectAtIndex: 0] retain];
244
 
                NSData* data = [dict objectForKey: TapDataKey];
245
 
                uint32_t messageId = [[dict objectForKey: TapIdKey] intValue];
246
 
                [sendQueue removeObjectAtIndex: 0];
247
 
                
248
 
                [sendLock unlock];
249
 
 
250
 
                size_t sizeToSend = 8;
251
 
                size_t dataSent = 0;
252
 
                uint32_t header[2] = {htonl(messageId), htonl([data length])};
253
 
                int err = 0;
254
 
                int socket = -1;
255
 
 
256
 
                @synchronized(self)
257
 
                {
258
 
                        socket = commsSocket;
259
 
                }
260
 
 
261
 
                while (dataSent < sizeToSend)
262
 
                {
263
 
                        if ((err = send(socket, header + dataSent, sizeToSend - dataSent, 0)) == -1)
264
 
                        {
265
 
                                perror("send");
266
 
                                break;
267
 
                        }
268
 
                        else
269
 
                                dataSent += err;
270
 
                }
271
 
                
272
 
                if (err != -1)
273
 
                {
274
 
                        sizeToSend = [data length];
275
 
                        dataSent = 0;
276
 
                        while (dataSent < sizeToSend)
277
 
                        {
278
 
                                if ((err = send(socket, [data bytes] + dataSent, sizeToSend - dataSent, 0)) == -1)
279
 
                                {
280
 
                                        perror("send");
281
 
                                        break;
282
 
                                }
283
 
                                else
284
 
                                        dataSent += err;
285
 
                                        
286
 
                        }
287
 
                }
288
 
                [dict release];
289
 
                
290
 
                if (err == -1)
291
 
                        break;
292
 
                
293
 
        }
294
 
        
295
 
 
296
 
        [self threadWillExit: info];
297
 
 
298
 
        @synchronized(self)
299
 
        {
300
 
                [self release];
301
 
        }
302
 
 
303
 
        [info release];
304
 
        [pool drain];
305
 
}
 
35
- (id) init
 
36
{
 
37
        if (!(self = [super init]))
 
38
                return nil;
 
39
 
 
40
 
 
41
 
 
42
        return self;
 
43
}
 
44
 
306
45
 
307
46
@end
308
47
 

Loggerhead 1.17 is a web-based interface for Bazaar branches