bool ClassType::loadString(const std::string& config) { std::ofstream tempFile; std::string fn; if (OSS::boost_temp_file(fn)) { std::ofstream tempFile(fn.c_str()); if (tempFile.is_open()) { tempFile.write(config.data(), config.size()); tempFile.close(); bool ok = load(fn); boost::filesystem::remove(fn); if (!ok) { OSS_LOG_ERROR("ClassType::loadString - Unable to load " << fn.c_str() << " for reading."); } return ok; } else { OSS_LOG_ERROR("ClassType::loadString - Unable to open " << fn.c_str() << " for writing."); } } else { OSS_LOG_ERROR("ClassType::loadString - Unable to generate new temp filename"); } return false; }
int DTLSBio::sslRead(char* buf, int bufLen) { /// 1. Read available data from the external input (probably libnice) /// If packet is not a DTLS packet, return the read value, else goto 2 /// 2. Store (encrypted) read data into the input BIO using BIO_write /// 3. Call SSL_read to decrypt the data /// Returns return value of SSL_read /// if (!_pSSL) { OSS_LOG_ERROR("DTLSBio::sslRead - _pSSL is not set."); return 0; } if (!SSL_is_init_finished(_pSSL)) { OSS_LOG_ERROR("DTLSBio::sslRead - SSL Handshake is not yet completed."); return 0; } int ret = 0; char readBuf[DTLS_BIO_BUFFER_LEN]; ret = readDirect(readBuf, DTLS_BIO_BUFFER_LEN); if (ret > 0) { // // We have read some packets // if (DTLSSession::peek(readBuf) != DTLSSession::DTLS) { // // Not a DTLS packet. return the raw packet // if (ret > bufLen) { // // We have read a packet that is bigger than the buffer provided // we do not have any better option but to truncate // OSS_LOG_WARNING("DTLSBio::sslRead - buffer size is smaller than the packet in the buffer. Packet will be truncated!"); ret = bufLen; } memcpy(buf, readBuf, ret); return ret; } ret = BIO_write(_pInBIO, readBuf, ret); if (ret > 0) { // // Packets are written to the IN BIO. Read it back unencrypted. // ret = SSL_read(_pSSL, buf, bufLen); } } return ret; }
int DTLSBio::writeDirect(const char* buf, int bufLen) { /// Write unencrypted data directly to external output (probably libnice) /// if (!_pSocket && !_writeHandler) { OSS_LOG_ERROR("DTLSBio::writeDirect - _writeHandler is not set."); return 0; } int ret = 0; if (!_pSocket && _writeHandler) { ret = _writeHandler(buf, bufLen); } else if (_pSocket) { ret = _pSocket->write(buf, bufLen); } return ret; }
void SIPTransaction::writeMessage(SIPMessage::Ptr pMsg) { OSS::mutex_lock lock(_mutex); if (!_transport) { OSS_LOG_ERROR("SIPTransaction::writeMessage - Transport is NULL while attempting to send a request."); return; } if (SIPXOR::isEnabled() && _isXOREncrypted) { pMsg->setProperty("xor", "1"); } std::ostringstream logMsg; logMsg << _logId << ">>> " << pMsg->startLine() << " LEN: " << pMsg->data().size() << " SRC: " << _transport->getLocalAddress().toIpPortString() << " DST: " << _transport->getRemoteAddress().toIpPortString() << " ENC: " << _isXOREncrypted << " PROT: " << _transport->getTransportScheme(); OSS::log_information(logMsg.str()); if (OSS::log_get_level() >= OSS::PRIO_DEBUG) OSS::log_debug(pMsg->createLoggerData()); if (_fsm->onSendMessage(pMsg)) { _transport->writeMessage(pMsg); } }
void SIPTransaction::writeMessage(SIPMessage::Ptr pMsg, const OSS::IPAddress& remoteAddress) { OSS::mutex_lock lock(_mutex); if (!_transport) { OSS_LOG_ERROR("SIPTransaction::writeMessage does not have a transport to use"); return; } if (SIPXOR::isEnabled() && _isXOREncrypted) { pMsg->setProperty("xor", "1"); } if (_fsm->onSendMessage(pMsg)) { std::ostringstream logMsg; logMsg << _logId << ">>> " << pMsg->startLine() << " LEN: " << pMsg->data().size() << " SRC: " << _transport->getLocalAddress().toIpPortString() << " DST: " << remoteAddress.toIpPortString() << " ENC: " << _isXOREncrypted << " PROT: " << _transport->getTransportScheme(); OSS::log_information(logMsg.str()); if (OSS::log_get_level() >= OSS::PRIO_DEBUG) OSS::log_debug(pMsg->createLoggerData()); _transport->writeMessage(pMsg, remoteAddress.toString(), OSS::string_from_number<unsigned short>(remoteAddress.getPort())); } }
void SIPTLSListener::run() { if (!_hasStarted) { // Open the acceptor with the option to reuse the address (i.e. SO_REUSEADDR). boost::system::error_code ec; boost::asio::ip::tcp::resolver::query query(getAddress(), getPort()); boost::asio::ip::tcp::endpoint endpoint = *_resolver.resolve(query, ec); if (!ec) { _acceptor.open(endpoint.protocol()); _acceptor.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true)); _acceptor.bind(endpoint); _acceptor.listen(); _acceptor.async_accept(dynamic_cast<SIPStreamedConnection*>(_pNewConnection.get())->socket().lowest_layer(), boost::bind(&SIPTLSListener::handleAccept, this, boost::asio::placeholders::error, (void*)0)); _hasStarted = true; } else { OSS_LOG_ERROR( "SIPTLSListener::run Exception " << boost::diagnostic_information(ec)); } } }
bool ClassType::load(const boost::filesystem::path& file) { if (!boost::filesystem::exists(file)) { std::ostringstream errorMsg; errorMsg << "Persistent::ClassType::load ** File does not exist ** " << file; OSS_LOG_ERROR(errorMsg.str()); return false; } // _csFileMutex.lock(); _currentFile = file; OSS_ASSERT(!_isLoaded); try { static_cast<libconfig::Config*>(_persistentClass->_config)->readFile(OSS::boost_path(file).c_str()); } catch(libconfig::ParseException e) { std::ostringstream errorMsg; errorMsg << "Persistent::ClassType::load Error reading " << file << " at line " << e.getLine() << " with error " << e.getError(); OSS_LOG_ERROR(errorMsg.str()); return false; } catch(OSS::Exception e) { //_csFileMutex.unlock(); std::ostringstream errorMsg; errorMsg << "Persistent::ClassType::load Error reading " << file << " - " << e.message(); OSS_LOG_ERROR(errorMsg.str()); return false; } catch(...) { std::ostringstream errorMsg; errorMsg << "Persistent::ClassType::load Error reading " << file; OSS_LOG_ERROR(errorMsg.str()); return false; } _isLoaded = true; return true; }
bool SBController::initListeners(ListenerConfig& config) { try { bool hasDefault = false; for (ListenerInfoVector::iterator iter = config.listeners.begin(); iter != config.listeners.end(); iter++) { std::string proto = iter->proto; boost::to_lower(proto); if (stack().enableUDP() && proto == "udp") { OSS::IPAddress listener; listener = iter->address; listener.externalAddress() = iter->externalAddress; listener.setPort(iter->port); stack().udpListeners().push_back(listener); if (!hasDefault) { stack().transport().defaultListenerAddress() = listener; hasDefault = true; } } else if (stack().enableTCP() && proto == "tcp") { OSS::IPAddress listener; listener = iter->address; listener.externalAddress() = iter->externalAddress; listener.setPort(iter->port); stack().tcpListeners().push_back(listener); if (!hasDefault) { stack().transport().defaultListenerAddress() = listener; hasDefault = true; } } } stack().transport().setTCPPortRange(config.tcpPortBase, config.tcpPortMax); stack().transportInit(); } catch(std::exception e) { OSS_LOG_ERROR("Unable to intialize transport. Error: " << e.what()); return false; } return true; }
void SIPTLSListener::handleAccept(const boost::system::error_code& e, OSS_HANDLE userData) { if (!e) { OSS_LOG_DEBUG("SIPTLSListener::handleAccept STARTING new connection"); _pNewConnection->setExternalAddress(_externalAddress); _connectionManager.start(_pNewConnection); if (_acceptor.is_open()) { OSS_LOG_DEBUG("SIPTLSListener::handleAccept RESTARTING async accept loop"); _pNewConnection.reset(new SIPStreamedConnection(*_pIoService, &_tlsContext, _connectionManager, this)); _acceptor.async_accept(dynamic_cast<SIPStreamedConnection*>(_pNewConnection.get())->socket().lowest_layer(), boost::bind(&SIPTLSListener::handleAccept, this, boost::asio::placeholders::error, userData)); } else { OSS_LOG_ERROR("SIPTLSListener::handleAccept ABORTING async accept loop"); } } else { OSS_LOG_ERROR("SIPTLSListener::handleAccept INVOKED with exception " << e.message()); if (_acceptor.is_open()) { OSS_LOG_DEBUG("SIPTLSListener::handleAccept RESTARTING async accept loop"); _pNewConnection.reset(new SIPStreamedConnection(*_pIoService, &_tlsContext, _connectionManager, this)); _acceptor.async_accept(dynamic_cast<SIPStreamedConnection*>(_pNewConnection.get())->socket().lowest_layer(), boost::bind(&SIPTLSListener::handleAccept, this, boost::asio::placeholders::error, userData)); } else { OSS_LOG_ERROR("SIPTLSListener::handleAccept ABORTING async accept loop"); } } }
void EndpointListener::dispatchMessage(const SIPMessage::Ptr& pRequest) { if (_dispatch) { OSS_LOG_DEBUG(pRequest->createContextId(true) << "EndpointListener::dispatchMessage( " << pRequest->startLine() << " )"); pRequest->setProperty(OSS::PropertyMap::PROP_EndpointName, _endpointName); pRequest->commitData(); _dispatch(pRequest, _pConnection); } else { OSS_LOG_ERROR(pRequest->createContextId(true) << "EndpointListener::dispatchMessage( NULL )"); } }
void SIPTLSListener::restart(boost::system::error_code& e) { if (!canBeRestarted()) { OSS_LOG_ERROR("SIPTLSListener::restart() - Exception: canBeRestarted returned FALSE!"); return; } try { _hasStarted = false; run(); OSS_LOG_NOTICE("SIPTLSListener::restart() address: " << _address << ":" << _port << " Ok"); } catch(const boost::system::error_code& err) { e = err; } catch(...) { OSS_LOG_ERROR("SIPTLSListener::restart() UNKNOWN EXCEPTION"); } }
void KVUnqlite::log_error() { unqlite* pDbHandle = static_cast<unqlite*>(_pDbHandle); if (!pDbHandle) return; const char *zBuf = 0; int iLen; unqlite_config(pDbHandle,UNQLITE_CONFIG_ERR_LOG,&zBuf,&iLen); if( iLen > 0 ) { OSS_LOG_ERROR("KVUnqlite Exception: " << zBuf); } }
bool SIPB2BTransactionManager::registerPlugin(const std::string& name, const std::string& path) { try { _pluginLoader.loadLibrary(path); SIPB2BUserAgentHandler* _pHandler = _pluginLoader.create(name); if (_pHandler) { addUserAgentHandler(_pHandler); } } catch(std::exception& e) { OSS_LOG_ERROR("SIPB2BTransactionManager::registerPlugin - Unable to load plugin " << path << " Error: " << e.what()); return false; } return true; }
bool KVUnqlite::put(const std::string& key, const std::string& value) { if (key.size() > PERSISTENT_STORE_MAX_KEY_SIZE || value.size() > PERSISTENT_STORE_MAX_VALUE_SIZE) { OSS_LOG_ERROR("KVUnqlite::put: Maximum data/ size exceeded"); return false; } unqlite* pDbHandle = static_cast<unqlite*>(_pDbHandle); if (!pDbHandle) return false; if (unqlite_kv_store(pDbHandle, key.c_str(), key.size(), value.c_str(), value.size()) != UNQLITE_OK) { log_error(); return false; } return true; }
int DTLSBio::readDirect(char* buf, int bufLen) { /// Read unencrypted data directly from the external source (probably libnice) /// if (!_pSocket && !_readHandler) { OSS_LOG_ERROR("DTLSBio::readDirect - _readHandler is not set."); return 0; } int ret = 0; if (!_pSocket && _readHandler) { ret = _readHandler(buf, bufLen); } else if (_pSocket) { ret = _pSocket->read(buf, bufLen); } return ret; }
int DTLSBio::accept() { // // Read from the external source // int ret = 0; char readBuf[DTLS_BIO_BUFFER_LEN]; while (!SSL_is_init_finished(_pSSL)) { ret = readDirect(readBuf, DTLS_BIO_BUFFER_LEN); if (ret > 0) { // // We have read request from the client // Write it to the input BIO // ret = BIO_write(_pInBIO, readBuf, ret); if (ret > 0) { // // Packets are written to the IN BIO. call the handshake to process // the request // SSL_do_handshake(_pSSL); // // Read the response from the out BIO // ret = BIO_read(_pOutBIO, readBuf, DTLS_BIO_BUFFER_LEN); if (ret > 0) { // // We have read the encrypted data, write it to our external output // ret = writeDirect(readBuf, ret); if (ret <= 0) { OSS_LOG_ERROR("DTLSBio::accept - writeDirect returned " << ret); break; } } else { OSS_LOG_ERROR("DTLSBio::connect - BIO_read returned " << ret); break; } } else { OSS_LOG_ERROR("DTLSBio::accept - BIO_write returned " << ret); break; } } else { OSS_LOG_ERROR("DTLSBio::accept - readDirect returned " << ret); if (ret == 0) { // // No data returned by socket but is not an error. Retry // continue; } else { break; } } } if (SSL_is_init_finished(_pSSL)) return 1; else return 0; }
void SIPTransaction::sendResponse( const SIPMessage::Ptr& pResponse, const OSS::IPAddress& sendAddress) { if (!pResponse->isResponse()) throw OSS::SIP::SIPException("Sending a REQUEST using sendResponse() is illegal!"); SIPTransaction::Ptr pParent = getParent(); if (!_transport && isParent()) throw OSS::SIP::SIPException("Transport Not Ready!"); else if (!isParent() && pParent) _transport = pParent->_transport; if (_sendAddress.getPort() == 0) _sendAddress = sendAddress; SIPTransaction::Ptr pBranch = findBranch(pResponse); if (pBranch) { pBranch->sendResponse(pResponse, sendAddress); return; } else { // // No branch is found. This instance will handle the response // if (_transport && _transport->isReliableTransport()) { if (_transport->writeKeepAlive()) { writeMessage(pResponse); } else { // // Keep-alive failed so create a new transport // if (_localAddress.isValid() && _sendAddress.isValid()) { // // According to RFC 3261, if there is any transport failure, we must try to // re-estabish a connectoin to the via sentby parameter instead // std::string transport; if (SIPVia::msgGetTopViaTransport(pResponse.get(), transport)) { _transport = _transportService->createClientTransport(_localAddress, _sendAddress, transport); writeMessage(pResponse); } } else { OSS_LOG_ERROR("SIPTransaction::sendResponse - Unable to re-establish transport to send response."); } } } else if (_transport) { // // This is UDP so a keep-alive check won't do us any good // writeMessage(pResponse, _sendAddress); } else { OSS_LOG_ERROR("SIPTransaction::sendResponse - Transport is NULL."); } } }
int DTLSBio::connect() { /// call the client handshake /// 1. Call SSL_do_handshake to start the handshake procedure /// 2. Read the ClientHello data from the output BIO and send to external output /// 3. Read the ServerHelloDone from external input and write it to the input BIO /// 4. Call SSL_do_handshake again to process ServerHelloDone /// 5. Repeat 2-4 to complete Certificate exchange /// if (SSL_is_init_finished(_pSSL)) { OSS_LOG_ERROR("DTLSBio::connect - SSL Handshake is already completed."); return 0; } // // Start the handshake // SSL_do_handshake(_pSSL); int ret = 0; char readBuf[DTLS_BIO_BUFFER_LEN]; int resendCount = 0; while (!SSL_is_init_finished(_pSSL)) { int pending = BIO_ctrl_pending(_pOutBIO); if (pending > 0) { ret = BIO_read(_pOutBIO, readBuf, DTLS_BIO_BUFFER_LEN); if (ret > 0) { // // We have read the encrypted data, write it to our external output // ret = writeDirect(readBuf, ret); if (ret <= 0) { OSS_LOG_ERROR("DTLSBio::connect - writeDirect returned " << ret); break; } } else { OSS_LOG_ERROR("DTLSBio::connect - BIO_read returned " << ret); break; } } // // Read the response from the server // ret = readDirect(readBuf, DTLS_BIO_BUFFER_LEN); if (ret > 0) { // // We have read the response from the server // Write it to the input BIO // ret = BIO_write(_pInBIO, readBuf, ret); if (ret > 0) { // // Packets are written to the IN BIO. call the handshake again to process // the response // SSL_do_handshake(_pSSL); } else { OSS_LOG_ERROR("DTLSBio::connect - BIO_write returned " << ret); break; } } else { OSS_LOG_ERROR("DTLSBio::connect - readDirect returned " << ret); if (ret < 0) { // // This is an error. Abort immediately // break; } // // We are not able to read any response. We will try to retransmit // struct timeval timeout; if (DTLSv1_get_timeout(_pSSL, &timeout)) { OSS::UInt64 timeout_value = timeout.tv_sec*1000 + timeout.tv_usec/1000; if (timeout_value > 0) { if (resendCount > MAX_RETRY_COUNT) { break; } else { continue; } } else { ++resendCount; DTLSv1_handle_timeout(_pSSL); continue; } } else { break; } } resendCount = 0; } if (SSL_is_init_finished(_pSSL)) return 1; else return 0; }
bool SBController::initHandler(HandlerConfig& config) { if (!config.inboundRequestScript.empty() && !loadInboundScript( config.inboundRequestScript, &SBController::jsRegisterExports, config.globalScriptsDirectory, config.inboundRequestScriptHelper)) { OSS_LOG_ERROR("Unable to load inbound script " << config.inboundRequestScript); return false; } if (!config.requestAuthenticatorScript.empty() && !loadAuthScript( config.requestAuthenticatorScript, &SBController::jsRegisterExports, config.globalScriptsDirectory, config.requestAuthenticatorScriptHelper)) { OSS_LOG_ERROR("Unable to load authenticator script " << config.requestAuthenticatorScript); return false; } if (!config.routeRequestScript.empty() && !loadRouteScript( config.routeRequestScript, &SBController::jsRegisterExports, config.globalScriptsDirectory, config.routeRequestScriptHelper)) { OSS_LOG_ERROR("Unable to load route script " << config.routeRequestScript); return false; } if (!config.failoverRequestScript.empty() && !loadRouteFailoverScript( config.failoverRequestScript, &SBController::jsRegisterExports, config.globalScriptsDirectory, config.failoverRequestScriptHelper)) { OSS_LOG_ERROR("Unable to load failover script " << config.failoverRequestScript); return false; } if (!config.outboundRequestScript.empty() && !loadOutboundScript( config.outboundRequestScript, &SBController::jsRegisterExports, config.globalScriptsDirectory, config.outboundRequestScriptHelper)) { OSS_LOG_ERROR("Unable to load outbound script " << config.outboundRequestScript); return false; } if (!config.outboundResponseScript.empty() && !loadOutboundResponseScript( config.outboundResponseScript, &SBController::jsRegisterExports, config.globalScriptsDirectory, config.outboundResponseScriptHelper)) { OSS_LOG_ERROR("Unable to load response script " << config.outboundResponseScript); return false; } registerDefaultHandler(dynamic_cast<SIPB2BHandler*>(this)); }
void SIPWebSocketConnection::handleRead(const boost::system::error_code& e, std::size_t bytes_transferred, OSS_HANDLE userData) /// Handle completion of a read operation. { if (e || bytes_transferred <=0) { OSS_LOG_DEBUG("SIPWebSocketConnection::handleRead Exception " << e.message()); if (++_readExceptionCount >= 5) { OSS_LOG_ERROR("SIPWebSocketConnection::handleRead has reached maximum exception count. Bailing out."); boost::system::error_code ignored_ec; _connectionManager.stop(shared_from_this()); } } OSS_LOG_DEBUG("SIPWebSocketConnection::handleRead STARTING new connection"); std::string* buffer = reinterpret_cast<std::string*>(userData); // // set the last read address // if (!_lastReadAddress.isValid()) { boost::system::error_code ec; EndPoint ep = _pServerConnection->get_raw_socket().remote_endpoint(ec); if (!ec) { boost::asio::ip::address ip = ep.address(); _lastReadAddress = OSS::IPAddress(ip.to_string(), ep.port()); } else { OSS_LOG_WARNING("SIPWebSocketConnection::handleRead() Exception " << ec.message()); } } // // Reset the read exception count // _readExceptionCount = 0; _bytesRead = bytes_transferred; if (!_pRequest) { _pRequest = SIPMessage::Ptr(new SIPMessage()); } boost::tribool result; const char* begin = buffer->data(); const char* end = buffer->data() + bytes_transferred; boost::tuple<boost::tribool, const char*> ret = _pRequest->consume(begin, end); result = ret.get<0>(); const char* tail = ret.get<1>(); if (result) { // // Message has been read in full // _pDispatch->onReceivedMessage(_pRequest->shared_from_this(), shared_from_this()); if (tail >= end) { // // The end of the SIPMessage is reached so we can simply reset the // request buffer and start the read operation all over again // _pRequest.reset(); // // We are done // return; } else { // // This should not happen as there is one full message per read. // The tail is within the range of the end of the read buffer. // OSS_ASSERT(false); } } else if (!result) { _pRequest.reset(); } else { // // This should not happen as there is one full message per read. // Partial message? // OSS_ASSERT(false); } }
static void initListeners(OSS::SIP::B2BUA::SBController& sbc, ServiceOptions& service) { OSS::SIP::B2BUA::SBController::ListenerConfig transport; OSS::SIP::B2BUA::SBController::ListenerInfo tcp, udp; std::string listenerAddress; std::string externalAddress; int listenerPort = 5060; transport.tcpPortBase = 30000; transport.tcpPortMax = 40000; try { std::ostringstream config; if (!service.hasOption("config-file", false)) { config << SIPX_CONFDIR << "/" << "sipxsbc.ini"; } else { std::string configFile; service.getOption("config-file", configFile); config << configFile; } ServiceOptions configOptions(config.str()); if (configOptions.parseOptions()) { int portBase = transport.tcpPortBase; int portMax = transport.tcpPortMax; configOptions.getOption("external-address", externalAddress); configOptions.getOption("listener-address", listenerAddress); configOptions.getOption("listener-port", listenerPort, listenerPort); configOptions.getOption("tcp-port-base", portBase, portBase); configOptions.getOption("tcp-port-max", portMax, portMax); transport.tcpPortBase = portBase; transport.tcpPortMax = portMax; } } catch(...) { OSS_LOG_ERROR("Unable to configure SIP transports."); _exit(-1); } if (listenerAddress.empty()) { OSS_LOG_ERROR("Unable to configure SIP transports."); _exit(-1); } udp.address = listenerAddress; udp.externalAddress = externalAddress; udp.port = listenerPort; udp.proto = "udp"; tcp.address = listenerAddress; tcp.externalAddress = externalAddress; tcp.port = listenerPort; tcp.proto = "tcp"; transport.listeners.push_back(udp); transport.listeners.push_back(tcp); sbc.initListeners(transport); }