1 | /// ----------------------------------------*- mode: C++; -*-- |
---|
2 | /// @file tp_over_tls_tcp.h |
---|
3 | /// Transport over TLS/TCP |
---|
4 | /// ---------------------------------------------------------- |
---|
5 | /// $Id: tp_over_tls_tcp.h 2872 2008-02-18 10:58:03Z bless $ |
---|
6 | /// $HeadURL: https://svn.ipv6.tm.uka.de/nsis/protlib/trunk/include/tp_over_tls_tcp.h $ |
---|
7 | // =========================================================== |
---|
8 | // |
---|
9 | // Copyright (C) 2005-2007, all rights reserved by |
---|
10 | // - Institute of Telematics, Universitaet Karlsruhe (TH) |
---|
11 | // |
---|
12 | // More information and contact: |
---|
13 | // https://projekte.tm.uka.de/trac/NSIS |
---|
14 | // |
---|
15 | // This program is free software; you can redistribute it and/or modify |
---|
16 | // it under the terms of the GNU General Public License as published by |
---|
17 | // the Free Software Foundation; version 2 of the License |
---|
18 | // |
---|
19 | // This program is distributed in the hope that it will be useful, |
---|
20 | // but WITHOUT ANY WARRANTY; without even the implied warranty of |
---|
21 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
---|
22 | // GNU General Public License for more details. |
---|
23 | // |
---|
24 | // You should have received a copy of the GNU General Public License along |
---|
25 | // with this program; if not, write to the Free Software Foundation, Inc., |
---|
26 | // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
---|
27 | // |
---|
28 | // =========================================================== |
---|
29 | /** @ingroup transport |
---|
30 | * @file tp_over_tls_tcp.h |
---|
31 | * TP over TLS/TCP |
---|
32 | */ |
---|
33 | |
---|
34 | #ifndef TP_OVER_TLS_H |
---|
35 | #define TP_OVER_TLS_H |
---|
36 | |
---|
37 | #include <ext/hash_map> |
---|
38 | |
---|
39 | #include "tp.h" |
---|
40 | #include "threads.h" |
---|
41 | #include "threadsafe_db.h" |
---|
42 | #include "connectionmap.h" |
---|
43 | #include "assocdata.h" |
---|
44 | |
---|
45 | #include <openssl/ssl.h> |
---|
46 | #include <openssl/err.h> |
---|
47 | #include <openssl/evp.h> |
---|
48 | |
---|
49 | |
---|
50 | namespace protlib |
---|
51 | { |
---|
52 | |
---|
53 | /** this struct contains parameters that determine |
---|
54 | * the behavior of listener and receiver threads in TPoverTLS_TCP |
---|
55 | * @param port - port number for master listener thread (server port) |
---|
56 | * @param sleep - time (in ms) that listener and receiver wait at a poll() call |
---|
57 | * @param d - destination module, where internal message are sent |
---|
58 | */ |
---|
59 | struct TPoverTLS_TCPParam : public ThreadParam |
---|
60 | { |
---|
61 | /// constructor |
---|
62 | TPoverTLS_TCPParam( |
---|
63 | const char* client_cert_filename, |
---|
64 | const char* client_privkey_filename, |
---|
65 | const char* root_cert_filename, |
---|
66 | unsigned short common_header_length, |
---|
67 | bool (*const getmsglength) (NetMsg& m, uint32& clen_bytes), |
---|
68 | port_t p, |
---|
69 | const char* threadname= "TPoverTLS_TCP", |
---|
70 | uint32 sleep = ThreadParam::default_sleep_time, |
---|
71 | bool debug_pdu = false, |
---|
72 | message::qaddr_t source = message::qaddr_tp_over_tls_tcp, |
---|
73 | message::qaddr_t dest = message::qaddr_signaling, |
---|
74 | bool sendaborts = false, |
---|
75 | uint8 tos = 0x10) : |
---|
76 | ThreadParam(sleep,threadname,1,1), |
---|
77 | port(p), |
---|
78 | debug_pdu(debug_pdu), |
---|
79 | source(source), |
---|
80 | dest(dest), |
---|
81 | common_header_length(common_header_length), |
---|
82 | client_cert_filename(client_cert_filename), |
---|
83 | client_privkey_filename(client_privkey_filename), |
---|
84 | root_cert_filename(root_cert_filename), |
---|
85 | getmsglength(getmsglength), |
---|
86 | terminate(false), |
---|
87 | ip_tos(tos) |
---|
88 | { |
---|
89 | |
---|
90 | //set up SSL |
---|
91 | ssl_ctx_client = SSL_CTX_new(TLSv1_client_method()); |
---|
92 | ssl_ctx_server = SSL_CTX_new(TLSv1_server_method()); |
---|
93 | |
---|
94 | }; |
---|
95 | |
---|
96 | /// to bind master listener thread to |
---|
97 | const port_t port; |
---|
98 | bool debug_pdu; |
---|
99 | |
---|
100 | /// message source |
---|
101 | const message::qaddr_t source; |
---|
102 | const message::qaddr_t dest; |
---|
103 | |
---|
104 | /// what is the length of the common header |
---|
105 | const unsigned short common_header_length; |
---|
106 | |
---|
107 | /// holds SSL context |
---|
108 | SSL_CTX *ssl_ctx_client; |
---|
109 | SSL_CTX *ssl_ctx_server; |
---|
110 | |
---|
111 | const char* client_cert_filename; |
---|
112 | const char* client_privkey_filename; |
---|
113 | const char* root_cert_filename; |
---|
114 | |
---|
115 | /// function pointer to a function that figures out the msg length in number of 4 byte words |
---|
116 | /// it returns false if error occured (e.g., malformed header), result is returned in variable clen_words |
---|
117 | bool (*const getmsglength) (NetMsg& m, uint32& clen_words); |
---|
118 | |
---|
119 | /// should master thread terminate? |
---|
120 | const bool terminate; |
---|
121 | const uint8 ip_tos; |
---|
122 | }; // end TPoverTLS_TCPParam |
---|
123 | |
---|
124 | |
---|
125 | typedef hash_map<uint32, SSL*> sslmap_t; |
---|
126 | |
---|
127 | /// TP over TCP |
---|
128 | /** This class implements the TP interface using TCP. */ |
---|
129 | class TPoverTLS_TCP : public TP, public Thread |
---|
130 | { |
---|
131 | /***** inherited from TP *****/ |
---|
132 | public: |
---|
133 | /// sends a network message, spawns receiver thread if necessary |
---|
134 | virtual void send(NetMsg* msg,const address& addr, bool use_existing_connection); |
---|
135 | virtual void terminate(const address& addr); |
---|
136 | |
---|
137 | /***** inherited from Thread *****/ |
---|
138 | public: |
---|
139 | /// main loop |
---|
140 | virtual void main_loop(uint32 nr); |
---|
141 | |
---|
142 | /***** other members *****/ |
---|
143 | public: |
---|
144 | /// constructor |
---|
145 | TPoverTLS_TCP(const TPoverTLS_TCPParam& p) : |
---|
146 | TP(prot_tls_tcp,"TLS",p.name,p.common_header_length,p.getmsglength), |
---|
147 | Thread(p), tpparam(p), already_aborted(false), msgqueue(NULL), debug_pdu(p.debug_pdu) |
---|
148 | { |
---|
149 | // perform some initializing actions |
---|
150 | // currently not required (SCTP had to init its library) |
---|
151 | init= true; ///< init done; |
---|
152 | |
---|
153 | |
---|
154 | sslmap.resize(128); |
---|
155 | |
---|
156 | } |
---|
157 | /// virtual destructor |
---|
158 | virtual ~TPoverTLS_TCP(); |
---|
159 | |
---|
160 | typedef |
---|
161 | struct receiver_thread_arg |
---|
162 | { |
---|
163 | const AssocData* peer_assoc; |
---|
164 | bool sig_terminate; |
---|
165 | bool terminated; |
---|
166 | public: |
---|
167 | receiver_thread_arg(const AssocData* peer_assoc) : |
---|
168 | peer_assoc(peer_assoc), sig_terminate(false), terminated(true) {}; |
---|
169 | } receiver_thread_arg_t; |
---|
170 | |
---|
171 | class receiver_thread_start_arg_t |
---|
172 | { |
---|
173 | public: |
---|
174 | TPoverTLS_TCP* instance; |
---|
175 | receiver_thread_arg_t* rtargp; |
---|
176 | |
---|
177 | receiver_thread_start_arg_t(TPoverTLS_TCP* instance, receiver_thread_arg_t* rtargp) : |
---|
178 | instance(instance), rtargp(rtargp) {}; |
---|
179 | }; |
---|
180 | |
---|
181 | class sender_thread_start_arg_t |
---|
182 | { |
---|
183 | public: |
---|
184 | TPoverTLS_TCP* instance; |
---|
185 | FastQueue* sender_thread_queue; |
---|
186 | |
---|
187 | sender_thread_start_arg_t(TPoverTLS_TCP* instance, FastQueue* sq) : |
---|
188 | instance(instance), sender_thread_queue(sq) {}; |
---|
189 | }; |
---|
190 | |
---|
191 | private: |
---|
192 | /// returns already existing connection or establishes a new one |
---|
193 | AssocData* get_connection_to(const appladdress& addr); |
---|
194 | |
---|
195 | static const char *SSLerrmessage(void); |
---|
196 | |
---|
197 | /// receiver thread for a specific socket |
---|
198 | void sender_thread(void *argp); |
---|
199 | |
---|
200 | /// receiver thread for a specific socket |
---|
201 | void receiver_thread(void *argp); |
---|
202 | |
---|
203 | /// send a message to the network via TCP+TLS |
---|
204 | void tcptlssend(NetMsg* msg, appladdress* addr); |
---|
205 | |
---|
206 | /// sender thread starter for a specific socket |
---|
207 | static void* sender_thread_starter(void *argp); |
---|
208 | |
---|
209 | /// receiver thread starter for a specific socket |
---|
210 | static void* receiver_thread_starter(void *argp); |
---|
211 | |
---|
212 | /// a static starter method to invoke the actual main listener |
---|
213 | static void* master_listener_thread_starter(void *argp); |
---|
214 | |
---|
215 | /// main listener thread procedure |
---|
216 | void master_listener_thread(); |
---|
217 | |
---|
218 | // create and start new sender thread |
---|
219 | void create_new_sender_thread(FastQueue* senderqueue); |
---|
220 | |
---|
221 | // create and start new receiver thread |
---|
222 | void create_new_receiver_thread(AssocData* peer_assoc); |
---|
223 | |
---|
224 | /// terminates particular thread |
---|
225 | void stop_receiver_thread(AssocData* peer_assoc); |
---|
226 | |
---|
227 | /// cleans up thread management structures |
---|
228 | void cleanup_receiver_thread(AssocData* peer_assoc); |
---|
229 | |
---|
230 | /// terminates a sender thread |
---|
231 | void terminate_sender_thread(const AssocData* assoc); |
---|
232 | |
---|
233 | /// terminates all active receiver or sender threads |
---|
234 | void terminate_all_threads(); |
---|
235 | |
---|
236 | /// ConnectionMap instance for keeping track of all existing connections |
---|
237 | ConnectionMap connmap; |
---|
238 | |
---|
239 | |
---|
240 | /// SSL Context |
---|
241 | SSL_CTX *ssl_ctx; |
---|
242 | |
---|
243 | /// store per receiver thread arguments, e.g. for signaling termination |
---|
244 | typedef hash_map<pthread_t, receiver_thread_arg_t*> recv_thread_argmap_t; |
---|
245 | recv_thread_argmap_t recv_thread_argmap; |
---|
246 | |
---|
247 | /// store sender thread related information |
---|
248 | typedef hash_map<appladdress, FastQueue*> sender_thread_queuemap_t; |
---|
249 | sender_thread_queuemap_t senderthread_queuemap; |
---|
250 | |
---|
251 | /// parameters for main TPoverTLS_TCP thread |
---|
252 | const TPoverTLS_TCPParam tpparam; |
---|
253 | |
---|
254 | /// did we already abort at thread shutdown |
---|
255 | bool already_aborted; |
---|
256 | /// message queue |
---|
257 | FastQueue* msgqueue; |
---|
258 | |
---|
259 | bool debug_pdu; |
---|
260 | |
---|
261 | /// holds socket<->SSL pointer assignment |
---|
262 | sslmap_t sslmap; |
---|
263 | |
---|
264 | }; // end class TPoverTLS_TCP |
---|
265 | |
---|
266 | /** A simple internal message for selfmessages |
---|
267 | * please note that carried items may get deleted after use of this message |
---|
268 | * the message destructor does not delete any item automatically |
---|
269 | */ |
---|
270 | class TPoverTLS_TCPMsg : public message |
---|
271 | { |
---|
272 | public: |
---|
273 | // message type start/stop thread, send data |
---|
274 | enum msg_t { start, |
---|
275 | stop, |
---|
276 | send_data |
---|
277 | }; |
---|
278 | |
---|
279 | private: |
---|
280 | const AssocData* peer_assoc; |
---|
281 | const TPoverTLS_TCPMsg::msg_t type; |
---|
282 | NetMsg* netmsg; |
---|
283 | appladdress* addr; |
---|
284 | |
---|
285 | public: |
---|
286 | TPoverTLS_TCPMsg(const AssocData* peer_assoc, message::qaddr_t source= qaddr_unknown, TPoverTLS_TCPMsg::msg_t type= stop) : |
---|
287 | message(type_transport, source), peer_assoc(peer_assoc), type(type), netmsg(0), addr(0) {} |
---|
288 | |
---|
289 | TPoverTLS_TCPMsg(NetMsg* netmsg, appladdress* addr, message::qaddr_t source= qaddr_unknown) : |
---|
290 | message(type_transport, source), peer_assoc(0), type(send_data), netmsg(netmsg), addr(addr) {} |
---|
291 | |
---|
292 | const AssocData* get_peer_assoc() const { return peer_assoc; } |
---|
293 | TPoverTLS_TCPMsg::msg_t get_msgtype() const { return type; } |
---|
294 | NetMsg* get_netmsg() const { return netmsg; } |
---|
295 | appladdress* get_appladdr() const { return addr; } |
---|
296 | }; |
---|
297 | |
---|
298 | } // end namespace protlib |
---|
299 | |
---|
300 | #endif |
---|