@class ITByteStream;
-@protocol ITByteStreamDelegate
+@protocol ITByteStreamDelegate <NSObject>
-(oneway void)newDataAdded:(ITByteStream *)sender;
@end
-(NSData*) readAllData;
-(void) writeData:(in NSData*)data;
-(void) writeBytes:(char *)b len:(long)length;
+-(void) lockStream;
+-(void) unlockStream;
+-(void) shortenData:(long)length;
@end
-(NSData*) readDataOfLength:(int)length
{
- NSData *ret, *tmp;
+ NSData *ret;
NSRange range = {0, length};
[lock lock];
ret = [data subdataWithRange:range];
-#if MAC_OS_X_VERSION_10_2 <= MAC_OS_X_VERSION_MAX_ALLOWED
[data replaceBytesInRange:range withBytes:nil length:0];
-#else
- range = {length, [data length]};
- tmp = [data subdataWithRange:range];
- [data setData:tmp];
-#endif
[lock unlock];
return ret;
}
[lock unlock];
[delegate newDataAdded:self];
}
+
+-(void) lockStream
+{
+ [lock lock];
+}
+
+-(void) unlockStream
+{
+ [lock unlock];
+}
+
+-(void) shortenData:(long)length
+{
+ NSRange range = {0, length};
+ [data replaceBytesInRange:range withBytes:nil length:0];
+}
@end
@class ITInetSocket;
@protocol ITInetServerSocketOwner
-- (void)newClientJoined:(ITInetSocket*)client;
+- (oneway void)newClientJoined:(ITInetSocket*)client;
@end
@interface ITInetServerSocket : NSObject {
#import <unistd.h>
/* Too bad Objective-C doesn't have class variables... */
-static NSMutableSet *servsockets;
@interface ITInetServerSocket(Private)
-+(void)registerSocket:(ITInetServerSocket*)sock;
-+(void)unregisterSocket:(ITInetServerSocket*)sock;
-(short)lookupPortForServiceType:(NSString*)name;
-(void)setupConnection;
-(void)stopConnection;
@end
@implementation ITInetServerSocket
-+ (void)initialize
-{
- servsockets = [[NSMutableSet alloc] init];
- //[self setupTimer];
-}
-
- (id)init
{
if (self = [super init])
- (BOOL)start
{
if (!rndName || !rndType || !port) return NO;
- [ITInetServerSocket registerSocket:self];
+ [self setupConnection];
return YES;
}
- (void)stop
{
- [ITInetServerSocket unregisterSocket:self];
+ [self stopConnection];
}
- (void)setServiceType:(NSString*)type useForPort:(BOOL)p
@end
@implementation ITInetServerSocket(Private)
-+(void)registerSocket:(ITInetServerSocket*)sock
-{
- [sock setupConnection];
- [servsockets addObject:sock];
-}
-
-+(void)unregisterSocket:(ITInetServerSocket*)sock
-{
- [sock stopConnection];
- [servsockets removeObject:sock];
-}
-
-(short)lookupPortForServiceType:(NSString*)name
{
const char *_name = [name cString];
hints.ai_addrlen = 0;
hints.ai_canonname = hints.ai_addr = hints.ai_next = NULL;
getaddrinfo(NULL,[[[NSNumber numberWithShort:port] stringValue] cString],&hints,&ai);
+ sockfd = socket(PF_INET6,SOCK_STREAM,IPPROTO_TCP);
bind(sockfd,ai->ai_addr,ai->ai_addrlen);
listen(sockfd, SOMAXCONN);
freeaddrinfo(ai);
{
[self stopRendezvousAdvertising];
[clients makeObjectsPerformSelector:@selector(disconnect)];
- shutdown(sockfd,2);
+ [self stopThread];
close(sockfd);
sockfd = -1;
}
- (void)stopThread
{
+ NSLog(@"stopping server thread");
dieflag = 1;
+ do {} while (dieflag == 1);
}
- (void)newClient:(int)cfd
{
ITInetSocket *csocket = [[ITInetSocket alloc] initWithFD:cfd delegate:delegate];
+ NSLog(@"new client for this server");
[clients addObject:csocket];
}
NSArray *par = data;
NSConnection *dcon = [[NSConnection alloc] initWithReceivePort:[par objectAtIndex:0] sendPort:[par objectAtIndex:1]];
NSProxy *dp = [dcon rootProxy];
- while ((sockfd != -1) && !dieflag)
+ while ((sockfd >= 0) && !dieflag)
{
signed int cfd;
cfd = accept(sockfd,NULL,NULL);
NSLog(@"Someone connected!");
[(id)dp newClient:cfd];
+ [ap release];
+ ap = [[NSAutoreleasePool alloc] init];
}
+
+ NSLog(@"suiciding");
dieflag = 0;
[dcon release];
[ap release];
* @discussion ITInetSockets use these methods to communicate with their delegates
*/
@protocol ITInetSocketDelegate <ITByteStreamDelegate>
-/*!
- * @method dataReceived:
- * @abstract Alerts the delegate of data.
- * @discussion The delegate should check [sender readPipe] to get the data.
- * @param sender The socket that the messages came from.
- */
-- (oneway void) dataReceived:(ITInetSocket *)sender;
/*!
* @method errorOccured:during:onSocket:
* @abstract Alerts the delegate of an error condition.
* @discussion ITInetSocket is an Internet socket class supporting IPv6 and Rendezvous.
*/
@interface ITInetSocket : NSObject <ITByteStreamDelegate> {
-
int sockfd;
int port;
int nc;
unsigned short bufs;
volatile int dieflag;
volatile int actionflag;
- id <ITInetSocketDelegate,NSObject> delegate;
+ id <ITInetSocketDelegate> delegate;
struct addrinfo *ai, *ai_cur;
ITByteStream *readPipe, *writePipe;
ITInetSocketState state;
* @param type The type of Rendezvous service to listen on.
* @param d The delegate that the sockets will belong to.
*/
-+(void)startAutoconnectingToService:(NSString*)type delegate:(id <ITInetSocketDelegate,NSObject>)d;
++(void)startAutoconnectingToService:(NSString*)type delegate:(id <ITInetSocketDelegate>)d;
/*!
* @method initWithFD:delegate:
* @abstract Wraps a socket around an existing socket descriptor.
* @param fd The descriptor.
* @param d The delegate for the socket.
*/
--(id) initWithFD:(int)fd delegate:(id <ITInetSocketDelegate,NSObject>)d;
+-(id) initWithFD:(int)fd delegate:(id <ITInetSocketDelegate>)d;
/*!
* @method initWithDelegate:
* @abstract Creates a new socket.
* @discussion The socket will not be connected to anything.
* @param d The delegate of the socket.
*/
--(id) initWithDelegate:(id <ITInetSocketDelegate,NSObject>)d;
+-(id) initWithDelegate:(id <ITInetSocketDelegate>)d;
-(id <ITInetSocketDelegate>)delegate;
-(unsigned short)bufferSize;
-(ITInetSocketState) state;
-(void) retryConnection;
-(void) disconnect;
+-(ITByteStream *)readPipe;
+-(ITByteStream *)writePipe;
@end
{
NSEnumerator *e = [arr objectEnumerator];
NSData *d;
- struct addrinfo *a;
+ struct addrinfo *a,*oa;
ai = malloc(sizeof(struct addrinfo));
- a = ai;
+ ai_cur = ai;
+ oa = a = ai;
+ bzero(a,sizeof(struct addrinfo));
while (d = [e nextObject])
{
struct sockaddr *s = (struct sockaddr*)[d bytes];
a->ai_family = s->sa_family;
a->ai_addr = s;
a->ai_next = malloc(sizeof(struct addrinfo));
+ oa = a;
a = a->ai_next;
}
- ai_cur = ai;
+ free(a);
+ oa->ai_next = NULL;
+ NSLog(@"Sockaddr connecting....");
+ [self dumpv6Addrinfo:ai];
[self realDoConnection];
}
}
{
NSLog(@"Got a disconnect");
dieflag = 1;
+ do {} while (dieflag == 1);
}
-(void)retryConnection
-(void)newDataAdded:(ITByteStream*)sender
{
- NSLog(@"writePipe got something");
- actionflag = 1;
- do {} while (actionflag == 1);
- NSLog(@"thread saw actionFlag");
}
+
+-(ITByteStream*)readPipe {return readPipe;}
+-(ITByteStream*)writePipe {return writePipe;}
@end
@implementation ITInetSocket(Debugging)
NSConnection *dcon = [[NSConnection alloc] initWithReceivePort:[data objectAtIndex:0] sendPort:[data objectAtIndex:1]];
NSProxy *dp = [[dcon rootProxy] retain];
char *buf = malloc(bufs);
- unsigned long readLen = 0;
+ unsigned long readLen = 0,wpl = 0;
signed int err;
- [readPipe setDelegate:dp];
+ [readPipe setDelegate:(id <ITInetSocketDelegate>)dp];
if (nc){
NSLog(@"Connecting");
err = connect(sockfd,ai_cur->ai_addr,ai_cur->ai_addrlen);
if (err == -1)
{
perror("CAwh");
+ *((char*)NULL) = 12;
[(id)dp errorOccured:ITInetCouldNotConnect during:ITInetSocketConnecting onSocket:self];
goto dieaction;
}
[(id)dp finishedConnecting:self];
lstart:
state = ITInetSocketListening;
- while (!actionflag && !dieflag)
+ while (!actionflag && !dieflag && !(wpl = CFDataGetLength((CFDataRef)writePipe->data)))
{
readLen = recv(sockfd,buf,bufs,0);
state = ITInetSocketReading;
}
{
+ const char *d = CFDataGetBytePtr((CFDataRef)writePipe->data);
state = ITInetSocketWriting;
- NSLog(@"Emptying writePipe");
- NSData *d = [writePipe readAllData];
- write(sockfd,[d bytes],[d length]);
+ NSLog(@"Writing");
+ [writePipe lockStream];
+ wpl = send(sockfd,d,wpl,0);
+ [writePipe shortenData:wpl];
+ [writePipe unlockStream];
[ap release];
ap = [[NSAutoreleasePool alloc] init];
goto lstart;
{
if (self = [super init])
{
- delegate = _delegate;
+ delegate = [_delegate retain];
}
return self;
}
+- (void) dealloc
+{
+ [delegate release];
+}
+
- (void)netServiceBrowser:(NSNetServiceBrowser *)aNetServiceBrowser didFindService:(NSNetService *)aNetService moreComing:(BOOL)moreComing
{
ITInetSocket *sock;
+ NSArray *arr;
+ id d = delegate;
if (!moreComing)
{
+ NSLog(@"Nothing more coming");
+ [[aNetService retain] autorelease];
[aNetServiceBrowser stop];
[aNetServiceBrowser release];
[self release];
}
- sock = [[ITInetSocket alloc] initWithDelegate:delegate];
+ sock = [[ITInetSocket alloc] initWithDelegate:d];
NSLog(@"Detected a service! name %@ type %@",[aNetService name],[aNetService type]);
- [sock connectWithSockaddrArray:[aNetService addresses]];
+ arr = [aNetService addresses];
+ if ([arr count])
+ [sock connectWithSockaddrArray:arr];
+ else
+ NSLog(@"There are no sockaddrs for this service!");
}
@end
}
- (void) finishedConnecting:(ITInetSocket *)sender {
- [sender disconnect];
+ [[sender writePipe] writeBytes:"suck" len:4];
}
- (void) errorOccured:(ITInetSocketError)err during:(ITInetSocketState)state onSocket:(in ITInetSocket*)sender
{
}
-- (void) dataReceived:(ITInetSocket *)sender
-{
-}
-
- (void) newDataAdded:(ITByteStream*)sender
{
- (void)newClientJoined:(ITInetSocket*)client
{
-
+ [[client writePipe] writeBytes:"suck" len:4];
}
@end