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 @interface ITInetServerSocket(Private)
21 -(short)lookupPortForServiceType:(NSString*)name;
22 -(void)setupConnection;
23 -(void)stopConnection;
24 -(void)setupRendezvousAdvertising;
25 -(void)stopRendezvousAdvertising;
28 -(void)newClient:(int)cfd;
29 -(void)socketAcceptLoop:(id)data;
32 @implementation ITInetServerSocket
35 if (self = [super init])
39 clients = [[NSMutableSet alloc] init];
43 rndType = rndName = nil;
49 - (id)initWithDelegate:(id)d
51 if (self = [super init])
54 delegate = [d retain];
55 clients = [[NSMutableSet alloc] init];
59 rndType = rndName = nil;
67 [self stopConnection];
76 if (!rndName || !rndType || !port) return NO;
77 [self setupConnection];
103 [self stopConnection];
106 - (void)setServiceType:(NSString*)type useForPort:(BOOL)p
108 rndType = [type retain];
110 port = [self lookupPortForServiceType:type];
114 - (void)setServiceName:(NSString*)name
116 rndName = [name retain];
119 - (void)setPort:(short)p
125 @implementation ITInetServerSocket(Private)
126 -(short)lookupPortForServiceType:(NSString*)name
128 const char *_name = [name cString];
129 struct addrinfo *res;
131 getaddrinfo(NULL,_name,NULL,&res);
132 p = ntohs(((struct sockaddr_in *)res->ai_addr)->sin_port);
137 -(void)setupConnection
139 struct addrinfo hints, *ai;
140 hints.ai_flags = AI_PASSIVE;
141 hints.ai_family = PF_INET6;
142 hints.ai_socktype = SOCK_STREAM;
143 hints.ai_protocol = IPPROTO_TCP;
144 hints.ai_addrlen = 0;
145 hints.ai_canonname = hints.ai_addr = hints.ai_next = NULL;
146 getaddrinfo(NULL,[[[NSNumber numberWithShort:port] stringValue] cString],&hints,&ai);
147 sockfd = socket(PF_INET6,SOCK_STREAM,IPPROTO_TCP);
148 bind(sockfd,ai->ai_addr,ai->ai_addrlen);
149 listen(sockfd, SOMAXCONN);
151 [self setupRendezvousAdvertising];
155 - (void)stopConnection
157 [self stopRendezvousAdvertising];
158 [clients makeObjectsPerformSelector:@selector(disconnect)];
164 - (void)setupRendezvousAdvertising
166 NSString *a = [NSString stringWithFormat:@"_%@._tcp.",rndType];
167 service = [[NSNetService alloc] initWithDomain:@"" type:a name:rndName port:htons(port)];
168 NSLog(@"Advertising a service of type %@ name %@",a,rndName);
172 - (void)stopRendezvousAdvertising
181 NSPort *p1 = [NSPort port], *p2 = [NSPort port];
182 NSConnection *dcon = [[NSConnection alloc] initWithReceivePort:p1 sendPort:p2];
183 NSArray *par = [NSArray arrayWithObjects:p2,p1,nil];
184 [dcon setRootObject:self];
185 NSLog(@"detached server thread");
186 [NSThread detachNewThreadSelector:@selector(socketAcceptLoop:) toTarget:self withObject:par];
191 NSLog(@"stopping server thread");
193 do {} while (dieflag == 1);
196 - (void)newClient:(int)cfd
198 ITInetSocket *csocket = [[ITInetSocket alloc] initWithFD:cfd delegate:delegate];
199 NSLog(@"new client for this server");
200 [clients addObject:csocket];
203 - (void)socketAcceptLoop:(id)data
205 NSAutoreleasePool *ap = [[NSAutoreleasePool alloc] init];
207 NSConnection *dcon = [[NSConnection alloc] initWithReceivePort:[par objectAtIndex:0] sendPort:[par objectAtIndex:1]];
208 NSProxy *dp = [dcon rootProxy];
209 while ((sockfd >= 0) && !dieflag)
212 cfd = accept(sockfd,NULL,NULL);
213 NSLog(@"Someone connected!");
214 [(id)dp newClient:cfd];
216 ap = [[NSAutoreleasePool alloc] init];