HTTPServer.m.svn-base
上传用户:kc0325
上传日期:2020-06-20
资源大小:204k
文件大小:9k
源码类别:

iPhone

开发平台:

Objective-C

  1. #import "AsyncSocket.h"
  2. #import "HTTPServer.h"
  3. #import "HTTPConnection.h"
  4. @implementation HTTPServer
  5. /**
  6.  * Standard Constructor.
  7.  * Instantiates an HTTP server, but does not start it.
  8. **/
  9. - (id)init
  10. {
  11. if(self = [super init])
  12. {
  13. // Initialize underlying asynchronous tcp/ip socket
  14. asyncSocket = [[AsyncSocket alloc] initWithDelegate:self];
  15. // Use default connection class of HTTPConnection
  16. connectionClass = [HTTPConnection self];
  17. // Configure default values for bonjour service
  18. // Use a default port of 0
  19. // This will allow the kernel to automatically pick an open port for us
  20. port = 0;
  21. // Bonjour domain. Use the local domain by default
  22. domain = @"local.";
  23. // If using an empty string ("") for the service name when registering,
  24. // the system will automatically use the "Computer Name".
  25. // Passing in an empty string will also handle name conflicts
  26. // by automatically appending a digit to the end of the name.
  27. name = @"";
  28. // Initialize an array to hold all the HTTP connections
  29. connections = [[NSMutableArray alloc] init];
  30. // And register for notifications of closed connections
  31. [[NSNotificationCenter defaultCenter] addObserver:self
  32.  selector:@selector(connectionDidDie:)
  33.  name:HTTPConnectionDidDieNotification
  34.    object:nil];
  35. }
  36. return self;
  37. }
  38. /**
  39.  * Standard Deconstructor.
  40.  * Stops the server, and clients, and releases any resources connected with this instance.
  41. **/
  42. - (void)dealloc
  43. {
  44. // Remove notification observer
  45. [[NSNotificationCenter defaultCenter] removeObserver:self];
  46. // Stop the server if it's running
  47. [self stop];
  48. // Release all instance variables
  49. [documentRoot release];
  50. [netService release];
  51.     [domain release];
  52.     [name release];
  53.     [type release];
  54. [txtRecordDictionary release];
  55. [asyncSocket release];
  56. [connections release];
  57. [super dealloc];
  58. }
  59. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  60. #pragma mark Server Configuration:
  61. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  62. /**
  63.  * Returns the delegate connected with this instance.
  64. **/
  65. - (id)delegate
  66. {
  67. return delegate;
  68. }
  69. /**
  70.  * Sets the delegate connected with this instance.
  71. **/
  72. - (void)setDelegate:(id)newDelegate
  73. {
  74. delegate = newDelegate;
  75. }
  76. /**
  77.  * The document root is filesystem root for the webserver.
  78.  * Thus requests for /index.html will be referencing the index.html file within the document root directory.
  79.  * All file requests are relative to this document root.
  80. **/
  81. - (NSURL *)documentRoot {
  82.     return documentRoot;
  83. }
  84. - (void)setDocumentRoot:(NSURL *)value
  85. {
  86.     if(![documentRoot isEqual:value])
  87. {
  88.         [documentRoot release];
  89.         documentRoot = [value copy];
  90.     }
  91. }
  92. /**
  93.  * The connection class is the class that will be used to handle connections.
  94.  * That is, when a new connection is created, an instance of this class will be intialized.
  95.  * The default connection class is HTTPConnection.
  96.  * If you use a different connection class, it is assumed that the class extends HTTPConnection
  97. **/
  98. - (Class)connectionClass {
  99.     return connectionClass;
  100. }
  101. - (void)setConnectionClass:(Class)value
  102. {
  103.     connectionClass = value;
  104. }
  105. /**
  106.  * Domain on which to broadcast this service via Bonjour.
  107.  * The default domain is @"local".
  108. **/
  109. - (NSString *)domain {
  110.     return domain;
  111. }
  112. - (void)setDomain:(NSString *)value
  113. {
  114. if(![domain isEqualToString:value])
  115. {
  116. [domain release];
  117.         domain = [value copy];
  118.     }
  119. }
  120. /**
  121.  * The type of service to publish via Bonjour.
  122.  * No type is set by default, and one must be set in order for the service to be published.
  123. **/
  124. - (NSString *)type {
  125.     return type;
  126. }
  127. - (void)setType:(NSString *)value
  128. {
  129. if(![type isEqualToString:value])
  130. {
  131. [type release];
  132. type = [value copy];
  133.     }
  134. }
  135. /**
  136.  * The name to use for this service via Bonjour.
  137.  * The default name is the host name of the computer.
  138. **/
  139. - (NSString *)name {
  140.     return name;
  141. }
  142. - (void)setName:(NSString *)value
  143. {
  144. if(![name isEqualToString:value])
  145. {
  146.         [name release];
  147.         name = [value copy];
  148.     }
  149. }
  150. /**
  151.  * The port to listen for connections on.
  152.  * By default this port is initially set to zero, which allows the kernel to pick an available port for us.
  153.  * After the HTTP server has started, the port being used may be obtained by this method.
  154. **/
  155. - (UInt16)port {
  156.     return port;
  157. }
  158. - (void)setPort:(UInt16)value {
  159.     port = value;
  160. }
  161. /**
  162.  * The extra data to use for this service via Bonjour.
  163. **/
  164. - (NSDictionary *)TXTRecordDictionary {
  165. return txtRecordDictionary;
  166. }
  167. - (void)setTXTRecordDictionary:(NSDictionary *)value
  168. {
  169. if(![txtRecordDictionary isEqualToDictionary:value])
  170. {
  171. [txtRecordDictionary release];
  172. txtRecordDictionary = [value copy];
  173. // And update the txtRecord of the netService if it has already been published
  174. if(netService)
  175. {
  176. [netService setTXTRecordData:[NSNetService dataFromTXTRecordDictionary:txtRecordDictionary]];
  177. }
  178. }
  179. }
  180. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  181. #pragma mark Server Control:
  182. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  183. - (BOOL)start:(NSError **)error
  184. {
  185. BOOL success = [asyncSocket acceptOnPort:port error:error];
  186. if(success)
  187. {
  188. // Update our port number
  189. [self setPort:[asyncSocket localPort]];
  190. // Output console message for debugging purposes
  191. NSLog(@"Started HTTP server on port: %hu", port);
  192. // We can only publish our bonjour service if a type has been set
  193. if(type != nil)
  194. {
  195. // Create the NSNetService with our basic parameters
  196. netService = [[NSNetService alloc] initWithDomain:domain type:type name:name port:port];
  197. [netService setDelegate:self];
  198. [netService publish];
  199. // Do not set the txtRecordDictionary prior to publishing!!!
  200. // This will cause the OS to crash!!!
  201. // Set the txtRecordDictionary if we have one
  202. if(txtRecordDictionary != nil)
  203. {
  204. [netService setTXTRecordData:[NSNetService dataFromTXTRecordDictionary:txtRecordDictionary]];
  205. }
  206. }
  207. }
  208. else
  209. {
  210. NSLog(@"Failed to start HTTP Server: %@", error);
  211. }
  212. return success;
  213. }
  214. - (BOOL)stop
  215. {
  216. // First stop publishing the service via bonjour
  217. if(netService)
  218. {
  219. [netService stop];
  220. [netService release];
  221. netService = nil;
  222. }
  223. // Now stop the asynchronouse tcp server
  224. // This will prevent it from accepting any more connections
  225. [asyncSocket disconnect];
  226. // Now stop all HTTP connections the server owns
  227. [connections removeAllObjects];
  228. return YES;
  229. }
  230. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  231. #pragma mark Server Status:
  232. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  233. /**
  234.  * Returns the number of clients that are currently connected to the server.
  235. **/
  236. - (int)numberOfHTTPConnections
  237. {
  238. return [connections count];
  239. }
  240. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  241. #pragma mark AsyncSocket Delegate Methods:
  242. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  243. -(void)onSocket:(AsyncSocket *)sock didAcceptNewSocket:(AsyncSocket *)newSocket
  244. {
  245. id newConnection = [[connectionClass alloc] initWithAsyncSocket:newSocket forServer:self];
  246. [connections addObject:newConnection];
  247. [newConnection release];
  248. }
  249. /**
  250.  * This method is automatically called when a notification of type HTTPConnectionDidDieNotification is posted.
  251.  * It allows us to remove the connection from our array.
  252. **/
  253. - (void)connectionDidDie:(NSNotification *)notification
  254. {
  255. [connections removeObject:[notification object]];
  256. }
  257. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  258. #pragma mark Bonjour Delegate Methods:
  259. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  260. /**
  261.  * Called when our bonjour service has been successfully published.
  262.  * This method does nothing but output a log message telling us about the published service.
  263. **/
  264. - (void)netServiceDidPublish:(NSNetService *)ns
  265. {
  266. // Override me to do something here...
  267. NSLog(@"Bonjour Service Published: domain(%@) type(%@) name(%@)", [ns domain], [ns type], [ns name]);
  268. }
  269. /**
  270.  * Called if our bonjour service failed to publish itself.
  271.  * This method does nothing but output a log message telling us about the published service.
  272. **/
  273. - (void)netService:(NSNetService *)ns didNotPublish:(NSDictionary *)errorDict
  274. {
  275. // Override me to do something here...
  276. NSLog(@"Failed to Publish Service: domain(%@) type(%@) name(%@)", [ns domain], [ns type], [ns name]);
  277. NSLog(@"Error Dict: %@", errorDict);
  278. }
  279. @end