Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
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
@snej snej authored
View
20 Demo-Mac/TouchServ.m
@@ -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];
View
14 Listener/TDHTTPConnection.m
@@ -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];
View
40 Listener/TDListener.h
@@ -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
View
31 Listener/TDListener.m
@@ -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

0 comments on commit 0235b18

Please sign in to comment.
Something went wrong with that request. Please try again.