2 // ITInetServerSocket.m
5 // Created by Alexander Strange on Thu Feb 13 2003.
6 // Copyright (c) 2003 __MyCompanyName__. All rights reserved.
9 #import "ITInetServerSocket.h"
10 #import "ITInetSocket.h"
14 #import <netinet/in.h>
15 #import <sys/socket.h>
20 /* Too bad Objective-C doesn't have class variables... */
21 static NSMutableSet *servsockets;
23 @interface ITInetServerSocket(Private)
24 +(void)registerSocket:(ITInetServerSocket*)sock;
25 +(void)unregisterSocket:(ITInetServerSocket*)sock;
26 -(short)lookupPortForServiceType:(NSString*)name;
27 -(void)setupConnection;
28 -(void)stopConnection;
29 -(void)setupRendezvousAdvertising;
30 -(void)stopRendezvousAdvertising;
33 -(void)newClient:(int)cfd;
34 -(void)socketAcceptLoop:(id)data;
37 @implementation ITInetServerSocket
40 servsockets = [[NSMutableSet alloc] init];
46 if (self = [super init])
50 clients = [[NSMutableSet alloc] init];
54 rndType = rndName = nil;
60 - (id)initWithDelegate:(id)d
62 if (self = [super init])
65 delegate = [d retain];
66 clients = [[NSMutableSet alloc] init];
70 rndType = rndName = nil;
78 [self stopConnection];
87 if (!rndName || !rndType || !port) return NO;
88 [ITInetServerSocket registerSocket:self];
114 [ITInetServerSocket unregisterSocket:self];
117 - (void)setServiceType:(NSString*)type useForPort:(BOOL)p
119 rndType = [type retain];
121 port = [self lookupPortForServiceType:type];
125 - (void)setServiceName:(NSString*)name
127 rndName = [name retain];
130 - (void)setPort:(short)p
136 @implementation ITInetServerSocket(Private)
137 +(void)registerSocket:(ITInetServerSocket*)sock
139 [sock setupConnection];
140 [servsockets addObject:sock];
143 +(void)unregisterSocket:(ITInetServerSocket*)sock
145 [sock stopConnection];
146 [servsockets removeObject:sock];
149 -(short)lookupPortForServiceType:(NSString*)name
151 const char *_name = [name cString];
152 struct addrinfo *res;
154 getaddrinfo(NULL,_name,NULL,&res);
155 p = ntohs(((struct sockaddr_in *)res->ai_addr)->sin_port);
160 -(void)setupConnection
162 struct addrinfo hints, *ai;
163 hints.ai_flags = AI_PASSIVE;
164 hints.ai_family = PF_INET6;
165 hints.ai_socktype = SOCK_STREAM;
166 hints.ai_protocol = IPPROTO_TCP;
167 hints.ai_addrlen = 0;
168 hints.ai_canonname = hints.ai_addr = hints.ai_next = NULL;
169 getaddrinfo(NULL,[[[NSNumber numberWithShort:port] stringValue] cString],&hints,&ai);
170 bind(sockfd,ai->ai_addr,ai->ai_addrlen);
171 listen(sockfd, SOMAXCONN);
173 [self setupRendezvousAdvertising];
177 - (void)stopConnection
179 [self stopRendezvousAdvertising];
180 [clients makeObjectsPerformSelector:@selector(disconnect)];
186 - (void)setupRendezvousAdvertising
188 NSString *a = [NSString stringWithFormat:@"_%@._tcp.",rndType];
189 service = [[NSNetService alloc] initWithDomain:@"" type:a name:rndName port:htons(port)];
190 NSLog(@"Advertising a service of type %@ name %@",a,rndName);
194 - (void)stopRendezvousAdvertising
203 NSPort *p1 = [NSPort port], *p2 = [NSPort port];
204 NSConnection *dcon = [[NSConnection alloc] initWithReceivePort:p1 sendPort:p2];
205 NSArray *par = [NSArray arrayWithObjects:p2,p1,nil];
206 [dcon setRootObject:self];
207 NSLog(@"detached server thread");
208 [NSThread detachNewThreadSelector:@selector(socketAcceptLoop:) toTarget:self withObject:par];
216 - (void)newClient:(int)cfd
218 ITInetSocket *csocket = [[ITInetSocket alloc] initWithFD:cfd delegate:delegate];
219 [clients addObject:csocket];
222 - (void)socketAcceptLoop:(id)data
224 NSAutoreleasePool *ap = [[NSAutoreleasePool alloc] init];
226 NSConnection *dcon = [[NSConnection alloc] initWithReceivePort:[par objectAtIndex:0] sendPort:[par objectAtIndex:1]];
227 NSProxy *dp = [dcon rootProxy];
228 while ((sockfd != -1) && !dieflag)
231 cfd = accept(sockfd,NULL,NULL);
232 NSLog(@"Someone connected!");
233 [(id)dp newClient:cfd];