/[resiprocate]/main/reflow/FlowManager.cxx
ViewVC logotype

Contents of /main/reflow/FlowManager.cxx

Parent Directory Parent Directory | Revision Log Revision Log


Revision 11159 - (show annotations) (download)
Fri Apr 25 14:03:32 2014 UTC (5 years, 8 months ago) by sgodin
File MIME type: text/plain
File size: 10094 byte(s)
-modified asio and boost include file ordering to avoid multiply defined symbol errors on linking
 -in preparation for upgrade of asio drop and support for latest boost 
 -include asio/ssh.hpp everywhere asio.hpp is included
 -include boost headers before others, to ensure we are not redefining stdint definitions in some includes
  and not others

1 #ifdef HAVE_CONFIG_H
2 #include "config.h"
3 #endif
4
5 #include <asio.hpp>
6 #ifdef USE_SSL
7 #include <asio/ssl.hpp>
8 #endif
9 #include <boost/function.hpp>
10 #include <map>
11
12 #include <rutil/Log.hxx>
13 #include <rutil/Logger.hxx>
14 #include <rutil/ThreadIf.hxx>
15 #include <rutil/Random.hxx>
16 #include <rutil/SharedPtr.hxx>
17 #include <rutil/Timer.hxx>
18
19 #ifdef WIN32
20 #include <srtp.h>
21 #else
22 #include <srtp/srtp.h>
23 #endif
24
25 #ifdef USE_SSL
26 #include <openssl/x509.h>
27 #include <openssl/x509v3.h>
28 #include "FlowDtlsTimerContext.hxx"
29 #endif //USE_SSL
30
31 #include "FlowManagerSubsystem.hxx"
32 #include "FlowManager.hxx"
33
34 using namespace flowmanager;
35 using namespace resip;
36 #ifdef USE_SSL
37 using namespace dtls;
38 #endif
39 using namespace std;
40
41 #define RESIPROCATE_SUBSYSTEM FlowManagerSubsystem::FLOWMANAGER
42
43 namespace flowmanager
44 {
45 class IOServiceThread : public ThreadIf
46 {
47 public:
48 IOServiceThread(asio::io_service& ioService) : mIOService(ioService) {}
49
50 virtual ~IOServiceThread() {}
51
52 virtual void thread()
53 {
54 mIOService.run();
55 }
56 private:
57 asio::io_service& mIOService;
58 };
59 }
60
61 FlowManager::FlowManager()
62 #ifdef USE_SSL
63 :
64 mSslContext(mIOService, asio::ssl::context::tlsv1),
65 mClientCert(0),
66 mClientKey(0),
67 mDtlsFactory(0)
68 #endif
69 {
70 mIOServiceWork = new asio::io_service::work(mIOService);
71 mIOServiceThread = new IOServiceThread(mIOService);
72 mIOServiceThread->run();
73
74 #ifdef USE_SSL
75 // Setup SSL context
76 asio::error_code ec;
77 mSslContext.set_verify_mode(asio::ssl::context::verify_peer |
78 asio::ssl::context::verify_fail_if_no_peer_cert);
79 #define VERIFY_FILE "ca.pem"
80 mSslContext.load_verify_file(VERIFY_FILE, ec); // TODO make a setting
81 if(ec)
82 {
83 ErrLog(<< "Unable to load verify file: " << VERIFY_FILE << ", error=" << ec.value() << "(" << ec.message() << ")");
84 }
85 #endif
86
87 // Initialize SRTP
88 err_status_t status = srtp_init();
89 if(status && status != err_status_bad_param) // Note: err_status_bad_param happens if srtp_init is called twice - we allow this for test programs
90 {
91 ErrLog(<< "Unable to initialize SRTP engine, error code=" << status);
92 throw FlowManagerException("Unable to initialize SRTP engine", __FILE__, __LINE__);
93 }
94 status = srtp_install_event_handler(FlowManager::srtpEventHandler);
95 }
96
97
98 FlowManager::~FlowManager()
99 {
100 delete mIOServiceWork;
101 mIOServiceThread->join();
102 delete mIOServiceThread;
103
104 #ifdef USE_SSL
105 if(mDtlsFactory) delete mDtlsFactory;
106 if(mClientCert) X509_free(mClientCert);
107 if(mClientKey) EVP_PKEY_free(mClientKey);
108 #endif
109 }
110
111 #ifdef USE_SSL
112 void
113 FlowManager::initializeDtlsFactory(const char* certAor)
114 {
115 if(mDtlsFactory)
116 {
117 ErrLog(<< "initializeDtlsFactory called when DtlsFactory is already initialized.");
118 return;
119 }
120
121 Data aor(certAor);
122 if(createCert(aor, 365 /* expireDays */, 1024 /* keyLen */, mClientCert, mClientKey))
123 {
124 FlowDtlsTimerContext* timerContext = new FlowDtlsTimerContext(mIOService);
125 mDtlsFactory = new DtlsFactory(std::auto_ptr<DtlsTimerContext>(timerContext), mClientCert, mClientKey);
126 assert(mDtlsFactory);
127 }
128 else
129 {
130 ErrLog(<< "Unable to create a client cert, cannot use Dtls-Srtp.");
131 }
132 }
133 #endif
134
135 void
136 FlowManager::srtpEventHandler(srtp_event_data_t *data)
137 {
138 switch(data->event) {
139 case event_ssrc_collision:
140 WarningLog(<< "SRTP SSRC collision");
141 break;
142 case event_key_soft_limit:
143 WarningLog(<< "SRTP key usage soft limit reached");
144 break;
145 case event_key_hard_limit:
146 WarningLog(<< "SRTP key usage hard limit reached");
147 break;
148 case event_packet_index_limit:
149 WarningLog(<< "SRTP packet index limit reached");
150 break;
151 default:
152 WarningLog(<< "SRTP unknown event reported to handler");
153 }
154 }
155
156 MediaStream*
157 FlowManager::createMediaStream(MediaStreamHandler& mediaStreamHandler,
158 const StunTuple& localBinding,
159 bool rtcpEnabled,
160 MediaStream::NatTraversalMode natTraversalMode,
161 const char* natTraversalServerHostname,
162 unsigned short natTraversalServerPort,
163 const char* stunUsername,
164 const char* stunPassword)
165 {
166 MediaStream* newMediaStream = 0;
167 if(rtcpEnabled)
168 {
169 StunTuple localRtcpBinding(localBinding.getTransportType(), localBinding.getAddress(), localBinding.getPort() + 1);
170 newMediaStream = new MediaStream(mIOService,
171 #ifdef USE_SSL
172 mSslContext,
173 #endif
174 mediaStreamHandler,
175 localBinding,
176 localRtcpBinding,
177 #ifdef USE_SSL
178 mDtlsFactory,
179 #endif
180 natTraversalMode,
181 natTraversalServerHostname,
182 natTraversalServerPort,
183 stunUsername,
184 stunPassword);
185 }
186 else
187 {
188 StunTuple rtcpDisabled; // Default constructor sets transport type to None - this signals Rtcp is disabled
189 newMediaStream = new MediaStream(mIOService,
190 #ifdef USE_SSL
191 mSslContext,
192 #endif
193 mediaStreamHandler,
194 localBinding,
195 rtcpDisabled,
196 #ifdef USE_SSL
197 mDtlsFactory,
198 #endif
199 natTraversalMode,
200 natTraversalServerHostname,
201 natTraversalServerPort,
202 stunUsername,
203 stunPassword);
204 }
205 return newMediaStream;
206 }
207
208 #ifdef USE_SSL
209 int
210 FlowManager::createCert(const resip::Data& pAor, int expireDays, int keyLen, X509*& outCert, EVP_PKEY*& outKey )
211 {
212 int ret;
213
214 Data aor = "sip:" + pAor;
215
216 // Make sure that necessary algorithms exist:
217 assert(EVP_sha1());
218
219 RSA* rsa = RSA_generate_key(keyLen, RSA_F4, NULL, NULL);
220 assert(rsa); // couldn't make key pair
221
222 EVP_PKEY* privkey = EVP_PKEY_new();
223 assert(privkey);
224 ret = EVP_PKEY_set1_RSA(privkey, rsa);
225 assert(ret);
226
227 X509* cert = X509_new();
228 assert(cert);
229
230 X509_NAME* subject = X509_NAME_new();
231 X509_EXTENSION* ext = X509_EXTENSION_new();
232
233 // set version to X509v3 (starts from 0)
234 X509_set_version(cert, 2L);
235
236 int serial = Random::getRandom(); // get an int worth of randomness
237 assert(sizeof(int)==4);
238 ASN1_INTEGER_set(X509_get_serialNumber(cert),serial);
239
240 // ret = X509_NAME_add_entry_by_txt( subject, "O", MBSTRING_ASC,
241 // (unsigned char *) domain.data(), domain.size(),
242 // -1, 0);
243 assert(ret);
244 ret = X509_NAME_add_entry_by_txt( subject, "CN", MBSTRING_ASC,
245 (unsigned char *) aor.data(), aor.size(),
246 -1, 0);
247 assert(ret);
248
249 ret = X509_set_issuer_name(cert, subject);
250 assert(ret);
251 ret = X509_set_subject_name(cert, subject);
252 assert(ret);
253
254 const long duration = 60*60*24*expireDays;
255 X509_gmtime_adj(X509_get_notBefore(cert),0);
256 X509_gmtime_adj(X509_get_notAfter(cert), duration);
257
258 ret = X509_set_pubkey(cert, privkey);
259 assert(ret);
260
261 Data subjectAltNameStr = Data("URI:sip:") + aor
262 + Data(",URI:im:")+aor
263 + Data(",URI:pres:")+aor;
264 ext = X509V3_EXT_conf_nid( NULL , NULL , NID_subject_alt_name,
265 (char*) subjectAltNameStr.c_str() );
266 X509_add_ext( cert, ext, -1);
267 X509_EXTENSION_free(ext);
268
269 static char CA_FALSE[] = "CA:FALSE";
270 ext = X509V3_EXT_conf_nid(NULL, NULL, NID_basic_constraints, CA_FALSE);
271 ret = X509_add_ext( cert, ext, -1);
272 assert(ret);
273 X509_EXTENSION_free(ext);
274
275 // TODO add extensions NID_subject_key_identifier and NID_authority_key_identifier
276
277 ret = X509_sign(cert, privkey, EVP_sha1());
278 assert(ret);
279
280 outCert = cert;
281 outKey = privkey;
282 return ret;
283 }
284 #endif
285
286 /* ====================================================================
287
288 Copyright (c) 2007-2008, Plantronics, Inc.
289 All rights reserved.
290
291 Redistribution and use in source and binary forms, with or without
292 modification, are permitted provided that the following conditions are
293 met:
294
295 1. Redistributions of source code must retain the above copyright
296 notice, this list of conditions and the following disclaimer.
297
298 2. Redistributions in binary form must reproduce the above copyright
299 notice, this list of conditions and the following disclaimer in the
300 documentation and/or other materials provided with the distribution.
301
302 3. Neither the name of Plantronics nor the names of its contributors
303 may be used to endorse or promote products derived from this
304 software without specific prior written permission.
305
306 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
307 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
308 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
309 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
310 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
311 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
312 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
313 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
314 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
315 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
316 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
317
318 ==================================================================== */

Properties

Name Value
svn:eol-style native
svn:mime-type text/plain

webmaster AT resiprocate DOT org
ViewVC Help
Powered by ViewVC 1.1.27