1Thrift C++ Software Library 2 3# License 4 5Licensed to the Apache Software Foundation (ASF) under one 6or more contributor license agreements. See the NOTICE file 7distributed with this work for additional information 8regarding copyright ownership. The ASF licenses this file 9to you under the Apache License, Version 2.0 (the 10"License"); you may not use this file except in compliance 11with the License. You may obtain a copy of the License at 12 13 http://www.apache.org/licenses/LICENSE-2.0 14 15Unless required by applicable law or agreed to in writing, 16software distributed under the License is distributed on an 17"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 18KIND, either express or implied. See the License for the 19specific language governing permissions and limitations 20under the License. 21 22# Using Thrift with C++ 23 24The Thrift C++ libraries are built using the GNU tools. Follow the instructions 25in the top-level README.md 26 27In case you do not want to open another README.md file, do this thrift src: 28 29 ./bootstrap.sh 30 ./configure (--with-boost=/usr/local) 31 make 32 sudo make install 33 34Thrift is divided into two libraries. 35 36* libthrift - The core Thrift library contains all the core Thrift code. It requires 37 boost shared pointers, pthreads, and librt. 38 39* libthriftnb - This library contains the Thrift nonblocking server, which uses libevent. 40 To link this library you will also need to link libevent. 41 42## Linking Against Thrift 43 44After you build and install Thrift the libraries are installed to 45/usr/local/lib by default. Make sure this is in your LDPATH. 46 47On Linux, the best way to do this is to ensure that /usr/local/lib is in 48your /etc/ld.so.conf and then run /sbin/ldconfig. 49 50Depending upon whether you are linking dynamically or statically and how 51your build environment it set up, you may need to include additional 52libraries when linking against thrift, such as librt and/or libpthread. If 53you are using libthriftnb you will also need libevent. 54 55## Dependencies 56 57If your C++ environment implements C++11 or later, thrift will automatically use 58std::shared_ptr. Otherwise you will need the boost library to provide a shared_ptr 59implementation for C++ environments pre-C++11. If you are linking against code 60that expects to be using boost::shared_ptr, you can define the preprocessor 61variable FORCE_BOOST_SMART_PTR for your build of thrift to make it use boost instead 62of std for a number of memory related classes. See thrift/stdcxx.h for more. 63 64libevent (for libthriftnb only) 65http://monkey.org/~provos/libevent/ 66 67# Using Thrift with C++ on Windows 68 69Both the autoconf and cmake build systems are able to automatically detect many 70system configurations without the need to specify library locations, however if 71you run into problems or want to redirect thrift to build and link against your 72own provided third party libraries: 73 74BOOST_ROOT : For boost, e.g. D:\boost_1_55_0 75OPENSSL_ROOT_DIR : For OpenSSL, e.g. D:\OpenSSL-Win32 76 77only required by libthriftnb: 78 79LIBEVENT_ROOT_DIR : For Libevent e.g. D:\libevent-2.0.21-stable 80 81See /3rdparty.user for more details. 82 83The same linking guidelines described above for libthriftnb apply to windows as well. 84 85## Linking Against Thrift 86 87You need to link your project that uses thrift against all the thrift 88dependencies; in the case of libthrift, boost and for 89libthriftnb, libevent. 90 91In the project properties you must also set HAVE_CONFIG_H as force include 92the config header: "windows/confg.h" 93 94## Dependencies 95 96The same dependencies for shared_ptr as described above apply to windows as well. 97 98boost thread 99http://www.boost.org/doc/libs/release/doc/html/thread.html 100 101libevent (for libthriftnb only) 102http://monkey.org/~provos/libevent/ 103 104## Notes on boost thread (static vs shared): 105 106By default lib/cpp/windows/force_inc.h defines: 107 108 #define BOOST_ALL_NO_LIB 1 109 #define BOOST_THREAD_NO_LIB 1 110 111This has for effect to have the host application linking against Thrift 112to have to link with boost thread as a static library. 113 114If you wanted instead to link with boost thread as a shared library, 115you'll need to uncomment those two lines, and recompile. 116 117## Windows version compatibility 118 119The Thrift library targets Windows XP for broadest compatbility. A notable 120difference is in the Windows-specific implementation of the socket poll 121function. To target Vista, Win7 or other versions, comment out the line 122 123 #define TARGET_WIN_XP. 124 125## Named Pipes 126 127Named Pipe transport has been added in the TPipe and TPipeServer classes. This 128is currently Windows-only. Named pipe transport for *NIX has not been 129implemented. Domain sockets are a better choice for local IPC under non-Windows 130OS's. *NIX named pipes only support 1:1 client-server connection. 131 132# Thrift/SSL 133 134## Scope 135 136This SSL only supports blocking mode socket I/O. It can only be used with 137TSimpleServer, TThreadedServer, and TThreadPoolServer. 138 139## Implementation 140 141There're two main classes TSSLSocketFactory and TSSLSocket. Instances of 142TSSLSocket are always created from TSSLSocketFactory. 143 144PosixSSLThreadFactory creates PosixSSLThread. The only difference from the 145PthreadThread type is that it cleanups OpenSSL error queue upon exiting 146the thread. Ideally, OpenSSL APIs should only be called from PosixSSLThread. 147 148## How to use SSL APIs 149 150This is for demo. In real code, typically only one TSSLSocketFactory 151instance is needed. 152 153 shared_ptr<TSSLSocketFactory> getSSLSocketFactory() { 154 shared_ptr<TSSLSocketFactory> factory(new TSSLSocketFactory()); 155 // client: load trusted certificates 156 factory->loadTrustedCertificates("my-trusted-ca-certificates.pem"); 157 // client: optionally set your own access manager, otherwise, 158 // the default client access manager will be loaded. 159 160 factory->loadCertificate("my-certificate-signed-by-ca.pem"); 161 factory->loadPrivateKey("my-private-key.pem"); 162 // server: optionally setup access manager 163 // shared_ptr<AccessManager> accessManager(new MyAccessManager); 164 // factory->access(accessManager); 165 ... 166 } 167 168 169client code sample 170 171 shared_ptr<TSSLSocketFactory> factory = getSSLSocketFactory(); 172 shared_ptr<TSocket> socket = factory.createSocket(host, port); 173 shared_ptr<TBufferedTransport> transport(new TBufferedTransport(socket)); 174 ... 175 176 177server code sample 178 179 shared_ptr<TSSLSocketFactory> factory = getSSLSocketFactory(); 180 shared_ptr<TSSLServerSocket> socket(new TSSLServerSocket(port, factory)); 181 shared_ptr<TTransportFactory> transportFactory(new TBufferedTransportFactory)); 182 ... 183 184## AccessManager 185 186AccessManager defines a callback interface. It has three callback methods: 187 188(a) Decision verify(const sockaddr_storage& sa); 189 190(b) Decision verify(const string& host, const char* name, int size); 191 192(c) Decision verify(const sockaddr_storage& sa, const char* data, int size); 193 194After SSL handshake completes, additional checks are conducted. Application 195is given the chance to decide whether or not to continue the conversation 196with the remote. Application is queried through the above three "verify" 197method. They are called at different points of the verification process. 198 199Decisions can be one of ALLOW, DENY, and SKIP. ALLOW and DENY means the 200conversation should be continued or disconnected, respectively. ALLOW and 201DENY decision stops the verification process. SKIP means there's no decision 202based on the given input, continue the verification process. 203 204First, (a) is called with the remote IP. It is called once at the beginning. 205"sa" is the IP address of the remote peer. 206 207Then, the certificate of remote peer is loaded. SubjectAltName extensions 208are extracted and sent to application for verification. When a DNS 209subjectAltName field is extracted, (b) is called. When an IP subjectAltName 210field is extracted, (c) is called. 211 212The "host" in (b) is the value from TSocket::getHost() if this is a client 213side socket, or TSocket::getPeerHost() if this is a server side socket. The 214reason is client side socket initiates the connection. TSocket::getHost() 215is the remote host name. On server side, the remote host name is unknown 216unless it's retrieved through TSocket::getPeerHost(). Either way, "host" 217should be the remote host name. Keep in mind, if TSocket::getPeerHost() 218failed, it would return the remote host name in numeric format. 219 220If all subjectAltName extensions were "skipped", the common name field would 221be checked. It is sent to application through (c), where "sa" is the remote 222IP address. "data" is the IP address extracted from subjectAltName IP 223extension, and "size" is the length of the extension data. 224 225If any of the above "verify" methods returned a decision ALLOW or DENY, the 226verification process would be stopped. 227 228If any of the above "verify" methods returned SKIP, that decision would be 229ignored and the verification process would move on till the last item is 230examined. At that point, if there's still no decision, the connection is 231terminated. 232 233Thread safety, an access manager should not store state information if it's 234to be used by many SSL sockets. 235 236## SIGPIPE signal 237 238Applications running OpenSSL over network connections may crash if SIGPIPE 239is not ignored. This happens when they receive a connection reset by remote 240peer exception, which somehow triggers a SIGPIPE signal. If not handled, 241this signal would kill the application. 242 243## How to run test client/server in SSL mode 244 245The server and client expects the followings from the directory /test/ 246 247- keys/server.crt 248- keys/server.key 249- keys/CA.pem 250 251The file names are hard coded in the source code. You need to create these 252certificates before you can run the test code in SSL mode. Make sure at least 253one of the followings is included in "keys/server.crt", 254 255- subjectAltName, DNS localhost 256- subjectAltName, IP 127.0.0.1 257- common name, localhost 258 259Run within /test/ folder, 260 261 ./cpp/TestServer --ssl & 262 ./cpp/TestClient --ssl 263 264If "-h <host>" is used to run client, the above "localhost" in the above 265keys/server.crt has to be replaced with that host name. 266 267## TSSLSocketFactory::randomize() 268 269The default implementation of OpenSSLSocketFactory::randomize() simply calls 270OpenSSL's RAND_poll() when OpenSSL library is first initialized. 271 272The PRNG seed is key to the application security. This method should be 273overridden if it's not strong enough for you. 274 275# Breaking Changes 276 277## 0.11.0 278 279Older versions of thrift depended on the <boost/smart_ptr.hpp> classes which 280were used in thrift headers to define interfaces. Thrift now detects C++11 281at build time and will prefer to use <memory> classes from C++11 instead. 282You can force the library to build with boost memory classes by defining the 283preprocessor macro `FORCE_BOOST_SMART_PTR`. (THRIFT-2221) 284 285In the pthread mutex implementation, the contention profiling code was enabled 286by default in all builds. This changed to be disabled by default. (THRIFT-4151) 287 288In older releases, if a TSSLSocketFactory's lifetime was not at least as long 289as the TSSLSockets it created, we silently reverted openssl to unsafe multithread behavior 290and so the results were undefined. Changes were made in 0.11.0 that cause either an 291assertion or a core instead of undefined behavior. The lifetime of a TSSLSocketFactory 292*must* be longer than any TSSLSocket that it creates, otherwise openssl will be cleaned 293up too early. If the static boolean is set to disable openssl initialization and 294cleanup and leave it up to the consuming application, this requirement is not needed. 295(THRIFT-4164) 296 297