Skip to content

Commit 647ba90

Browse files
committed
Refactoring protocol common code into NativeProtocol
1 parent 6dea2bc commit 647ba90

File tree

7 files changed

+885
-735
lines changed

7 files changed

+885
-735
lines changed

Foundation.xcodeproj/project.pbxproj

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -309,6 +309,8 @@
309309
5BF9B8011FABD5DA00EE1A7C /* CFBundle_ResourceFork.c in Sources */ = {isa = PBXBuildFile; fileRef = 5BF9B7F61FABD5D400EE1A7C /* CFBundle_ResourceFork.c */; };
310310
5BF9B8021FABD5DA00EE1A7C /* CFBundle_Tables.c in Sources */ = {isa = PBXBuildFile; fileRef = 5BF9B7F71FABD5D400EE1A7C /* CFBundle_Tables.c */; };
311311
5FE52C951D147D1C00F7D270 /* TestNSTextCheckingResult.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5FE52C941D147D1C00F7D270 /* TestNSTextCheckingResult.swift */; };
312+
61AB1C4C1FD151B8000947CC /* NativeProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61AB1C4B1FD151B8000947CC /* NativeProtocol.swift */; };
313+
61B669201FD53F0200EAA8EC /* HTTPMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61B6691F1FD53F0200EAA8EC /* HTTPMessage.swift */; };
312314
61E0117D1C1B5590000037DD /* RunLoop.swift in Sources */ = {isa = PBXBuildFile; fileRef = EADE0B761BD15DFF00C49C64 /* RunLoop.swift */; };
313315
61E0117E1C1B55B9000037DD /* Timer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BDC3F481BCC5DCB00ED97BB /* Timer.swift */; };
314316
61E0117F1C1B5990000037DD /* CFRunLoop.c in Sources */ = {isa = PBXBuildFile; fileRef = 5B5D88D81BBC9AD800234F36 /* CFRunLoop.c */; };
@@ -337,7 +339,7 @@
337339
B9974B971EDF4A22007F15B8 /* MultiHandle.swift in Sources */ = {isa = PBXBuildFile; fileRef = B9974B901EDF4A22007F15B8 /* MultiHandle.swift */; };
338340
B9974B981EDF4A22007F15B8 /* libcurlHelpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = B9974B911EDF4A22007F15B8 /* libcurlHelpers.swift */; };
339341
B9974B991EDF4A22007F15B8 /* HTTPURLProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = B9974B921EDF4A22007F15B8 /* HTTPURLProtocol.swift */; };
340-
B9974B9A1EDF4A22007F15B8 /* HTTPMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = B9974B931EDF4A22007F15B8 /* HTTPMessage.swift */; };
342+
B9974B9A1EDF4A22007F15B8 /* Message.swift in Sources */ = {isa = PBXBuildFile; fileRef = B9974B931EDF4A22007F15B8 /* Message.swift */; };
341343
B9974B9B1EDF4A22007F15B8 /* BodySource.swift in Sources */ = {isa = PBXBuildFile; fileRef = B9974B941EDF4A22007F15B8 /* BodySource.swift */; };
342344
B9974B9C1EDF4A22007F15B8 /* EasyHandle.swift in Sources */ = {isa = PBXBuildFile; fileRef = B9974B951EDF4A22007F15B8 /* EasyHandle.swift */; };
343345
BD8042161E09857800487EB8 /* TestLengthFormatter.swift in Sources */ = {isa = PBXBuildFile; fileRef = BD8042151E09857800487EB8 /* TestLengthFormatter.swift */; };
@@ -779,6 +781,8 @@
779781
5EF673AB1C28B527006212A3 /* TestNotificationQueue.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestNotificationQueue.swift; sourceTree = "<group>"; };
780782
5FE52C941D147D1C00F7D270 /* TestNSTextCheckingResult.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestNSTextCheckingResult.swift; sourceTree = "<group>"; };
781783
61A395F91C2484490029B337 /* TestNSLocale.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestNSLocale.swift; sourceTree = "<group>"; };
784+
61AB1C4B1FD151B8000947CC /* NativeProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NativeProtocol.swift; sourceTree = "<group>"; };
785+
61B6691F1FD53F0200EAA8EC /* HTTPMessage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HTTPMessage.swift; sourceTree = "<group>"; };
782786
61D6C9EE1C1DFE9500DEF583 /* TestTimer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestTimer.swift; sourceTree = "<group>"; };
783787
61E0117B1C1B554D000037DD /* TestRunLoop.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestRunLoop.swift; sourceTree = "<group>"; };
784788
61F8AE7C1C180FC600FB62F0 /* TestNotificationCenter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestNotificationCenter.swift; sourceTree = "<group>"; };
@@ -810,11 +814,11 @@
810814
B933A79C1F3055F600FE6846 /* NSString-UTF32-BE-data.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = "NSString-UTF32-BE-data.txt"; sourceTree = "<group>"; };
811815
B933A79D1F3055F600FE6846 /* NSString-UTF32-LE-data.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = "NSString-UTF32-LE-data.txt"; sourceTree = "<group>"; };
812816
B951B5EB1F4E2A2000D8B332 /* TestNSLock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestNSLock.swift; sourceTree = "<group>"; };
813-
B9974B8F1EDF4A22007F15B8 /* TransferState.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = TransferState.swift; path = http/TransferState.swift; sourceTree = "<group>"; };
817+
B9974B8F1EDF4A22007F15B8 /* TransferState.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TransferState.swift; sourceTree = "<group>"; };
814818
B9974B901EDF4A22007F15B8 /* MultiHandle.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MultiHandle.swift; sourceTree = "<group>"; };
815819
B9974B911EDF4A22007F15B8 /* libcurlHelpers.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = libcurlHelpers.swift; sourceTree = "<group>"; };
816820
B9974B921EDF4A22007F15B8 /* HTTPURLProtocol.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = HTTPURLProtocol.swift; path = http/HTTPURLProtocol.swift; sourceTree = "<group>"; };
817-
B9974B931EDF4A22007F15B8 /* HTTPMessage.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = HTTPMessage.swift; path = http/HTTPMessage.swift; sourceTree = "<group>"; };
821+
B9974B931EDF4A22007F15B8 /* Message.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Message.swift; sourceTree = "<group>"; };
818822
B9974B941EDF4A22007F15B8 /* BodySource.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BodySource.swift; sourceTree = "<group>"; };
819823
B9974B951EDF4A22007F15B8 /* EasyHandle.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EasyHandle.swift; sourceTree = "<group>"; };
820824
BD8042151E09857800487EB8 /* TestLengthFormatter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestLengthFormatter.swift; sourceTree = "<group>"; };
@@ -1010,12 +1014,15 @@
10101014
614732781FC2DEB7005B5E61 /* libcurl */,
10111015
E4F889331E9CF04D008A70EB /* http */,
10121016
5B1FD9C81D6D16580080E83C /* Configuration.swift */,
1017+
B9974B931EDF4A22007F15B8 /* Message.swift */,
1018+
B9974B8F1EDF4A22007F15B8 /* TransferState.swift */,
10131019
B9974B941EDF4A22007F15B8 /* BodySource.swift */,
10141020
5B1FD9CE1D6D16580080E83C /* URLSession.swift */,
10151021
5B1FD9CF1D6D16580080E83C /* URLSessionConfiguration.swift */,
10161022
5B1FD9D01D6D16580080E83C /* URLSessionDelegate.swift */,
10171023
5B1FD9D11D6D16580080E83C /* URLSessionTask.swift */,
10181024
5B1FD9D21D6D16580080E83C /* TaskRegistry.swift */,
1025+
61AB1C4B1FD151B8000947CC /* NativeProtocol.swift */,
10191026
);
10201027
name = Session;
10211028
path = URLSession;
@@ -1398,8 +1405,7 @@
13981405
isa = PBXGroup;
13991406
children = (
14001407
B9974B921EDF4A22007F15B8 /* HTTPURLProtocol.swift */,
1401-
B9974B8F1EDF4A22007F15B8 /* TransferState.swift */,
1402-
B9974B931EDF4A22007F15B8 /* HTTPMessage.swift */,
1408+
61B6691F1FD53F0200EAA8EC /* HTTPMessage.swift */,
14031409
);
14041410
name = http;
14051411
sourceTree = "<group>";
@@ -2200,7 +2206,10 @@
22002206
5BF7AEBB1BCD51F9008F214A /* NSSwiftRuntime.swift in Sources */,
22012207
5B5C5EF01CE61FA4001346BD /* Date.swift in Sources */,
22022208
EADE0B9B1BD15DFF00C49C64 /* FileHandle.swift in Sources */,
2209+
B9974B9A1EDF4A22007F15B8 /* Message.swift in Sources */,
22032210
B9974B9C1EDF4A22007F15B8 /* EasyHandle.swift in Sources */,
2211+
B9974B961EDF4A22007F15B8 /* TransferState.swift in Sources */,
2212+
61AB1C4C1FD151B8000947CC /* NativeProtocol.swift in Sources */,
22042213
EADE0BB11BD15E0000C49C64 /* NSPredicate.swift in Sources */,
22052214
5BF7AEC01BCD51F9008F214A /* NSUUID.swift in Sources */,
22062215
EADE0BCB1BD15E0000C49C64 /* XMLNode.swift in Sources */,
@@ -2245,7 +2254,6 @@
22452254
EADE0BB31BD15E0000C49C64 /* NSRegularExpression.swift in Sources */,
22462255
EADE0BA41BD15E0000C49C64 /* LengthFormatter.swift in Sources */,
22472256
5BDC3FCA1BCF176100ED97BB /* NSCFArray.swift in Sources */,
2248-
B9974B961EDF4A22007F15B8 /* TransferState.swift in Sources */,
22492257
EADE0BB21BD15E0000C49C64 /* Progress.swift in Sources */,
22502258
EADE0B961BD15DFF00C49C64 /* DateIntervalFormatter.swift in Sources */,
22512259
5B5BFEAC1E6CC0C200AC8D9E /* NSCFBoolean.swift in Sources */,
@@ -2295,13 +2303,13 @@
22952303
EADE0BBC1BD15E0000C49C64 /* URLCache.swift in Sources */,
22962304
5B4092121D1B30B40022B067 /* ExtraStringAPIs.swift in Sources */,
22972305
5BC46D541D05D6D900005853 /* DateInterval.swift in Sources */,
2306+
61B669201FD53F0200EAA8EC /* HTTPMessage.swift in Sources */,
22982307
EADE0BC51BD15E0000C49C64 /* UserDefaults.swift in Sources */,
22992308
5BF7AEB11BCD51F9008F214A /* NSLock.swift in Sources */,
23002309
5BF7AEB91BCD51F9008F214A /* NSSet.swift in Sources */,
23012310
EADE0B9E1BD15DFF00C49C64 /* HTTPCookie.swift in Sources */,
23022311
5BCCA8D91CE6697F0059B963 /* URLComponents.swift in Sources */,
23032312
5BDC3FCC1BCF177E00ED97BB /* NSCFString.swift in Sources */,
2304-
B9974B9A1EDF4A22007F15B8 /* HTTPMessage.swift in Sources */,
23052313
EADE0BAC1BD15E0000C49C64 /* NSOrderedSet.swift in Sources */,
23062314
EADE0BC31BD15E0000C49C64 /* URLResponse.swift in Sources */,
23072315
EADE0B971BD15DFF00C49C64 /* Decimal.swift in Sources */,

