NSNetServiceListenForConnections option implemented for GSAvahiNetService

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@37521 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
znek 2013-12-26 23:16:36 +00:00
parent dcb77e3632
commit 27e3e2f3f5
3 changed files with 104 additions and 16 deletions

View file

@ -1,5 +1,10 @@
2013-12-26 Marcus Mueller <znek@mulle-kybernetik.com>
* Headers/Foundation/NSNetServices.h:
* Source/GSAvahiNetService.m:
added NSNetServiceListenForConnections option (introduced in
OSX 10.9) and accompanying delegate method, currently implemented in
GSAvahiNetService.m only.
* Headers/Foundation/NSStream.h: fixed typo (_clang_ -> __clang__)
2013-12-24 Richard Frith-Macdonald <rfm@gnu.org>

View file

@ -93,7 +93,10 @@ enum
typedef NSUInteger NSNetServicesError;
enum {
NSNetServiceNoAutoRename = 1 << 0
NSNetServiceNoAutoRename = 1 << 0
#if OS_API_VERSION(MAC_OS_X_VERSION_10_9,GS_API_LATEST)
,NSNetServiceListenForConnections = 1 << 1
#endif
};
typedef NSUInteger NSNetServiceOptions;
@ -202,6 +205,22 @@ GS_EXPORT NSString * const NSNetServicesErrorDomain;
- (void) netService: (NSNetService *) sender
didUpdateTXTRecordData: (NSData *) data;
#if OS_API_VERSION(MAC_OS_X_VERSION_10_9,GS_API_LATEST)
/**
* Notifies the delegate that the service, which must have been published with
* option NSNetServiceListenForConnections, received a new connection.
* In order to communicate with the connecting client, you must -open
* the streams and schedule them with a runloop.
* To reject a connection, just -open and immediately -close both streams.
*/
- (void) netService: (NSNetService *) sender
didAcceptConnectionWithInputStream: (NSInputStream *) inputStream
outputStream: (NSOutputStream *)outputStream;
#endif
@end
/**

View file

@ -33,6 +33,7 @@
#import "Foundation/NSLock.h"
#import "Foundation/NSException.h"
#import "GNUstepBase/GSObjCRuntime.h"
#import <GNUstepBase/NSStream+GNUstepBase.h>
#include <avahi-common/error.h>
#include <avahi-common/malloc.h>
#include <avahi-common/strlst.h>
@ -990,6 +991,48 @@ didUpdateRecordData: (id)data
}
}
if (options & NSNetServiceListenForConnections)
{
/* setup server socket first, as port is required in
* -[self addServiceEntry] (see below)
*/
NSInteger port = [self port];
if (port < 0)
{
port = 0;
}
GSServerStream *serverStream = [GSServerStream serverStreamToAddr: @""
port: port];
if (serverStream != nil)
{
[serverStream setDelegate:self];
[serverStream open];
if ([serverStream streamStatus] != NSStreamStatusOpen)
{
ret = 1;
}
else
{
[serverStream scheduleInRunLoop: [NSRunLoop currentRunLoop]
forMode: NSDefaultRunLoopMode];
[self setInfoObject: serverStream forKey: @"serverStream"];
NSNumber *portNumber = [serverStream propertyForKey: GSStreamLocalPortKey];
[self setInfoObject: portNumber forKey: @"port"];
}
}
else
{
ret = 1;
}
if (ret != 0)
{
[self handleError:NSNetServicesBadArgumentError];
[_lock unlock];
return NO;
}
}
/* Try adding the service to the entry group until we find an unused name
* for it (but only if NSNetServiceNoAutoRename is not set).
*/
@ -1011,14 +1054,8 @@ didUpdateRecordData: (id)data
}
}
// Handle any new error condition.
if (ret != 0)
{
[_lock unlock];
return NO;
}
[_lock unlock];
return YES;
return ret == 0 ? YES : NO;
}
- (BOOL) addServiceRecord
@ -1029,15 +1066,12 @@ didUpdateRecordData: (id)data
- (void) publishWithOptions: (NSNetServiceOptions)options
{
[_lock lock];
if (_entryGroup != NULL)
if (_entryGroup == NULL)
{
[self commitEntryGroup];
return;
}
if (NO == [self addServiceRecordWithOptions: options])
{
[self handleError: avahi_client_errno((AvahiClient*)_client)];
if (NO == [self addServiceRecordWithOptions: options])
{
[self handleError: avahi_client_errno((AvahiClient*)_client)];
}
}
[self commitEntryGroup];
[_lock unlock];
@ -1204,6 +1238,7 @@ didUpdateRecordData: (id)data
}
if (!hadError)
{
[self removeInfoObjectForKey: @"serverStream"];
[self netServiceDidStop: self];
}
_serviceState = GSNetServiceIdle;
@ -1931,6 +1966,35 @@ didUpdateRecordData: (id)data
[_lock unlock];
}
/**
* GSServerStream delegate method, called only when this service has been
* published with the NSNetServiceListenForConnections option.
*/
- (void) stream:(NSStream*) stream handleEvent: (NSStreamEvent)anEvent
{
switch (anEvent)
{
case NSStreamEventHasBytesAvailable:
{
if ([[self delegate]
respondsToSelector:
@selector(netService:didAcceptConnectionWithInputStream:outputStream:)])
{
NSInputStream *is;
NSOutputStream *os;
GSServerStream *serverStream = [self infoObjectForKey: @"serverStream"];
[serverStream acceptWithInputStream: &is outputStream: &os];
[[self delegate] netService: self
didAcceptConnectionWithInputStream: is
outputStream: os];
}
break;
}
default:
break;
}
}
- (void) dealloc
{
/*