You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
99 lines
3.6 KiB
99 lines
3.6 KiB
//////////////////////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// FoundationHTTPHandler.swift
|
|
// Starscream
|
|
//
|
|
// Created by Dalton Cherry on 4/2/19.
|
|
// Copyright © 2019 Vluxe. All rights reserved.
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
import Foundation
|
|
|
|
public class FoundationHTTPServerHandler: HTTPServerHandler {
|
|
var buffer = Data()
|
|
weak var delegate: HTTPServerDelegate?
|
|
let getVerb: NSString = "GET"
|
|
|
|
public func register(delegate: HTTPServerDelegate) {
|
|
self.delegate = delegate
|
|
}
|
|
|
|
public func createResponse(headers: [String: String]) -> Data {
|
|
#if os(watchOS)
|
|
//TODO: build response header
|
|
return Data()
|
|
#else
|
|
let response = CFHTTPMessageCreateResponse(kCFAllocatorDefault, HTTPWSHeader.switchProtocolCode,
|
|
nil, kCFHTTPVersion1_1).takeRetainedValue()
|
|
|
|
//TODO: add other values to make a proper response here...
|
|
//TODO: also sec key thing (Sec-WebSocket-Key)
|
|
for (key, value) in headers {
|
|
CFHTTPMessageSetHeaderFieldValue(response, key as CFString, value as CFString)
|
|
}
|
|
guard let cfData = CFHTTPMessageCopySerializedMessage(response)?.takeRetainedValue() else {
|
|
return Data()
|
|
}
|
|
return cfData as Data
|
|
#endif
|
|
}
|
|
|
|
public func parse(data: Data) {
|
|
buffer.append(data)
|
|
if parseContent(data: buffer) {
|
|
buffer = Data()
|
|
}
|
|
}
|
|
|
|
//returns true when the buffer should be cleared
|
|
func parseContent(data: Data) -> Bool {
|
|
var pointer = [UInt8]()
|
|
data.withUnsafeBytes { pointer.append(contentsOf: $0) }
|
|
#if os(watchOS)
|
|
//TODO: parse data
|
|
return false
|
|
#else
|
|
let response = CFHTTPMessageCreateEmpty(kCFAllocatorDefault, true).takeRetainedValue()
|
|
if !CFHTTPMessageAppendBytes(response, pointer, data.count) {
|
|
return false //not enough data, wait for more
|
|
}
|
|
if !CFHTTPMessageIsHeaderComplete(response) {
|
|
return false //not enough data, wait for more
|
|
}
|
|
if let method = CFHTTPMessageCopyRequestMethod(response)?.takeRetainedValue() {
|
|
if (method as NSString) != getVerb {
|
|
delegate?.didReceive(event: .failure(HTTPUpgradeError.invalidData))
|
|
return true
|
|
}
|
|
}
|
|
|
|
if let cfHeaders = CFHTTPMessageCopyAllHeaderFields(response) {
|
|
let nsHeaders = cfHeaders.takeRetainedValue() as NSDictionary
|
|
var headers = [String: String]()
|
|
for (key, value) in nsHeaders {
|
|
if let key = key as? String, let value = value as? String {
|
|
headers[key] = value
|
|
}
|
|
}
|
|
delegate?.didReceive(event: .success(headers))
|
|
return true
|
|
}
|
|
|
|
delegate?.didReceive(event: .failure(HTTPUpgradeError.invalidData))
|
|
return true
|
|
#endif
|
|
}
|
|
}
|