1 /*
2  *  Copyright (c) 2021, The OpenThread Authors.
3  *  All rights reserved.
4  *
5  *  Redistribution and use in source and binary forms, with or without
6  *  modification, are permitted provided that the following conditions are met:
7  *  1. Redistributions of source code must retain the above copyright
8  *     notice, this list of conditions and the following disclaimer.
9  *  2. Redistributions in binary form must reproduce the above copyright
10  *     notice, this list of conditions and the following disclaimer in the
11  *     documentation and/or other materials provided with the distribution.
12  *  3. Neither the name of the copyright holder nor the
13  *     names of its contributors may be used to endorse or promote products
14  *     derived from this software without specific prior written permission.
15  *
16  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17  *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20  *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21  *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22  *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23  *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24  *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25  *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26  *  POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 /**
30  * @file
31  * @brief
32  *   This file includes the platform abstraction for DNS Stateful Operations (DSO) transport.
33  */
34 
35 #ifndef OPENTHREAD_PLATFORM_DSO_TRANSPORT_H_
36 #define OPENTHREAD_PLATFORM_DSO_TRANSPORT_H_
37 
38 #include <stdint.h>
39 
40 #include <openthread/error.h>
41 #include <openthread/instance.h>
42 #include <openthread/ip6.h>
43 #include <openthread/message.h>
44 
45 #ifdef __cplusplus
46 extern "C" {
47 #endif
48 
49 /**
50  * Represents a DSO connection.
51  *
52  * It is an opaque struct (the platform implementation only deals with pointers to this struct).
53  *
54  */
55 typedef struct otPlatDsoConnection otPlatDsoConnection;
56 
57 /**
58  * Can be used by DSO platform implementation to get the the OpenThread instance associated with a
59  * connection instance.
60  *
61  * @param[in] aConnection   A pointer to the DSO connection.
62  *
63  * @returns A pointer to the `otInstance`.
64  *
65  */
66 extern otInstance *otPlatDsoGetInstance(otPlatDsoConnection *aConnection);
67 
68 /**
69  * Starts or stops listening for incoming connection requests on transport layer.
70  *
71  * For DNS-over-TLS, the transport layer MUST listen on port 853 and follow RFC 7858.
72  *
73  * While listening is enabled, if a connection request is received, the `otPlatDsoAccept()` callback MUST be called.
74  *
75  * @param[in] aInstance    The OpenThread instance.
76  * @param[in] aEnable      TRUE to start listening, FALSE to stop listening.
77  *
78  */
79 void otPlatDsoEnableListening(otInstance *aInstance, bool aEnable);
80 
81 /**
82  * Is a callback from the DSO platform to indicate an incoming connection request when listening is
83  * enabled.
84  *
85  * Determines whether or not to accept the connection request. It returns a non-null `otPlatDsoConnection`
86  * pointer if the request is to be accepted, or `NULL` if the request is to be rejected.
87  *
88  * If a non-null connection pointer is returned, the platform layer MUST continue establishing the connection with the
89  * peer. The platform reports the outcome by invoking `otPlatDsoHandleConnected()` callback on success or
90  * `otPlatDsoHandleDisconnected()` callback on failure.
91  *
92  * @param[in] aInstance      The OpenThread instance.
93  * @param[in] aPeerSockAddr  The socket address (IPv6 address and port number) of the peer requesting connection.
94  *
95  * @returns A pointer to the `otPlatDsoConnection` to use if to accept, or `NULL` if to reject.
96  *
97  */
98 extern otPlatDsoConnection *otPlatDsoAccept(otInstance *aInstance, const otSockAddr *aPeerSockAddr);
99 
100 /**
101  * Requests the platform layer to initiate establishing a connection with a peer.
102  *
103  * The platform reports the outcome by invoking `otPlatDsoHandleConnected()` callback on success or
104  * `otPlatDsoHandleDisconnected()` callback (on failure).
105  *
106  * @param[in] aConnection     The connection.
107  * @param[in] aPeerSockAddr   The socket address (IPv6 address and port number) of the peer to connect to.
108  *
109  */
110 void otPlatDsoConnect(otPlatDsoConnection *aConnection, const otSockAddr *aPeerSockAddr);
111 
112 /**
113  * Is a callback from the platform layer to indicate that a connection is successfully established.
114  *
115  * It MUST be called either after accepting an incoming connection (`otPlatDsoAccept`) or after a `otPlatDsoConnect()`
116  * call.
117  *
118  * Only after this callback, the connection can be used to send and receive messages.
119  *
120  * @param[in] aConnection     The connection.
121  *
122  */
123 extern void otPlatDsoHandleConnected(otPlatDsoConnection *aConnection);
124 
125 /**
126  * Sends a DSO message to the peer on a connection.
127  *
128  * Is used only after the connection is successfully established (after `otPlatDsoHandleConnected()`
129  * callback).
130  *
131  * Passes the ownership of the @p aMessage to the DSO platform layer, and the platform implementation is
132  * expected to free the message once it is no longer needed.
133  *
134  * The @p aMessage contains the DNS message (starting with DNS header). Note that it does not contain the the length
135  * field that is needed when sending over TLS/TCP transport. The platform layer MUST therefore include the length
136  * field when passing the message to TLS/TCP layer.
137  *
138  * @param[in] aConnection   The connection to send on.
139  * @param[in] aMessage      The message to send.
140  *
141  */
142 void otPlatDsoSend(otPlatDsoConnection *aConnection, otMessage *aMessage);
143 
144 /**
145  * Is a callback from the platform layer to indicate that a DNS message was received over a connection.
146  *
147  * The platform MUST call this function only after the connection is successfully established (after callback
148  * `otPlatDsoHandleConnected()` is invoked).
149  *
150  * Passes the ownership of the @p aMessage from the DSO platform layer to OpenThread. OpenThread will
151  * free the message when no longer needed.
152  *
153  * The @p aMessage MUST contain the DNS message (starting with DNS header) and not include the length field that may
154  * be included in TCP/TLS exchange.
155  *
156  * @param[in] aConnection   The connection on which the message was received.
157  * @param[in] aMessage      The received message.
158  *
159  */
160 extern void otPlatDsoHandleReceive(otPlatDsoConnection *aConnection, otMessage *aMessage);
161 
162 /**
163  * Defines disconnect modes.
164  *
165  */
166 typedef enum
167 {
168     OT_PLAT_DSO_DISCONNECT_MODE_GRACEFULLY_CLOSE, ///< Gracefully close the connection.
169     OT_PLAT_DSO_DISCONNECT_MODE_FORCIBLY_ABORT,   ///< Forcibly abort the connection.
170 } otPlatDsoDisconnectMode;
171 
172 /**
173  * Requests a connection to be disconnected.
174  *
175  * After calling this function, the DSO platform implementation MUST NOT maintain `aConnection` pointer (platform
176  * MUST NOT call any callbacks using this `Connection` pointer anymore). In particular, calling `otPlatDsoDisconnect()`
177  * MUST NOT trigger the callback `otPlatDsoHandleDisconnected()`.
178  *
179  * @param[in] aConnection   The connection to disconnect
180  * @param[in] aMode         The disconnect mode (close gracefully or forcibly abort).
181  *
182  */
183 void otPlatDsoDisconnect(otPlatDsoConnection *aConnection, otPlatDsoDisconnectMode aMode);
184 
185 /**
186  * Is a callback from the platform layer to indicate that peer closed/aborted the connection or the
187  * connection establishment failed (e.g., peer rejected a connection request).
188  *
189  * After calling this function, the DSO platform implementation MUST NOT maintain `aConnection` pointer (platform
190  * MUST NOT call any callbacks using this `Connection` pointer anymore).
191  *
192  * @param[in] aConnection   The connection which disconnected.
193  * @param[in] aMode         The disconnect mode (closed gracefully or forcibly aborted).
194  *
195  */
196 extern void otPlatDsoHandleDisconnected(otPlatDsoConnection *aConnection, otPlatDsoDisconnectMode aMode);
197 
198 #ifdef __cplusplus
199 } // extern "C"
200 #endif
201 
202 #endif // OPENTHREAD_PLATFORM_DSO_TRANSPORT_H_
203