Rev 30 | Blame | Compare with Previous | Last modification | View Log | RSS feed
/** Licensed to the Apache Software Foundation (ASF) under one* or more contributor license agreements. See the NOTICE file* distributed with this work for additional information* regarding copyright ownership. The ASF licenses this file* to you under the Apache License, Version 2.0 (the* "License"); you may not use this file except in compliance* with the License. You may obtain a copy of the License at** http://www.apache.org/licenses/LICENSE-2.0** Unless required by applicable law or agreed to in writing,* software distributed under the License is distributed on an* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY* KIND, either express or implied. See the License for the* specific language governing permissions and limitations* under the License.*/#import <Foundation/Foundation.h>#import "TSocketServer.h"#import "TNSFileHandleTransport.h"#import "TProtocol.h"#import "TTransportException.h"#import <sys/socket.h>#include <netinet/in.h>NSString * const kTSocketServer_ClientConnectionFinishedForProcessorNotification = @"TSocketServer_ClientConnectionFinishedForProcessorNotification";NSString * const kTSocketServer_ProcessorKey = @"TSocketServer_Processor";NSString * const kTSockerServer_TransportKey = @"TSockerServer_Transport";@implementation TSocketServer- (id) initWithPort: (int) portprotocolFactory: (id <TProtocolFactory>) protocolFactoryprocessorFactory: (id <TProcessorFactory>) processorFactory;{self = [super init];mInputProtocolFactory = [protocolFactory retain];mOutputProtocolFactory = [protocolFactory retain];mProcessorFactory = [processorFactory retain];// create a socket.int fd = -1;CFSocketRef socket = CFSocketCreate(kCFAllocatorDefault, PF_INET, SOCK_STREAM, IPPROTO_TCP, 0, NULL, NULL);if (socket) {fd = CFSocketGetNative(socket);int yes = 1;setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (void *)&yes, sizeof(yes));struct sockaddr_in addr;memset(&addr, 0, sizeof(addr));addr.sin_len = sizeof(addr);addr.sin_family = AF_INET;addr.sin_port = htons(port);addr.sin_addr.s_addr = htonl(INADDR_ANY);NSData *address = [NSData dataWithBytes:&addr length:sizeof(addr)];if (CFSocketSetAddress(socket, (CFDataRef)address) != kCFSocketSuccess) {NSLog(@"*** Could not bind to address");return nil;}} else {NSLog(@"*** No server socket");return nil;}// wrap it in a file handle so we can get messages from itmSocketFileHandle = [[NSFileHandle alloc] initWithFileDescriptor: fdcloseOnDealloc: YES];// register for notifications of accepted incoming connections[[NSNotificationCenter defaultCenter] addObserver: selfselector: @selector(connectionAccepted:)name: NSFileHandleConnectionAcceptedNotificationobject: mSocketFileHandle];// tell socket to listen[mSocketFileHandle acceptConnectionInBackgroundAndNotify];NSLog(@"Listening on TCP port %d", port);return self;}- (void) dealloc {[[NSNotificationCenter defaultCenter] removeObject: self];[mInputProtocolFactory release];[mOutputProtocolFactory release];[mProcessorFactory release];[mSocketFileHandle release];[super dealloc];}- (void) connectionAccepted: (NSNotification *) aNotification{NSFileHandle * socket = [[aNotification userInfo] objectForKey: NSFileHandleNotificationFileHandleItem];// now that we have a client connected, spin off a thread to handle activity[NSThread detachNewThreadSelector: @selector(handleClientConnection:)toTarget: selfwithObject: socket];[[aNotification object] acceptConnectionInBackgroundAndNotify];}- (void) handleClientConnection: (NSFileHandle *) clientSocket{NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];TNSFileHandleTransport * transport = [[TNSFileHandleTransport alloc] initWithFileHandle: clientSocket];id<TProcessor> processor = [mProcessorFactory processorForTransport: transport];id <TProtocol> inProtocol = [mInputProtocolFactory newProtocolOnTransport: transport];id <TProtocol> outProtocol = [mOutputProtocolFactory newProtocolOnTransport: transport];@try {BOOL result = NO;do {NSAutoreleasePool * myPool = [[NSAutoreleasePool alloc] init];result = [processor processOnInputProtocol: inProtocol outputProtocol: outProtocol];[myPool release];} while (result);}@catch (TTransportException * te) {//NSLog(@"Caught transport exception, abandoning client connection: %@", te);}NSNotification * n = [NSNotification notificationWithName: kTSocketServer_ClientConnectionFinishedForProcessorNotificationobject: selfuserInfo: [NSDictionary dictionaryWithObjectsAndKeys:processor,kTSocketServer_ProcessorKey,transport,kTSockerServer_TransportKey,nil]];[[NSNotificationCenter defaultCenter] performSelectorOnMainThread: @selector(postNotification:) withObject: n waitUntilDone: YES];[pool release];}@end