Finished the server sockets, almost. Not touched clients yet. Cleanups for other...
[ITFoundation.git] / ITInetServerSocket.m
diff --git a/ITInetServerSocket.m b/ITInetServerSocket.m
new file mode 100755 (executable)
index 0000000..dcc8805
--- /dev/null
@@ -0,0 +1,151 @@
+//
+//  ITInetServerSocket.m
+//  ITFoundation
+//
+//  Created by Alexander Strange on Thu Feb 13 2003.
+//  Copyright (c) 2003 __MyCompanyName__. All rights reserved.
+//
+
+#import "ITInetServerSocket.h"
+#import "ITInetSocket.h"
+#import <sys/types.h>
+#import <arpa/inet.h>
+#import <netinet/in.h>
+#import <sys/socket.h>
+#import <netdb.h>
+#import <fcntl.h>
+
+@interface ITInetServerSocket(Private)
+-(void)setupConnectionWithServiceName:(NSString*)name;
+-(void)setupConnectionWithPortNumber:(NSNumber*)port;
+-(void)setupRendezvousAdvertising:(NSString*)name;
+-(void)setupTimer;
+-(void)timerFunc:(NSTimer*)timer;
+@end
+
+@implementation ITInetServerSocket
+- (id)init
+{
+    if (self = [super init])
+          {
+          sockfd = 0;
+          delegate = clients = nil;
+          }
+    return self;
+}
+
+- (id)initWithServiceName:(NSString*)name delegate:(id)d
+{
+    if (self = [super init])
+          {
+          delegate = [d retain];
+          clients = [[NSMutableSet alloc] init];
+          [self setupConnectionWithServiceName:name];
+          }
+    return self;
+}
+
+- (id)initWithPort:(NSNumber*)port rendezvousName:(NSString*)name delegate:(id)d
+{
+    if (self = [super init])
+          {
+          delegate = [d retain];
+          clients = [[NSMutableSet alloc] init];
+          [self setupConnectionWithPortNumber:port];
+          }
+    return self;
+}
+
+- (void)dealloc
+{
+    [service stop];
+    [service release];
+    [clients release];
+    [delegate release];
+    shutdown(sockfd,2);
+}
+
+- (int)sockfd
+{
+    return sockfd;
+}
+
+- (NSSet*)clients
+{
+    return clients;
+}
+
+- (id)delegate
+{
+    return delegate;
+}
+@end
+
+@implementation ITInetServerSocket(Private)
+-(void)setupConnectionWithServiceName:(NSString*)name
+{
+    const char *_name = [name cString];
+    struct addrinfo hints,*res;
+
+    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);
+    sockfd = socket(res->ai_family, res->ai_socktype,res->ai_protocol);
+    bind(sockfd, res->ai_addr, res->ai_addrlen);
+    listen(sockfd, SOMAXCONN);
+    fcntl(sockfd,F_SETFL,O_NONBLOCK);
+    freeaddrinfo(res);
+}
+
+-(void)setupConnectionWithPortNumber:(NSNumber*)port
+{
+    short _port = [port shortValue];
+    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));
+    listen(sockfd, SOMAXCONN);
+    fcntl(sockfd,F_SETFL,O_NONBLOCK);
+}
+
+- (void)setupRendezvousAdvertising:(NSString*)name port:(NSNumber*)port
+{
+    service = [[NSNetService alloc] initWithDomain:@"" type:[NSString stringWithFormat:@"_%@._tcp.",name] port:htons([port shortValue])];
+    [service publish];
+}
+
+- (void)setupTimer
+{
+    NSTimer *timer = [NSTimer timerWithTimeInterval:0 target:self selector:@selector(timerFunc:) userInfo:nil repeats:YES];
+    [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode];
+}
+
+- (void)timerFunc:(NSTimer*)timer
+{
+    struct sockaddr_in csa;
+    int csalen;
+    signed int cfd;
+    (void) timer;
+    cfd = accept(sockfd,(struct sockaddr*)&csa,&csalen);
+    if (cfd == -1) {
+          if (errno == EWOULDBLOCK) return;
+          else {perror("Too bad I haven't implemented error checking yet");}
+          }
+          else {
+                  ITInetSocket *csocket = [[[ITInetSocket alloc] initWithFD:cfd delegate:self] autorelease];
+                  [clients addObject:csocket];
+                  [delegate newClientJoined:csocket];
+                  
+          }
+}
+@end
\ No newline at end of file