Subversion Repositories SmartDukaan

Rev

Rev 30 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
30 ashish 1
/*
2
 * Licensed to the Apache Software Foundation (ASF) under one
3
 * or more contributor license agreements. See the NOTICE file
4
 * distributed with this work for additional information
5
 * regarding copyright ownership. The ASF licenses this file
6
 * to you under the Apache License, Version 2.0 (the
7
 * "License"); you may not use this file except in compliance
8
 * with the License. You may obtain a copy of the License at
9
 *
10
 *   http://www.apache.org/licenses/LICENSE-2.0
11
 *
12
 * Unless required by applicable law or agreed to in writing,
13
 * software distributed under the License is distributed on an
14
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15
 * KIND, either express or implied. See the License for the
16
 * specific language governing permissions and limitations
17
 * under the License.
18
 */
19
 
20
#import <Foundation/Foundation.h>
21
#import "TSocketServer.h"
22
#import "TNSFileHandleTransport.h"
23
#import "TProtocol.h"
24
#import "TTransportException.h"
25
#import <sys/socket.h>
26
#include <netinet/in.h>
27
 
28
 
29
 
30
NSString * const kTSocketServer_ClientConnectionFinishedForProcessorNotification = @"TSocketServer_ClientConnectionFinishedForProcessorNotification";
31
NSString * const kTSocketServer_ProcessorKey = @"TSocketServer_Processor";
32
NSString * const kTSockerServer_TransportKey = @"TSockerServer_Transport";
33
 
34
 
35
@implementation TSocketServer
36
 
37
- (id) initWithPort: (int) port
38
    protocolFactory: (id <TProtocolFactory>) protocolFactory
39
   processorFactory: (id <TProcessorFactory>) processorFactory;
40
{
41
  self = [super init];
42
 
43
  mInputProtocolFactory = [protocolFactory retain];
44
  mOutputProtocolFactory = [protocolFactory retain];
45
  mProcessorFactory = [processorFactory retain];
46
 
47
  // create a socket.
48
  int fd = -1;
49
  CFSocketRef socket = CFSocketCreate(kCFAllocatorDefault, PF_INET, SOCK_STREAM, IPPROTO_TCP, 0, NULL, NULL);
50
  if (socket) {
51
    fd = CFSocketGetNative(socket);
52
    int yes = 1;
53
    setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (void *)&yes, sizeof(yes));
54
 
55
    struct sockaddr_in addr;
56
    memset(&addr, 0, sizeof(addr));
57
    addr.sin_len = sizeof(addr);
58
    addr.sin_family = AF_INET;
59
    addr.sin_port = htons(port);
60
    addr.sin_addr.s_addr = htonl(INADDR_ANY);
61
    NSData *address = [NSData dataWithBytes:&addr length:sizeof(addr)];
62
    if (CFSocketSetAddress(socket, (CFDataRef)address) != kCFSocketSuccess) {
63
      NSLog(@"*** Could not bind to address");
64
      return nil;
65
    }
66
  } else {
67
    NSLog(@"*** No server socket");
68
    return nil;
69
  }
70
 
71
  // wrap it in a file handle so we can get messages from it
72
  mSocketFileHandle = [[NSFileHandle alloc] initWithFileDescriptor: fd
73
                                                    closeOnDealloc: YES];
74
 
75
    // register for notifications of accepted incoming connections
76
  [[NSNotificationCenter defaultCenter] addObserver: self
77
                                           selector: @selector(connectionAccepted:)
78
                                               name: NSFileHandleConnectionAcceptedNotification
79
                                             object: mSocketFileHandle];
80
 
81
  // tell socket to listen
82
  [mSocketFileHandle acceptConnectionInBackgroundAndNotify];
83
 
84
  NSLog(@"Listening on TCP port %d", port);
85
 
86
  return self;
87
}
88
 
89
 
90
- (void) dealloc {
91
  [[NSNotificationCenter defaultCenter] removeObject: self];
92
  [mInputProtocolFactory release];
93
  [mOutputProtocolFactory release];
94
  [mProcessorFactory release];
95
  [mSocketFileHandle release];
96
  [super dealloc];
97
}
98
 
99
 
100
- (void) connectionAccepted: (NSNotification *) aNotification
101
{
102
  NSFileHandle * socket = [[aNotification userInfo] objectForKey: NSFileHandleNotificationFileHandleItem];
103
 
104
  // now that we have a client connected, spin off a thread to handle activity
105
  [NSThread detachNewThreadSelector: @selector(handleClientConnection:)
106
                           toTarget: self
107
                         withObject: socket];
108
 
109
  [[aNotification object] acceptConnectionInBackgroundAndNotify];
110
}
111
 
112
 
113
- (void) handleClientConnection: (NSFileHandle *) clientSocket
114
{
115
  NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
116
 
117
  TNSFileHandleTransport * transport = [[TNSFileHandleTransport alloc] initWithFileHandle: clientSocket];
118
  id<TProcessor> processor = [mProcessorFactory processorForTransport: transport];
119
 
120
  id <TProtocol> inProtocol = [mInputProtocolFactory newProtocolOnTransport: transport];
121
  id <TProtocol> outProtocol = [mOutputProtocolFactory newProtocolOnTransport: transport];
122
 
123
  @try {
124
    BOOL result = NO;
125
    do {
126
      NSAutoreleasePool * myPool = [[NSAutoreleasePool alloc] init];
127
      result = [processor processOnInputProtocol: inProtocol outputProtocol: outProtocol];
128
      [myPool release];
129
    } while (result);
130
  }
131
  @catch (TTransportException * te) {
132
    //NSLog(@"Caught transport exception, abandoning client connection: %@", te);
133
  }
134
 
135
  NSNotification * n = [NSNotification notificationWithName: kTSocketServer_ClientConnectionFinishedForProcessorNotification
136
                                                     object: self
137
                                                   userInfo: [NSDictionary dictionaryWithObjectsAndKeys: 
138
                                                              processor,
139
                                                              kTSocketServer_ProcessorKey,
140
                                                              transport,
141
                                                              kTSockerServer_TransportKey,
142
                                                              nil]];
143
  [[NSNotificationCenter defaultCenter] performSelectorOnMainThread: @selector(postNotification:) withObject: n waitUntilDone: YES];
144
 
145
  [pool release];
146
}
147
 
148
 
149
 
150
@end
151
 
152
 
153