-(void)stopConnection;
-(void)setupRendezvousAdvertising;
-(void)stopRendezvousAdvertising;
--(void)setupTimer;
--(void)stopTimer;
-+(void)globalTimerFunc:(NSTimer*)timer;
--(void)timerFunc:(NSTimer*)timer;
+-(void)setupThread;
+-(void)stopThread;
+-(void)newClient:(int)cfd;
+-(void)socketAcceptLoop:(id)data;
@end
@implementation ITInetServerSocket
clients = [[NSMutableSet alloc] init];
service = nil;
port = 0;
+ dieflag = 0;
rndType = rndName = nil;
timer = nil;
}
clients = [[NSMutableSet alloc] init];
service = nil;
port = 0;
+ dieflag = 0;
rndType = rndName = nil;
timer = nil;
}
-(short)lookupPortForServiceType:(NSString*)name
{
const char *_name = [name cString];
- struct addrinfo hints,*res;
+ struct addrinfo *res;
short p;
-
- hints.ai_flags = AI_PASSIVE;
- hints.ai_family = PF_INET;
- hints.ai_socktype = SOCK_STREAM;
- hints.ai_protocol = IPPROTO_TCP;
- hints.ai_addrlen = 0;
- hints.ai_canonname = NULL;
- hints.ai_addr = NULL;
- hints.ai_next = NULL;
-
- getaddrinfo(NULL,_name,&hints,&res);
+ getaddrinfo(NULL,_name,NULL,&res);
p = ntohs(((struct sockaddr_in *)res->ai_addr)->sin_port);
freeaddrinfo(res);
return p;
-(void)setupConnection
{
- struct sockaddr_in sa;
-
- sockfd = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
- sa.sin_addr.s_addr = INADDR_ANY;
- sa.sin_family = AF_INET;
- sa.sin_port = htons(port);
- bind(sockfd,(struct sockaddr *)&sa,sizeof(sa));
+ struct addrinfo hints, *ai;
+ hints.ai_flags = AI_PASSIVE;
+ hints.ai_family = PF_INET6;
+ hints.ai_socktype = SOCK_STREAM;
+ hints.ai_protocol = IPPROTO_TCP;
+ hints.ai_addrlen = 0;
+ hints.ai_canonname = hints.ai_addr = hints.ai_next = NULL;
+ getaddrinfo(NULL,[[[NSNumber numberWithShort:port] stringValue] cString],&hints,&ai);
+ bind(sockfd,ai->ai_addr,ai->ai_addrlen);
listen(sockfd, SOMAXCONN);
- fcntl(sockfd,F_SETFL,O_NONBLOCK);
+ freeaddrinfo(ai);
[self setupRendezvousAdvertising];
- [self setupTimer];
+ [self setupThread];
}
- (void)stopConnection
service = nil;
}
-- (void)setupTimer
+- (void)setupThread
{
- if (!timer) timer = [NSTimer timerWithTimeInterval:0 target:self selector:@selector(timerFunc:) userInfo:nil repeats:YES];
- [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode];
+ NSPort *p1 = [NSPort port], *p2 = [NSPort port];
+ NSConnection *dcon = [[NSConnection alloc] initWithReceivePort:p1 sendPort:p2];
+ NSArray *par = [NSArray arrayWithObjects:p2,p1,nil];
+ [dcon setRootObject:self];
+ [NSThread detachNewThreadSelector:@selector(socketAcceptLoop:) toTarget:self withObject:par];
}
-- (void)stopTimer
+- (void)stopThread
{
- [timer invalidate];
- [timer release];
- timer = nil;
+ dieflag = 1;
}
-+ (void)globalTimerFunc:(NSTimer*)timer
+- (void)newClient:(int)cfd
{
- [servsockets makeObjectsPerformSelector:@selector(timerFunc)];
+ ITInetSocket *csocket = [[ITInetSocket alloc] initWithFD:cfd delegate:delegate];
+ [clients addObject:csocket];
}
-- (void)timerFunc:(NSTimer*)timer
+- (void)socketAcceptLoop:(id)data
{
- if (sockfd != -1)
+ NSAutoreleasePool *ap = [[NSAutoreleasePool alloc] init];
+ NSArray *par = data;
+ NSConnection *dcon = [[NSConnection alloc] initWithReceivePort:[par objectAtIndex:0] sendPort:[par objectAtIndex:1]];
+ NSProxy *dp = [dcon rootProxy];
+ while ((sockfd != -1) && !dieflag)
{
- struct sockaddr_in csa;
- int csalen;
signed int cfd;
- cfd = accept(sockfd,(struct sockaddr*)&csa,&csalen);
- if (cfd == -1) {
- if (errno == EWOULDBLOCK) ;
- else {perror("Too bad I haven't implemented error checking yet");}
- }
- else {
- ITInetSocket *csocket = [[ITInetSocket alloc] initWithFD:cfd delegate:self];
- [clients addObject:csocket];
- [delegate newClientJoined:csocket];
- }
+ cfd = accept(sockfd,NULL,NULL);
+ [(id)dp newClient:cfd];
}
+ dieflag = 0;
+ [dcon release];
+ [ap release];
}
@end
\ No newline at end of file
* @abstract Definitions for the ITInetSocket class
*/
-/*!
- * @constant ITInetMaxConnections
- * @abstract The maximum number of running ITInetSockets you can have.
- * @discussion The socket will error during a connection request if you are over the maximum.
- */
-
-enum {
- ITInetMaxConnections = 128
-};
/*!
* @enum ITInetSocketState
* @discussion The delegate should check [sender readPipe] to get the data.
* @param sender The socket that the messages came from.
*/
-- (void) dataReceived:(ITInetSocket *)sender;
+- (oneway void) dataReceived:(ITInetSocket *)sender;
/*!
* @method errorOccured:during:onSocket:
* @abstract Alerts the delegate of an error condition.
* @param state What the socket was doing when the error occured.
* @param sender The socket the error occured on.
*/
-- (void) errorOccured:(ITInetSocketError)err during:(ITInetSocketState)state onSocket:(ITInetSocket*)sender;
+- (oneway void) errorOccured:(ITInetSocketError)err during:(ITInetSocketState)state onSocket:(ITInetSocket*)sender;
/*!
* @method finishedConnecting:
* @abstract Alerts the delegate of a successful connection attempt.
* @discussion The delegate should send whatever initial data is required for the protocol (nickname for IRC, etc.)
* @param sender The socket that established the connection.
*/
-- (void) finishedConnecting:(ITInetSocket *)sender;
+- (oneway void) finishedConnecting:(ITInetSocket *)sender;
@end
/*!
a->ai_next = malloc(sizeof(struct addrinfo));
a = a->ai_next;
}
+ ai_cur = ai;
+ [self realDoConnection];
}
}
{
NSLog(@"Got a disconnect");
dieflag = 1;
- do {} while (dieflag == 1);
}
-(void)retryConnection
{
NSLog(@"writePipe got something");
actionflag = 1;
+ do {} while (actionflag == 1);
NSLog(@"thread saw actionFlag");
}
@end
struct addrinfo hints;
int err;
const char *portNam = [namedPort cString], *hostCStr = [host cString];
-
+ state = ITInetSocketConnecting;
hints.ai_flags = 0;
hints.ai_family = PF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
NSLog(@"Sending finishedConnecting");
[(id)dp finishedConnecting:self];
lstart:
-
+ state = ITInetSocketListening;
while (!actionflag && !dieflag)
{
- NSData *d;
readLen = recv(sockfd,buf,bufs,0);
+ state = ITInetSocketReading;
if (readLen == -1) {[(id)dp errorOccured:ITInetConnectionDropped during:ITInetSocketReading onSocket:self];goto dieaction;}
if (readLen) {
NSLog(@"recv'd");
ap = [[NSAutoreleasePool alloc] init];
}
}
-
+ state = ITInetSocketListening;
actionflag = 0;
if (dieflag)
{
dieaction:
+ state = ITInetSocketDisconnected;
perror("Awh");
free(buf);
shutdown(sockfd,2);
}
{
+ state = ITInetSocketWriting;
NSLog(@"Emptying writePipe");
NSData *d = [writePipe readAllData];
write(sockfd,[d bytes],[d length]);