Foundation/URLSession/Message.swift

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
// Foundation/URLSession/Message.swift - Message parsing for native protocols
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See http://swift.org/LICENSE.txt for license information
9+
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
// -----------------------------------------------------------------------------
12+
///
13+
/// These are libcurl helpers for the URLSession API code.
14+
/// - SeeAlso: https://curl.haxx.se/libcurl/c/
15+
/// - SeeAlso: URLSession.swift
16+
///
17+
// -----------------------------------------------------------------------------
18+
19+
extension _NativeProtocol {
20+
/// A native protocol header like FTP or HTTP being parsed.
21+
///
22+
/// It can either be complete (i.e. the final CR LF CR LF has been
23+
/// received), or partial.
24+
internal enum _ParsedResponseHeader {
25+
case partial(_ResponseHeaderLines)
26+
case complete(_ResponseHeaderLines)
27+
init() {
28+
self = .partial(_ResponseHeaderLines())
29+
}
30+
}
31+
/// A type safe wrapper around multiple lines of headers.
32+
///
33+
/// This can be converted into an `HTTPURLResponse`.
34+
internal struct _ResponseHeaderLines {
35+
let lines: [String]
36+
init() {
37+
self.lines = []
38+
}
39+
init(headerLines: [String]) {
40+
self.lines = headerLines
41+
}
42+
}
43+
}
44+
45+
extension _NativeProtocol._ParsedResponseHeader {
46+
/// Parse a header line passed by libcurl.
47+
///
48+
/// These contain the <CRLF> ending and the final line contains nothing but
49+
/// that ending.
50+
/// - Returns: Returning nil indicates failure. Otherwise returns a new
51+
/// `ParsedResponseHeader` with the given line added.
52+
func byAppending(headerLine data: Data, isHeaderComplete: (String) -> Bool) -> _NativeProtocol._ParsedResponseHeader? {
53+
// The buffer must end in CRLF
54+
guard 2 <= data.count &&
55+
data[data.endIndex - 2] == _Delimiters.CR &&
56+
data[data.endIndex - 1] == _Delimiters.LF
57+
else { return nil }
58+
let lineBuffer = data.subdata(in: Range(data.startIndex..<data.endIndex-2))
59+
guard let line = String(data: lineBuffer, encoding: String.Encoding.utf8) else { return nil}
60+
return byAppending(headerLine: line, isHeaderComplete: isHeaderComplete)
61+
}
62+
/// Append a status line.
63+
///
64+
/// If the line is empty, it marks the end of the header, and the result
65+
/// is a complete header. Otherwise it's a partial header.
66+
/// - Note: Appending a line to a complete header results in a partial
67+
/// header with just that line.
68+
private func byAppending(headerLine line: String, isHeaderComplete: (String) -> Bool) -> _NativeProtocol._ParsedResponseHeader {
69+
if isHeaderComplete(line) {
70+
switch self {
71+
case .partial(let header): return .complete(header)
72+
case .complete: return .partial(_NativeProtocol._ResponseHeaderLines())
73+
}
74+
} else {
75+
let header = partialResponseHeader
76+
return .partial(header.byAppending(headerLine: line))
77+
}
78+
}
79+
80+
private var partialResponseHeader: _NativeProtocol._ResponseHeaderLines {
81+
switch self {
82+
case .partial(let header): return header
83+
case .complete: return _NativeProtocol._ResponseHeaderLines()
84+
}
85+
}
86+
}
87+
88+
private extension _NativeProtocol._ResponseHeaderLines {
89+
/// Returns a copy of the lines with the new line appended to it.
90+
func byAppending(headerLine line: String) -> _NativeProtocol._ResponseHeaderLines {
91+
var l = self.lines
92+
l.append(line)
93+
return _NativeProtocol._ResponseHeaderLines(headerLines: l)
94+
}
95+
}
96+
97+
// Characters that we need for Header parsing:
98+
99+
struct _Delimiters {
100+
/// *Carriage Return* symbol
101+
static let CR: UInt8 = 0x0d
102+
/// *Line Feed* symbol
103+
static let LF: UInt8 = 0x0a
104+
/// *Space* symbol
105+
static let Space = UnicodeScalar(0x20)
106+
static let HorizontalTab = UnicodeScalar(0x09)
107+
static let Colon = UnicodeScalar(0x3a)
108+
/// *Separators* according to RFC 2616
109+
static let Separators = NSCharacterSet(charactersIn: "()<>@,;:\\\"/[]?={} \t")
110+
}
111+

0 commit comments

Comments
 (0)