9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
|
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
|
-
+
+
+
+
+
+
-
+
-
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
-
+
-
+
-
-
+
+
+
-
-
-
+
+
+
-
-
+
-
-
+
+
+
+
-
+
+
+
+
+
+
+
-
+
-
+
-
+
-
-
+
+
-
-
+
+
-
-
-
-
+
+
+
-
+
+
+
-
+
-
-
+
-
-
+
+
-
+
+
-
-
+
+
+
+
-
+
-
+
-
+
+
+
+
-
+
+
-
+
-
+
+
-
+
-
+
+
+
+
+
-
+
|
*
* Alternatively, it may be distributed under the terms of the GNU General
* Public License, either version 2 or 3, which can be found in the file
* LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
* file.
*/
#import "OFTCPSocket.h"
#import "OFStream.h"
#import "OFRunLoop.h"
OF_ASSUME_NONNULL_BEGIN
/** @file */
@class OFTLSStream;
/**
* @protocol OFTLSSocketDelegate OFTLSSocket.h ObjFW/OFTLSSocket.h
* @protocol OFTLSStreamDelegate OFTLSStream.h ObjFW/OFTLSStream.h
*
* A delegate for OFTLSSocket.
* A delegate for OFTLSStream.
*/
@protocol OFTLSSocketDelegate <OFTCPSocketDelegate>
@protocol OFTLSStreamDelegate <OFStreamDelegate>
/**
* @brief A method which is called when a TLS stream performed the client
* handshake.
*
* @param stream The TLS stream which performed the handshake
* @param host The host for which the handshake was performed
* @param exception An exception that occurred during the handshake, or nil on
* success
*/
- (void)stream: (OFTLSStream *)stream
didPerformClientHandshakeWithHost: (OFString *)host
exception: (nullable id)exception;
@end
/**
* @class OFTLSSocket OFTLSSocket.h ObjFW/OFTLSSocket.h
* @class OFTLSStream OFTLSStream.h ObjFW/OFTLSStream.h
*
* @brief A class that provides Transport Layer Security on top of a TCP socket.
* @brief A class that provides Transport Layer Security on top of a stream.
*
* This class is a class cluster and returns a suitable OFTLSSocket subclass,
* This class is a class cluster and returns a suitable OFTLSStream subclass,
* if available.
*
* Subclasses need to override @ref accept, @ref lowlevelReadIntoBuffer:length:,
* @ref lowlevelWriteBuffer:length: and @ref startTLSForHost:port:. The method
* Subclasses need to override @ref lowlevelReadIntoBuffer:length:,
* @ref lowlevelWriteBuffer:length: and
* @ref asyncPerformClientHandshakeWithHost:runLoopMode:. The method
* @ref hasDataInReadBuffer should be overridden to return `true` if the TLS
* socket has cached unprocessed data internally, while returning
* `[super hasDataInReadBuffer]` if it does not have any unprocessed data. In
* order to get access to the lowlevel TCP methods (you cannot call `super`, as
* stream has cached unprocessed data internally, while returning
* `self.wrappedStream.hasDataInReadBuffer` if it does not have any unprocessed
* data. In order to get access to the wrapped stream, @ref wrappedStream can
* the class is abstract), the private methods @ref TCPAccept,
* @ref lowlevelTCPReadIntoBuffer:length: and
* be used.
* @ref lowlevelTCPWriteBuffer:length: are provided.
*/
@interface OFTLSSocket: OFTCPSocket
@interface OFTLSStream: OFStream <OFReadyForReadingObserving,
OFReadyForWritingObserving>
{
OFStream <OFReadyForReadingObserving, OFReadyForWritingObserving>
*_wrappedStream;
bool _verifiesCertificates;
OF_RESERVE_IVARS(OFTLSSocket, 4)
OF_RESERVE_IVARS(OFTLSStream, 4)
}
/**
* @brief The wrapped stream.
*/
@property (readonly, nonatomic) OFStream <OFReadyForReadingObserving,
OFReadyForWritingObserving> *wrappedStream;
/**
* @brief The delegate for asynchronous operations on the socket.
* @brief The delegate for asynchronous operations on the stream.
*
* @note The delegate is retained for as long as asynchronous operations are
* still ongoing.
*/
@property OF_NULLABLE_PROPERTY (assign, nonatomic)
id <OFTLSSocketDelegate> delegate;
id <OFTLSStreamDelegate> delegate;
/**
* @brief Whether certificates are verified.
* @brief Whether certificates are verified. Default is true.
*
* The default is enabled.
*/
@property (nonatomic) bool verifiesCertificates;
- (instancetype)init OF_UNAVAILABLE;
/**
* @brief Initializes the TLS socket with the specified TCP socket as its
* underlying socket.
* @brief Creates a new TLS stream with the specified stream as its underlying
* stream.
*
* The passed socket will become invalid, as the internal socket handle gets
* moved from the specified socket to the OFTLSSocket.
*
* @param socket The TCP socket to use as underlying socket
* @param stream The stream to use as underlying stream. Must not be closed
* before the TLS stream is closed.
* @return A new, autoreleased TLS stream
*/
- (instancetype)initWithSocket: (OFTCPSocket *)socket;
+ (instancetype)streamWithStream: (OFStream <OFReadyForReadingObserving,
OFReadyForWritingObserving> *)stream;
/**
* @brief Initializes the TLS stream with the specified stream as its
* @brief Start TLS on the underlying socket with the assumption that it is
* underlying stream.
* connected to the specified host and port.
*
* @param host The host the socket is connected to, which is also used for
* @param stream The stream to use as underlying stream. Must not be closed
* verification
* @param port The port the socket is connected to
* before the TLS stream is closed.
* @return An initialized TLS stream
*/
- (void)startTLSForHost: (OFString *)host port: (uint16_t)port;
- (instancetype)initWithStream: (OFStream <OFReadyForReadingObserving,
OFReadyForWritingObserving> *)stream;
/**
* @brief This method should never be called directly. Only subclasses of
* @ref OFTLSSocket are allowed to call it.
* @brief Asynchronously performs the TLS client handshake for the specified
* host and calls the delegate afterwards.
*
* @param host The host to perform the handshake with
*/
- (instancetype)TCPAccept;
- (void)asyncPerformClientHandshakeWithHost: (OFString *)host;
/**
* @brief This method should never be called directly. Only subclasses of
* @brief Asynchronously performs the TLS client handshake for the specified
* @ref OFTLSSocket are allowed to call it.
* host and calls the delegate afterwards.
*
* @param host The host to perform the handshake with
* @param runLoopMode The run loop mode in which to perform the async handshake
*/
- (size_t)lowlevelTCPReadIntoBuffer: (void *)buffer length: (size_t)length;
- (void)asyncPerformClientHandshakeWithHost: (OFString *)host
runLoopMode: (OFRunLoopMode)runLoopMode;
/**
* @brief This method should never be called directly. Only subclasses of
* @brief Performs the TLS client handshake for the specified host.
* @ref OFTLSSocket are allowed to call it.
*
* @param host The host to perform the handshake with
*/
- (size_t)lowlevelTCPWriteBuffer: (const void *)buffer length: (size_t)length;
- (void)performClientHandshakeWithHost: (OFString *)host;
@end
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief The concrete subclass of OFTLSSocket that should be used.
* @brief The implementation for OFTLSStream to use.
*
* This can be set to a class that is always used for OFTLSStream. This is
* useful to either force a specific implementation or use one that ObjFW does
* not know about.
*/
extern Class _Nullable OFTLSSocketImplementation;
extern Class OFTLSStreamImplementation;
#ifdef __cplusplus
}
#endif
OF_ASSUME_NONNULL_END
|