Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Port, auth, Bonjour config for listener

Lots of additions to TDListener:
* Set port to 0 to get a dynamically-assigned port number (access the .port property to find out what it is.)
* Can publish via Bonjour by setting service name/type and optionally TXT dictionary.
* Can require authentication by supplying usernames and passwords.
  • Loading branch information...
commit 0235b18264f73ed14303ebf50e354f7aa7fd3ec0 1 parent b44e545
Jens Alfke snej authored
20 Demo-Mac/TouchServ.m
View
@@ -10,6 +10,7 @@
#import <TouchDB/TouchDB.h>
#import <TouchDB/TDRouter.h>
#import <TouchDBListener/TDListener.h>
+#import "CollectionUtils.h"
#if DEBUG
#import "Logging.h"
@@ -61,15 +62,28 @@ int main (int argc, const char * argv[])
// Start a listener socket:
TDListener* listener = [[TDListener alloc] initWithTDServer: server port: kPortNumber];
- if (argc >= 2 && strcmp(argv[1], "--readonly") == 0)
- listener.readOnly = YES;
+ [listener setBonjourName: @"TouchServ" type: @"_touchdb._tcp."];
+ listener.TXTRecordDictionary = $dict({@"Key",
+ [@"value" dataUsingEncoding: NSUTF8StringEncoding]});
+
+ for (int i = 1; i < argc; ++i) {
+ if (strcmp(argv[i], "--readonly") == 0) {
+ listener.readOnly = YES;
+ } else if (strcmp(argv[i], "--auth") == 0) {
+ srandomdev();
+ NSString* password = $sprintf(@"%x", random());
+ listener.passwords = [NSDictionary dictionaryWithObject: password
+ forKey: @"touchdb"];
+ Log(@"Auth required: user='touchdb', password='%@'", password);
+ }
+ }
[listener start];
Log(@"TouchServ %@ is listening%@ on port %d ... relax!",
[TDRouter versionString],
(listener.readOnly ? @" in read-only mode" : @""),
- kPortNumber);
+ listener.port);
[[NSRunLoop currentRunLoop] run];
14 Listener/TDHTTPConnection.m
View
@@ -36,6 +36,20 @@ - (TDListener*) listener {
}
+- (BOOL)isPasswordProtected:(NSString *)path {
+ return self.listener.requiresAuth;
+}
+
+- (NSString*) realm {
+ return self.listener.realm;
+}
+
+- (NSString*) passwordForUser: (NSString*)username {
+ LogTo(TDListener, @"Login attempted for user '%@'", username);
+ return [self.listener passwordForUser: username];
+}
+
+
- (BOOL)supportsMethod:(NSString *)method atPath:(NSString *)path {
return $equal(method, @"POST") || $equal(method, @"PUT") || $equal(method, @"DELETE")
|| [super supportsMethod: method atPath: path];
40 Listener/TDListener.h
View
@@ -15,14 +15,54 @@
{
TDHTTPServer* _httpServer;
TDServer* _tdServer;
+ NSString* _realm;
BOOL _readOnly;
+ BOOL _requiresAuth;
+ NSDictionary* _passwords;
}
+/** Initializes a TDListener.
+ @param server The TDServer whose databases to serve.
+ @param port The TCP port number to listen on. Use 0 to automatically pick an available port (you can get the port number after the server starts by getting the .port property.) */
- (id) initWithTDServer: (TDServer*)server port: (UInt16)port;
+/** The TCP port number that the listener is listening on.
+ If the listener has not yet started, this will return 0. */
+@property (readonly) UInt16 port;
+
+
+/** The Bonjour service name and type to advertise as.
+ @param name The service name; this can be arbitrary but is generally the device user's name. An empty string will be mapped to the device's name.
+ @param type The service type; the type of a generic HTTP server is "_http._tcp." but you should use something more specific. */
+- (void) setBonjourName: (NSString*)name type: (NSString*)type;
+
+/** Bonjour metadata associated with the service. Changes will be visible almost immediately.
+ The keys are NSStrings and values are NSData. Total size should be kept small (under 1kbyte if possible) as this data is multicast over UDP. */
+@property (copy) NSDictionary* TXTRecordDictionary;
+
+
+/** If set to YES, remote requests will not be allowed to make any changes to the server or its databases. */
@property BOOL readOnly;
+/** If set to YES, all requests will be required to authenticate.
+ Setting a .passwords dictionary automatically enables this.*/
+@property BOOL requiresAuth;
+
+/** Security realm string to return in authentication challenges. */
+@property (copy) NSString* realm;
+
+/** Sets user names and passwords for authentication.
+ @param passwords A dictionary mapping user names to passwords. */
+- (void) setPasswords: (NSDictionary*)passwords;
+
+/** Returns the password assigned to a user name, or nil if the name is not recognized. */
+- (NSString*) passwordForUser: (NSString*)username;
+
+
+/** Starts the listener. */
- (BOOL) start;
+
+/** Stops the listener. */
- (void) stop;
@end
31 Listener/TDListener.m
View
@@ -24,7 +24,7 @@
@implementation TDListener
-@synthesize readOnly=_readOnly;
+@synthesize readOnly=_readOnly, requiresAuth=_requiresAuth, realm=_realm;
- (id) initWithTDServer: (TDServer*)server port: (UInt16)port {
@@ -36,6 +36,7 @@ - (id) initWithTDServer: (TDServer*)server port: (UInt16)port {
_httpServer.tdServer = _tdServer;
_httpServer.port = port;
_httpServer.connectionClass = [TDHTTPConnection class];
+ self.realm = @"TouchDB";
}
return self;
}
@@ -46,10 +47,22 @@ - (void)dealloc
[self stop];
[_tdServer release];
[_httpServer release];
+ [_realm release];
+ [_passwords release];
[super dealloc];
}
+- (void) setBonjourName: (NSString*)name type: (NSString*)type {
+ _httpServer.name = name;
+ _httpServer.type = type;
+}
+
+- (NSDictionary *)TXTRecordDictionary {return _httpServer.TXTRecordDictionary;}
+- (void)setTXTRecordDictionary:(NSDictionary *)dict {_httpServer.TXTRecordDictionary = dict;}
+
+
+
- (BOOL) start {
NSError* error;
return [_httpServer start: &error];
@@ -60,6 +73,22 @@ - (void) stop {
}
+- (UInt16) port {
+ return _httpServer.listeningPort;
+}
+
+
+- (void) setPasswords: (NSDictionary*)passwords {
+ [_passwords autorelease];
+ _passwords = [passwords copy];
+ _requiresAuth = (_passwords != nil);
+}
+
+- (NSString*) passwordForUser:(NSString *)username {
+ return [_passwords objectForKey: username];
+}
+
+
@end
Please sign in to comment.
Something went wrong with that request. Please try again.