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... */
22 @interface ITInetServerSocket(Private)
23 -(short)lookupPortForServiceType:(NSString*)name;
24 -(void)setupConnection;
25 -(void)stopConnection;
26 -(void)setupRendezvousAdvertising;
27 -(void)stopRendezvousAdvertising;
30 -(void)newClient:(int)cfd;
31 -(void)socketAcceptLoop:(id)data;
34 @implementation ITInetServerSocket
37 if (self = [super init])
41 clients = [[NSMutableSet alloc] init];
45 rndType = rndName = nil;
51 - (id)initWithDelegate:(id)d
53 if (self = [super init])
56 delegate = [d retain];
57 clients = [[NSMutableSet alloc] init];
61 rndType = rndName = nil;
69 [self stopConnection];
78 if (!rndName || !rndType || !port) return NO;
79 [self setupConnection];
105 [self stopConnection];
108 - (void)setServiceType:(NSString*)type useForPort:(BOOL)p
110 rndType = [type retain];
112 port = [self lookupPortForServiceType:type];
116 - (void)setServiceName:(NSString*)name
118 rndName = [name retain];
121 - (void)setPort:(short)p
127 @implementation ITInetServerSocket(Private)
128 -(short)lookupPortForServiceType:(NSString*)name
130 const char *_name = [name cString];
131 struct addrinfo *res;
133 getaddrinfo(NULL,_name,NULL,&res);
134 p = ntohs(((struct sockaddr_in *)res->ai_addr)->sin_port);
139 -(void)setupConnection
141 struct addrinfo hints, *ai;
142 hints.ai_flags = AI_PASSIVE;
143 hints.ai_family = PF_INET6;
144 hints.ai_socktype = SOCK_STREAM;
145 hints.ai_protocol = IPPROTO_TCP;
146 hints.ai_addrlen = 0;
147 hints.ai_canonname = hints.ai_addr = hints.ai_next = NULL;
148 getaddrinfo(NULL,[[[NSNumber numberWithShort:port] stringValue] cString],&hints,&ai);
149 sockfd = socket(PF_INET6,SOCK_STREAM,IPPROTO_TCP);
150 bind(sockfd,ai->ai_addr,ai->ai_addrlen);
151 listen(sockfd, SOMAXCONN);
153 [self setupRendezvousAdvertising];
157 - (void)stopConnection
159 [self stopRendezvousAdvertising];
160 [clients makeObjectsPerformSelector:@selector(disconnect)];
166 - (void)setupRendezvousAdvertising
168 NSString *a = [NSString stringWithFormat:@"_%@._tcp.",rndType];
169 service = [[NSNetService alloc] initWithDomain:@"" type:a name:rndName port:htons(port)];
170 NSLog(@"Advertising a service of type %@ name %@",a,rndName);
174 - (void)stopRendezvousAdvertising
183 NSPort *p1 = [NSPort port], *p2 = [NSPort port];
184 NSConnection *dcon = [[NSConnection alloc] initWithReceivePort:p1 sendPort:p2];
185 NSArray *par = [NSArray arrayWithObjects:p2,p1,nil];
186 [dcon setRootObject:self];
187 NSLog(@"detached server thread");
188 [NSThread detachNewThreadSelector:@selector(socketAcceptLoop:) toTarget:self withObject:par];
193 NSLog(@"stopping server thread");
195 do {} while (dieflag == 1);
198 - (void)newClient:(int)cfd
200 ITInetSocket *csocket = [[ITInetSocket alloc] initWithFD:cfd delegate:delegate];
201 NSLog(@"new client for this server");
202 [clients addObject:csocket];
205 - (void)socketAcceptLoop:(id)data
207 NSAutoreleasePool *ap = [[NSAutoreleasePool alloc] init];
209 NSConnection *dcon = [[NSConnection alloc] initWithReceivePort:[par objectAtIndex:0] sendPort:[par objectAtIndex:1]];
210 NSProxy *dp = [dcon rootProxy];
211 while ((sockfd >= 0) && !dieflag)
214 cfd = accept(sockfd,NULL,NULL);
215 NSLog(@"Someone connected!");
216 [(id)dp newClient:cfd];
218 ap = [[NSAutoreleasePool alloc] init];