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)globalTimerFunc:(NSTimer*)timer;
34 -(void)timerFunc:(NSTimer*)timer;
37 @implementation ITInetServerSocket
40 servsockets = [[NSMutableSet alloc] init];
46 if (self = [super init])
50 clients = [[NSMutableSet alloc] init];
53 rndType = rndName = nil;
59 - (id)initWithDelegate:(id)d
61 if (self = [super init])
64 delegate = [d retain];
65 clients = [[NSMutableSet alloc] init];
68 rndType = rndName = nil;
76 [self stopConnection];
85 if (!rndName || !rndType || !port) return NO;
86 [ITInetServerSocket registerSocket:self];
112 [ITInetServerSocket unregisterSocket:self];
115 - (void)setServiceType:(NSString*)type useForPort:(BOOL)p
117 rndType = [type retain];
119 port = [self lookupPortForServiceType:type];
123 - (void)setServiceName:(NSString*)name
125 rndName = [name retain];
128 - (void)setPort:(short)p
134 @implementation ITInetServerSocket(Private)
135 +(void)registerSocket:(ITInetServerSocket*)sock
137 [sock setupConnection];
138 [servsockets addObject:sock];
141 +(void)unregisterSocket:(ITInetServerSocket*)sock
143 [sock stopConnection];
144 [servsockets removeObject:sock];
147 -(short)lookupPortForServiceType:(NSString*)name
149 const char *_name = [name cString];
150 struct addrinfo hints,*res;
153 hints.ai_flags = AI_PASSIVE;
154 hints.ai_family = PF_INET;
155 hints.ai_socktype = SOCK_STREAM;
156 hints.ai_protocol = IPPROTO_TCP;
157 hints.ai_addrlen = 0;
158 hints.ai_canonname = NULL;
159 hints.ai_addr = NULL;
160 hints.ai_next = NULL;
162 getaddrinfo(NULL,_name,&hints,&res);
163 p = ntohs(((struct sockaddr_in *)res->ai_addr)->sin_port);
168 -(void)setupConnection
170 struct sockaddr_in sa;
172 sockfd = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
173 sa.sin_addr.s_addr = INADDR_ANY;
174 sa.sin_family = AF_INET;
175 sa.sin_port = htons(port);
176 bind(sockfd,(struct sockaddr *)&sa,sizeof(sa));
177 listen(sockfd, SOMAXCONN);
178 fcntl(sockfd,F_SETFL,O_NONBLOCK);
179 [self setupRendezvousAdvertising];
183 - (void)stopConnection
185 [self stopRendezvousAdvertising];
186 [clients makeObjectsPerformSelector:@selector(disconnect)];
192 - (void)setupRendezvousAdvertising
194 service = [[NSNetService alloc] initWithDomain:@"" type:[NSString stringWithFormat:@"_%@._tcp.",rndType] name:rndName port:htons(port)];
198 - (void)stopRendezvousAdvertising
207 if (!timer) timer = [NSTimer timerWithTimeInterval:0 target:self selector:@selector(timerFunc:) userInfo:nil repeats:YES];
208 [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode];
218 + (void)globalTimerFunc:(NSTimer*)timer
220 [servsockets makeObjectsPerformSelector:@selector(timerFunc)];
223 - (void)timerFunc:(NSTimer*)timer
227 struct sockaddr_in csa;
230 cfd = accept(sockfd,(struct sockaddr*)&csa,&csalen);
232 if (errno == EWOULDBLOCK) ;
233 else {perror("Too bad I haven't implemented error checking yet");}
236 ITInetSocket *csocket = [[[ITInetSocket alloc] initWithFD:cfd delegate:self] autorelease];
237 [clients addObject:csocket];
238 [delegate newClientJoined:csocket];