0001 // 0002 // Types.swift 0003 // Dynamo 0004 // 0005 // Created by John Holdsworth on 07/12/2015. 0006 // Copyright © 2015 John Holdsworth. All rights reserved. 0007 // 0008 0009 import Foundation 0010 0011 /** 0012 Linux can not inherit from NSObject for some reason and OSX/iOS must so... 0013 */ 0014 0015 #if os(Linux) 0016 import Glibc 0017 0018 public class _NSObject_ { 0019 init() { 0020 } 0021 } 0022 #else 0023 public class _NSObject_: NSObject { 0024 } 0025 #endif 0026 0027 /** 0028 Result returned by a swiftlet to indicate whether it has handled the request. If a "Content-Length" 0029 header has been provided the connection can be reused in the HTTP/1.1 protocol and the connection 0030 will be kept open and recycled. 0031 */ 0032 0033 @objc public enum DynamoProcessed
Connection.swift:49 public class DynamoHTTPRequest: _NSObject_ {Document.swift:21 public class LoggingSwiftlet: _NSObject_, DynamoSwiftlet {Document.swift:96 public class DocumentSwiftlet: _NSObject_, DynamoSwiftlet {Proxies.swift:26 public class ProxySwiftlet: _NSObject_, DynamoSwiftlet {Servers.swift:31 public class DynamoWebServer: _NSObject_ {Swiftlets.swift:26 public class ApplicationSwiftlet: _NSObject_, DynamoBrowserSwiftlet {: Int { 0034 case 0035 NotProcessed
Connection.swift:381 public func sendResponse( resp: DynamoResponse ) -> DynamoProcessed {Document.swift:31 public func present( httpClient: DynamoHTTPConnection ) -> DynamoProcessed {Document.swift:128 public func present( httpClient: DynamoHTTPConnection ) -> DynamoProcessed {Proxies.swift:36 public func present( httpClient: DynamoHTTPConnection ) -> DynamoProcessed {Proxies.swift:85 public override func present( httpClient: DynamoHTTPConnection ) -> DynamoProcessed {Swiftlets.swift:38 public func present( httpClient: DynamoHTTPConnection ) -> DynamoProcessed {Swiftlets.swift:53 public func process( httpClient: DynamoHTTPConnection, pathInfo: String ) -> DynamoProcessed {Swiftlets.swift:365 override public func present( httpClient: DynamoHTTPConnection ) -> DynamoProcessed {Types.swift:69 func present( httpClient: DynamoHTTPConnection ) -> DynamoProcessed, // does not recogise the request 0036 Processed
Document.swift:33 return .NotProcessedDocument.swift:175 return .NotProcessedProxies.swift:39 return .NotProcessedProxies.swift:98 return .NotProcessedServers.swift:133 case .NotProcessed:Swiftlets.swift:45 return .NotProcessedSwiftlets.swift:373 return .NotProcessedSwiftlets.swift:391 return .NotProcessedSwiftlets.swift:403 return .NotProcessed, // has processed the request 0037 ProcessedAndReusable
Proxies.swift:72 return .ProcessedProxies.swift:95 return .ProcessedServers.swift:135 case .Processed:Swiftlets.swift:76 return httpClient.knowsResponseLength ? .ProcessedAndReusable : .ProcessedSwiftlets.swift:91 return httpClient.knowsResponseLength ? .ProcessedAndReusable : .Processed// "" and connection may be reused 0038 } 0039 0040 /** 0041 Simple enum for response data 0042 */ 0043 0044 public enum DynamoResponse
Connection.swift:396 return .ProcessedAndReusableServers.swift:137 case .ProcessedAndReusable:Swiftlets.swift:76 return httpClient.knowsResponseLength ? .ProcessedAndReusable : .ProcessedSwiftlets.swift:91 return httpClient.knowsResponseLength ? .ProcessedAndReusable : .Processed{ 0045 case OK
Connection.swift:381 public func sendResponse( resp: DynamoResponse ) -> DynamoProcessed {( html: String ) 0046 case Data
Connection.swift:385 case .OK( let html ):Proxies.swift:69 httpClient.sendResponse( .OK( html: "Unable to resolve host \(host)" ) )( data: NSData ) 0047 case JSON
Connection.swift:389 case .Data( let data ):Document.swift:165 return httpClient.sendResponse( .Data( data: data ) )( json: AnyObject ) 0048 case Status
Connection.swift:387 case .JSON( let json ):( status: Int, text: String ) 0049 } 0050 0051 /** 0052 Basic protocol that switlets implement to pick up and process requests from a client. 0053 */ 0054 0055 #if os(Linux) 0056 public protocol DynamoSwiftlet { 0057 0058 /** 0059 each request is presented ot each swiftlet until one indicates it has processed the request 0060 */ 0061 func present( httpClient: DynamoHTTPConnection ) -> DynamoProcessed 0062 } 0063 #else 0064 @objc public protocol DynamoSwiftlet
Connection.swift:391 case .Status( let theStatus, let text ):Document.swift:161 return httpClient.sendResponse( .Status( status: 304, text: "" ) )Document.swift:171 return httpClient.sendResponse( .Status( status: 404, text: "<b>File not found:</b> \(fullPath)" ) ){ 0065 0066 /** 0067 each request is presented ot each swiftlet until one indicates it has processed the request 0068 */ 0069 func present
Document.swift:21 public class LoggingSwiftlet: _NSObject_, DynamoSwiftlet {Document.swift:96 public class DocumentSwiftlet: _NSObject_, DynamoSwiftlet {Proxies.swift:26 public class ProxySwiftlet: _NSObject_, DynamoSwiftlet {Servers.swift:33 private let swiftlets: [DynamoSwiftlet]Servers.swift:40 public convenience init?( portNumber: UInt16, swiftlets: [DynamoSwiftlet], localhostOnly: Bool = false ) {Servers.swift:49 init?( _ portNumber: UInt16, swiftlets: [DynamoSwiftlet], localhostOnly: Bool ) {Servers.swift:197 public init?( portNumber: UInt16, swiftlets: [DynamoSwiftlet] = [], certs: [AnyObject], surrogate: String? = nil ) {Types.swift:78 public protocol DynamoBrowserSwiftlet: DynamoSwiftlet {( httpClient: DynamoHTTPConnection ) -> DynamoProcessed 0070 } 0071 #endif 0072 0073 /** 0074 Once a swiftlet has decided it can handle a request the headers are interpreted to extract parameters 0075 and cookies and any POST parameters. The web application then implements this protocol. 0076 */ 0077 0078 public protocol DynamoBrowserSwiftlet
Servers.swift:132 switch swiftlet.present( httpClient ) {: DynamoSwiftlet { 0079 0080 /** 0081 A request can be further parsed to extract parameters, method "POST" data and cookies before processing 0082 */ 0083 0084 func processRequest( out: DynamoHTTPConnection, pathInfo: String, parameters: [String : String], cookies: [String : String] ) 0085 0086 } 0087 0088 // MARK: util definitions/functions 0089 0090 let INADDR_ANY
Swiftlets.swift:26 public class ApplicationSwiftlet: _NSObject_, DynamoBrowserSwiftlet {= in_addr_t(0) 0091 #if os(Linux) 0092 let sockType = Int32(SOCK_STREAM.rawValue) 0093 #else 0094 let sockType
Servers.swift:64 ip4addr.sin_addr = in_addr( s_addr: INADDR_ANY )= SOCK_STREAM 0095 #endif 0096 0097 func htons
Connection.swift:117 let remoteSocket = socket( Int32(addr.sa_family), sockType, 0 )Servers.swift:70 serverSocket = socket( Int32(ip4addr.sin_family), sockType, 0 )( port: UInt16 ) -> UInt16 { 0098 return (port << 8) + (port >> 8) 0099 } 0100 let ntohs
Servers.swift:63 ip4addr.sin_port = htons( portNumber )Types.swift:170 ip4addr.sin_port = htons( port )Types.swift:181 ip6addr.sin6_port = in_port_t(htons( port ))Types.swift:194 sockaddr_in_cast( &(sockaddrTmp!) ).memory.sin_port = htons( port )= htons 0101 0102 func sockaddr_cast
Servers.swift:90 serverPort = ntohs( ip4addr.sin_port )(p: UnsafeMutablePointer<Void>) -> UnsafeMutablePointer<sockaddr> { 0103 return UnsafeMutablePointer<sockaddr>(p) 0104 } 0105 0106 func sockaddr_in_cast
Servers.swift:83 else if bind( serverSocket, sockaddr_cast(&ip4addr), addrLen ) < 0 {Servers.swift:89 else if getsockname( serverSocket, sockaddr_cast(&ip4addr), &addrLen ) == 0 {Types.swift:172 sockaddrPtr.memory = sockaddr_cast(&ip4addr).memoryTypes.swift:183 sockaddrPtr.memory = sockaddr_cast(&ip6addr).memory(p: UnsafeMutablePointer<sockaddr>) -> UnsafeMutablePointer<sockaddr_in> { 0107 return UnsafeMutablePointer<sockaddr_in>(p) 0108 } 0109 0110 /** default tracer for frequent messages */ 0111 public func dynamoTrace
Connection.swift:142 return String.fromCString( inet_ntoa( sockaddr_in_cast(&addr).memory.sin_addr ) )!Types.swift:194 sockaddr_in_cast( &(sockaddrTmp!) ).memory.sin_port = htons( port )<T>( msg: T ) { 0112 print( msg ) 0113 } 0114 0115 /** logger for server errors */ 0116 func dynamoLog
Servers.swift:213 DynamoSelector.relay( "surrogate", from: sslConnection, to: surrogateConnection, dynamoTrace )<T>( msg: T ) { 0117 #if os(Linux) 0118 print( "DynamoWebServer: \(msg)" ) 0119 #else 0120 NSLog( "DynamoWebServer: %@", "\(msg)" ) 0121 #endif 0122 } 0123 0124 /** logger for low level errors */ 0125 func dynamoStrerror
Connection.swift:264 dynamoLog( "Could not read \(contentLength) bytes post data from client " )Connection.swift:287 dynamoLog( "JSON parse error:: \(error)" )Connection.swift:348 dynamoLog( "Cookies must be set before the first HTML content is sent" )Connection.swift:422 dynamoLog( "Could not encode: \(object) \(error)" )Connection.swift:441 dynamoLog( "Could not write \(dout.length) bytes to client " )Document.swift:170 dynamoLog( "404 File not Found: \(fullPath)" )Proxies.swift:241 dynamoLog( "Closing reader: \(fd)" )Proxies.swift:251 dynamoLog( "Closing writer: \(fd)" )Proxies.swift:294 dynamoLog( "Short write on relay \(writer.label)" )Proxies.swift:311 dynamoLog( "ERROR from select on relay" )Servers.swift:96 dynamoLog( "Server available on http\(s)://localhost:\(serverPort)" )Servers.swift:218 dynamoLog( "Invalid surrogate URL: \(surrogate)" )Swiftlets.swift:84 dynamoLog( "POST data not available" )Swiftlets.swift:116 dynamoLog( "DynamoApplicationSwiftlet.processRequest(): Subclass responsibility" )Swiftlets.swift:195 dynamoLog( "Missing app for session \(sessionKey)" )Swiftlets.swift:235 dynamoLog( "DynamoSessionApplication.processRequest(): Subclass responsibility" )Swiftlets.swift:285 dynamoLog( "Could not locate class with @objc name \(bundleName)Swiftlet in \(bundlePath)")Swiftlets.swift:289 dynamoLog( "Could not find/load swiftlet for bundle \(bundlePath)" )Swiftlets.swift:322 dynamoLog( "Could not reload bundle \(nextPath)" )Swiftlets.swift:326 dynamoLog( "Could not copy bundle to \(nextPath) \(error)" )Swiftlets.swift:390 dynamoLog( "Unable to parse .ssp path: \(sspPath)" )Swiftlets.swift:399 dynamoLog( "Missing .ssp bundle for path \(path)" )Types.swift:129 dynamoLog( "\(msg) - \( String.fromCString( strerror(errno) )! )" )Types.swift:153 dynamoLog( "Could not resolve \(hostname) - "+String.fromCString( hstrerror(h_errno) )! )Types.swift:186 dynamoLog( "Unknown address family: \(addr.memory.h_addrtype)" )( msg: String ) { 0126 #if os(Linux) 0127 dynamoLog( "\(msg)" ) 0128 #else 0129 dynamoLog( "\(msg) - \( String.fromCString( strerror(errno) )! )" ) 0130 #endif 0131 } 0132 0133 // MARK: Cached gethostbyname() 0134 0135 private var hostAddressCache
Connection.swift:97 dynamoStrerror( "Could not set SO_NOSIGPIPE" )Connection.swift:119 dynamoStrerror( "Could not obtain remote socket" )Connection.swift:122 dynamoStrerror( "Could not connect to: \(host):\(port)" )Proxies.swift:235 dynamoStrerror( "Select error \(readMap) \(writeMap)" )Servers.swift:78 dynamoStrerror( "Could not get server socket" )Servers.swift:81 dynamoStrerror( "Could not set SO_REUSEADDR" )Servers.swift:84 dynamoStrerror( "Could not bind service socket on port \(portNumber)" )Servers.swift:87 dynamoStrerror( "Server socket would not listen" )= [String:UnsafeMutablePointer<sockaddr>]() 0136 0137 /** 0138 Caching version of gethostbyname() returning a struct sockaddr for use in a connect() call 0139 */ 0140 public func addressForHost
Types.swift:143 var sockaddrTmp = hostAddressCache[hostname]?.memoryTypes.swift:190 hostAddressCache[hostname] = sockaddrPtr( hostname: String, port: UInt16 ) -> sockaddr? { 0141 0142 var addr: UnsafeMutablePointer<hostent> = nil 0143 var sockaddrTmp = hostAddressCache[hostname]?.memory 0144 0145 if sockaddrTmp == nil { 0146 hostname.withCString { (hostString) in 0147 addr = gethostbyname( hostString ) 0148 } 0149 if addr == nil { 0150 #if os(Linux) 0151 dynamoLog( "Could not resolve \(hostname)" ) 0152 #else 0153 dynamoLog( "Could not resolve \(hostname) - "+String.fromCString( hstrerror(h_errno) )! ) 0154 #endif 0155 return nil 0156 } 0157 } 0158 0159 if sockaddrTmp == nil { 0160 let sockaddrPtr = UnsafeMutablePointer<sockaddr>(malloc(sizeof(sockaddr.self))) 0161 switch addr.memory.h_addrtype { 0162 0163 case AF_INET: 0164 let addr0 = UnsafePointer<in_addr>(addr.memory.h_addr_list.memory) 0165 var ip4addr = sockaddr_in() 0166 #if !os(Linux) 0167 ip4addr.sin_len = UInt8(sizeof(sockaddr_in)) 0168 #endif 0169 ip4addr.sin_family = sa_family_t(addr.memory.h_addrtype) 0170 ip4addr.sin_port = htons( port ) 0171 ip4addr.sin_addr = addr0.memory 0172 sockaddrPtr.memory = sockaddr_cast(&ip4addr).memory 0173 0174 case AF_INET6: // TODO... completely untested 0175 let addr0 = UnsafePointer<in6_addr>(addr.memory.h_addr_list.memory) 0176 var ip6addr = sockaddr_in6() 0177 #if !os(Linux) 0178 ip6addr.sin6_len = UInt8(sizeof(sockaddr_in6)) 0179 #endif 0180 ip6addr.sin6_family = sa_family_t(addr.memory.h_addrtype) 0181 ip6addr.sin6_port = in_port_t(htons( port )) 0182 ip6addr.sin6_addr = addr0.memory 0183 sockaddrPtr.memory = sockaddr_cast(&ip6addr).memory 0184 0185 default: 0186 dynamoLog( "Unknown address family: \(addr.memory.h_addrtype)" ) 0187 return nil 0188 } 0189 0190 hostAddressCache[hostname] = sockaddrPtr 0191 sockaddrTmp = sockaddrPtr.memory 0192 } 0193 else { 0194 sockaddr_in_cast( &(sockaddrTmp!) ).memory.sin_port = htons( port ) 0195 } 0196 0197 return sockaddrTmp 0198 } 0199 0200 public extension NSData { 0201 0202 /** 0203 Overridden by NSData+deflate.m 0204 */ 0205 func deflate
Connection.swift:109 if let addr = addressForHost( host, port: port ) {() -> NSData? { 0206 return nil 0207 } 0208 0209 } 0210
Connection.swift:432 if let deflated = dout.deflate() {