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_
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 {
: 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: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
: Int { 0034 case 0035 NotProcessed
Document.swift:33
        return .NotProcessed
Document.swift:175
        return .NotProcessed
Proxies.swift:39
            return .NotProcessed
Proxies.swift:98
        return .NotProcessed
Servers.swift:133
                    case .NotProcessed:
Swiftlets.swift:45
        return .NotProcessed
Swiftlets.swift:373
                return .NotProcessed
Swiftlets.swift:391
                    return .NotProcessed
Swiftlets.swift:403
        return .NotProcessed
, // does not recogise the request 0036 Processed
Proxies.swift:72
        return .Processed
Proxies.swift:95
            return .Processed
Servers.swift:135
                    case .Processed:
Swiftlets.swift:76
                return httpClient.knowsResponseLength ? .ProcessedAndReusable : .Processed
Swiftlets.swift:91
        return httpClient.knowsResponseLength ? .ProcessedAndReusable : .Processed
, // has processed the request 0037 ProcessedAndReusable
Connection.swift:396
        return .ProcessedAndReusable
Servers.swift:137
                    case .ProcessedAndReusable:
Swiftlets.swift:76
                return httpClient.knowsResponseLength ? .ProcessedAndReusable : .Processed
Swiftlets.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:381
    public func sendResponse( resp: DynamoResponse ) -> DynamoProcessed {
{ 0045 case OK
Connection.swift:385
        case .OK( let html ):
Proxies.swift:69
                httpClient.sendResponse( .OK( html: "Unable to resolve host \(host)" ) )
( html: String ) 0046 case Data
Connection.swift:389
        case .Data( let data ):
Document.swift:165
                    return httpClient.sendResponse( .Data( data: data ) )
( data: NSData ) 0047 case JSON
Connection.swift:387
        case .JSON( let json ):
( json: AnyObject ) 0048 case Status
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)" ) )
( 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
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 {
{ 0065 0066 /** 0067 each request is presented ot each swiftlet until one indicates it has processed the request 0068 */ 0069 func present
Servers.swift:132
                    switch swiftlet.present( httpClient ) {
( 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
Swiftlets.swift:26
public class ApplicationSwiftlet: _NSObject_, DynamoBrowserSwiftlet {
: 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
Servers.swift:64
        ip4addr.sin_addr = in_addr( s_addr: INADDR_ANY )
= in_addr_t(0) 0091 #if os(Linux) 0092 let sockType = Int32(SOCK_STREAM.rawValue) 0093 #else 0094 let sockType
Connection.swift:117
                let remoteSocket = socket( Int32(addr.sa_family), sockType, 0 )
Servers.swift:70
        serverSocket = socket( Int32(ip4addr.sin_family), sockType, 0 )
= SOCK_STREAM 0095 #endif 0096 0097 func htons
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 )
( port: UInt16 ) -> UInt16 { 0098 return (port << 8) + (port >> 8) 0099 } 0100 let ntohs
Servers.swift:90
            serverPort = ntohs( ip4addr.sin_port )
= htons 0101 0102 func sockaddr_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).memory
Types.swift:183
            sockaddrPtr.memory = sockaddr_cast(&ip6addr).memory
(p: UnsafeMutablePointer<Void>) -> UnsafeMutablePointer<sockaddr> { 0103 return UnsafeMutablePointer<sockaddr>(p) 0104 } 0105 0106 func sockaddr_in_cast
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 )
(p: UnsafeMutablePointer<sockaddr>) -> UnsafeMutablePointer<sockaddr_in> { 0107 return UnsafeMutablePointer<sockaddr_in>(p) 0108 } 0109 0110 /** default tracer for frequent messages */ 0111 public func dynamoTrace
Servers.swift:213
                        DynamoSelector.relay( "surrogate", from: sslConnection, to: surrogateConnection, dynamoTrace )
<T>( msg: T ) { 0112 print( msg ) 0113 } 0114 0115 /** logger for server errors */ 0116 func dynamoLog
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)" )
<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: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" )
( 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
Types.swift:143
    var sockaddrTmp = hostAddressCache[hostname]?.memory
Types.swift:190
        hostAddressCache[hostname] = sockaddrPtr
= [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
Connection.swift:109
            if let addr = addressForHost( host, port: port ) {
( 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:432
            if let deflated = dout.deflate() {
() -> NSData? { 0206 return nil 0207 } 0208 0209 } 0210