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;
22 static NSTimer *timer;
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;
37 @implementation ITInetServerSocket
40 servsockets = [[NSMutableSet alloc] init];
46 if (self = [super init])
50 clients = [[NSMutableSet alloc] init];
53 rndType = rndName = nil;
58 - (id)initWithDelegate:(id)d
60 if (self = [super init])
63 delegate = [d retain];
64 clients = [[NSMutableSet alloc] init];
67 rndType = rndName = nil;
74 [self stopConnection];
83 if (!rndName || !rndType || !port) return NO;
84 [ITInetServerSocket registerSocket:self];
110 [ITInetServerSocket unregisterSocket:self];
113 - (void)setServiceType:(NSString*)type useForPort:(BOOL)p
115 rndType = [type retain];
117 port = [self lookupPortForServiceType:type];
121 - (void)setServiceName:(NSString*)name
123 rndName = [name retain];
126 - (void)setPort:(short)p
132 @implementation ITInetServerSocket(Private)
133 +(void)registerSocket:(ITInetServerSocket*)sock
135 [sock setupConnection];
136 [servsockets addObject:sock];
139 +(void)unregisterSocket:(ITInetServerSocket*)sock
141 [sock stopConnection];
142 [servsockets removeObject:sock];
145 -(short)lookupPortForServiceType:(NSString*)name
147 const char *_name = [name cString];
148 struct addrinfo hints,*res;
151 hints.ai_flags = AI_PASSIVE;
152 hints.ai_family = PF_INET;
153 hints.ai_socktype = SOCK_STREAM;
154 hints.ai_protocol = IPPROTO_TCP;
155 hints.ai_addrlen = 0;
156 hints.ai_canonname = NULL;
157 hints.ai_addr = NULL;
158 hints.ai_next = NULL;
160 getaddrinfo(NULL,_name,&hints,&res);
161 p = ntohs(((struct sockaddr_in *)res->ai_addr)->sin_port);
166 -(void)setupConnection
168 struct sockaddr_in sa;
170 sockfd = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
171 sa.sin_addr.s_addr = INADDR_ANY;
172 sa.sin_family = AF_INET;
173 sa.sin_port = htons(port);
174 bind(sockfd,(struct sockaddr *)&sa,sizeof(sa));
175 listen(sockfd, SOMAXCONN);
176 fcntl(sockfd,F_SETFL,O_NONBLOCK);
177 [self setupRendezvousAdvertising];
180 - (void)stopConnection
182 [self stopRendezvousAdvertising];
183 [clients makeObjectsPerformSelector:@selector(disconnect)];
189 - (void)setupRendezvousAdvertising
191 service = [[NSNetService alloc] initWithDomain:@"" type:[NSString stringWithFormat:@"_%@._tcp.",rndType] name:rndName port:htons(port)];
195 - (void)stopRendezvousAdvertising
204 if (!timer) timer = [NSTimer timerWithTimeInterval:0 target:self selector:@selector(globalTimerFunc:) userInfo:nil repeats:YES];
205 [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode];
215 + (void)globalTimerFunc:(NSTimer*)timer
217 [servsockets makeObjectsPerformSelector:@selector(timerFunc)];
224 struct sockaddr_in csa;
227 cfd = accept(sockfd,(struct sockaddr*)&csa,&csalen);
229 if (errno == EWOULDBLOCK) ;
230 else {perror("Too bad I haven't implemented error checking yet");}
233 ITInetSocket *csocket = [[[ITInetSocket alloc] initWithFD:cfd delegate:self] autorelease];
234 [clients addObject:csocket];
235 [delegate newClientJoined:csocket];