std::map<std::string, int> _createPortMap(int argCount, char** arguments) { auto portMap = std::map<string, int>(); for(auto i = 1; i < argCount; i++) { portMap.insert(_getPort(arguments[i])); } return portMap; }
void ClientStore::_enumerateStreamBuffers(std::vector<BufferId>& out) const { Message response = {0}; ClientPort& port = _getPort(); port.call(&response, RpcApi::CCV_StreamBufferEnumerate); uint32_t n = response.parameter0; ThrowOn((response.payloadType != MessagePayloadType::MptData) || ((response.data.payloadLength % sizeof(BufferId)) != 0) || (response.data.payloadLength / sizeof(BufferId) != n), RpcMessageMalformedException); if (n > 0) { assert(response.data.payload != nullptr); assert(n <= SIMUTRACE_STORE_MAX_NUM_STREAMBUFFERS); BufferId* buffer = reinterpret_cast<BufferId*>(response.data.payload); std::vector<BufferId> ids(buffer, buffer + n); std::swap(ids, out); } else { out.clear(); } }
ClientStore::~ClientStore() { try { // We first flush all streams to get any pending data to the server. // Afterwards, we can close the store. The server will process the // data we send here (and any other pending data), before closing // the server instance of the store. std::vector<Stream*> streams; this->Store::_enumerateStreams(streams, StreamEnumFilter::SefAll); for (auto i = 0; i < streams.size(); ++i) { assert(streams[i] != nullptr); ClientStream* stream = reinterpret_cast<ClientStream*>(streams[i]); stream->flush(); } ClientPort& port = _getPort(); port.call(nullptr, RpcApi::CCV_StoreClose); } catch (const std::exception& e) { // There is nothing we can do about it. So just log a message and // destroy the client store. LogError("Could not rundown store. Data may have been lost. " "The exception is '%s'", e.what()); } }
std::unique_ptr<StreamBuffer> ClientStore::_createStreamBuffer( size_t segmentSize, uint32_t numSegments) { Message response = {0}; ClientPort& port = _getPort(); std::unique_ptr<StreamBuffer> buffer = nullptr; port.call(&response, RpcApi::CCV_StreamBufferRegister, numSegments, static_cast<uint64_t>(segmentSize)); BufferId id = static_cast<BufferId>(response.parameter0); // If the payload contains handles, the connection between the // server and the client supports shared memory buffers. if (response.payloadType == MessagePayloadType::MptHandles) { assert(response.handles.handles != nullptr); assert(response.handles.handles->size() == response.handles.handleCount); ThrowOn(response.handles.handleCount != 1, RpcMessageMalformedException); Handle& bufferHandle = response.handles.handles->at(0); buffer = std::unique_ptr<StreamBuffer>( new StreamBuffer(id, segmentSize, numSegments, bufferHandle)); } else { buffer = std::unique_ptr<StreamBuffer>( new StreamBuffer(id, segmentSize, numSegments, false)); } return buffer; }
Stream* ClientStore::_replicateStream(StreamId stream) { assert(stream < _dynamicStreamIdBoundary); Message response = {0}; ClientPort& port = _getPort(); port.call(&response, RpcApi::CCV_StreamQuery, stream); ThrowOn((response.payloadType != MessagePayloadType::MptData) || (response.data.payloadLength != sizeof(StreamQueryInformation)), RpcMessageMalformedException); assert(response.data.payload != nullptr); StreamBuffer* buffer = _getStreamBuffer(response.parameter0); ThrowOnNull(buffer, NotFoundException, stringFormat("stream buffer with id %d", response.parameter0)); StreamQueryInformation* desc = reinterpret_cast<StreamQueryInformation*>(response.data.payload); std::unique_ptr<Stream> str(new StaticStream(stream, desc->descriptor, *buffer, getSession())); Stream* pstr = str.get(); // Make a shortcut for the return value _addStream(str); return pstr; }
BuddyPtr TCPAccountHandler::constructBuddy(const PropertyMap& props) { UT_DEBUGMSG(("TCPAccountHandler::constructBuddy()\n")); PropertyMap::const_iterator hi = props.find("server"); UT_return_val_if_fail(hi != props.end(), BuddyPtr()); UT_return_val_if_fail(hi->second.size() > 0, BuddyPtr()); UT_sint32 port = _getPort(props); UT_return_val_if_fail(port != -1, BuddyPtr()); UT_DEBUGMSG(("Constructing TCP Buddy (host: %s, port: %d)\n", hi->second.c_str(), port)); return boost::shared_ptr<TCPBuddy>(new TCPBuddy(this, hi->second, boost::lexical_cast<std::string>(port))); }
std::unique_ptr<Stream> ClientStore::_createStream(StreamId id, StreamDescriptor& desc, BufferId buffer) { assert(id == INVALID_STREAM_ID); Message response = {0}; ClientPort& port = _getPort(); StreamBuffer* buf = _getStreamBuffer(buffer); ThrowOnNull(buf, NotFoundException, stringFormat("stream buffer with id %d", buffer)); if (IsSet(desc.flags, SfDynamic)) { const DynamicStreamDescriptor& dyndesc = reinterpret_cast<DynamicStreamDescriptor&>(desc); // For regular streams the server generates a valid id. For // dynamic streams we have to do this on our own, as dynamic // streams are local to the client. The ids must not collide! // The server generates ids for regular streams in the lower // positive integer range. We therefore generate the ids for // dynamic streams in the high positive integer range. The // limit for the number of streams (see Version.h) prevents a // collision. StreamId sid = --_dynamicStreamIdBoundary; #ifdef _DEBUG std::vector<StreamId> ids; _enumerateStreams(ids, StreamEnumFilter::SefRegular); StreamId max = *std::max_element(ids.cbegin(), ids.cend()); assert(max < sid); #endif return std::unique_ptr<Stream>( new DynamicStream(sid, dyndesc, *buf, getSession())); } else { port.call(&response, RpcApi::CCV_StreamRegister, &desc, sizeof(StreamDescriptor), buffer); StreamId rid = static_cast<StreamId>(response.parameter0); return std::unique_ptr<Stream>( new StaticStream(rid, desc, *buf, getSession())); } }
void ClientStore::_enumerateStreams(std::vector<StreamId>& out, StreamEnumFilter filter) const { std::vector<StreamId> ids; // Request the ids for the static streams. Since we are replicating // static streams on-demand, we cannot just query our local store but // must ask the server. Message response = {0}; ClientPort& port = _getPort(); port.call(&response, RpcApi::CCV_StreamEnumerate, filter); uint32_t n = response.parameter0; ThrowOn((response.payloadType != MessagePayloadType::MptData) || ((response.data.payloadLength % sizeof(StreamId)) != 0) || (response.data.payloadLength / sizeof(StreamId) != n), RpcMessageMalformedException); if (n > 0) { assert(response.data.payload != nullptr); assert(n <= SIMUTRACE_STORE_MAX_NUM_STREAMS); StreamId* buffer = reinterpret_cast<StreamId*>(response.data.payload); ids.assign(buffer, buffer + n); } // Now add the dynamic streams that this client session possesses. std::vector<Stream*> dynStreams; this->Store::_enumerateStreams(dynStreams, StreamEnumFilter::SefDynamic); for (auto stream : dynStreams) { assert(IsSet(stream->getFlags(), StreamFlags::SfDynamic)); assert(!IsSet(stream->getFlags(), StreamFlags::SfHidden)); ids.push_back(stream->getId()); } std::swap(ids, out); }
ClientStore::ClientStore(ClientSession& session, const std::string& name, bool alwaysCreate, bool open) : Store(CLIENT_STORE_ID, name), ClientObject(session), _dynamicStreamIdBoundary(INVALID_STREAM_ID) { Message response = {0}; ClientPort& port = _getPort(); // Send the request to open the store port.call(&response, RpcApi::CCV_StoreCreate, name, (alwaysCreate && !open) ? _true : _false, (open) ? _true : _false); try { _replicateConfiguration(); } catch (...) { port.call(nullptr, RpcApi::CCV_StoreClose); throw; } }
StreamBuffer* ClientStore::_replicateStreamBuffer(BufferId buffer) { Message response = {0}; ClientPort& port = _getPort(); std::unique_ptr<StreamBuffer> buf; port.call(&response, RpcApi::CCV_StreamBufferQuery, buffer, _true); uint32_t numSegments = response.parameter0; size_t segmentSize = response.handles.parameter1; // If the payload contains handles, the connection between the // server and the client supports shared memory buffers. if (response.payloadType == MessagePayloadType::MptHandles) { assert(response.handles.handles != nullptr); assert(response.handles.handles->size() == response.handles.handleCount); ThrowOn(response.handles.handleCount != 1, RpcMessageMalformedException); Handle& bufferHandle = response.handles.handles->at(0); buf = std::unique_ptr<StreamBuffer>( new StreamBuffer(buffer, segmentSize, numSegments, bufferHandle)); } else { buf = std::unique_ptr<StreamBuffer>( new StreamBuffer(buffer, segmentSize, numSegments, false)); } StreamBuffer* pbuf = buf.get(); // Make a shortcut for the return value _addStreamBuffer(buf); return pbuf; }
unsigned int _ossSocket::getPeerPort () { return _getPort ( &_peerAddress ) ; }
unsigned int _ossSocket::getLocalPort () { return _getPort ( &_sockAddress ) ; }
ConnectResult TCPAccountHandler::connect() { UT_DEBUGMSG(("TCPAccountHandler::connect()\n")); AbiCollabSessionManager* pManager = AbiCollabSessionManager::getManager(); UT_return_val_if_fail(pManager, CONNECT_INTERNAL_ERROR); UT_return_val_if_fail(!m_pDelegator, CONNECT_INTERNAL_ERROR); UT_return_val_if_fail(!m_bConnected, CONNECT_ALREADY_CONNECTED); UT_return_val_if_fail(!m_thread, CONNECT_INTERNAL_ERROR); m_io_service.reset(); m_thread = new asio::thread(boost::bind(&asio::io_service::run, &m_io_service)); // set up the connection if (getProperty("server") == "") { UT_sint32 port = _getPort(getProperties()); UT_DEBUGMSG(("Start accepting connections on port %d...\n", port)); try { IOServerHandler* pDelegator = new IOServerHandler(port, boost::bind(&TCPAccountHandler::_handleAccept, this, _1, _2), boost::bind(&TCPAccountHandler::handleEvent, this, _1), m_io_service); m_pDelegator = pDelegator; m_bConnected = true; // todo: ask it to the acceptor pDelegator->run(); } catch (asio::system_error se) { UT_DEBUGMSG(("Failed to start accepting connections: %s\n", se.what())); _teardownAndDestroyHandler(); return CONNECT_FAILED; } catch (...) { UT_DEBUGMSG(("Caught unhandled server exception!\n")); _teardownAndDestroyHandler(); return CONNECT_FAILED; } } else { UT_DEBUGMSG(("Connecting to server %s on port %d...\n", getProperty("server").c_str(), _getPort(getProperties()))); try { asio::ip::tcp::resolver resolver(m_io_service); asio::ip::tcp::resolver::query query(getProperty("server"), getProperty("port")); asio::ip::tcp::resolver::iterator iterator(resolver.resolve(query)); bool connected = false; boost::shared_ptr<Session> session_ptr(new Session(m_io_service, boost::bind(&TCPAccountHandler::handleEvent, this, _1))); while (iterator != tcp::resolver::iterator()) { try { UT_DEBUGMSG(("Attempting to connect...\n")); session_ptr->connect(iterator); UT_DEBUGMSG(("Connected!\n")); connected = true; break; } catch (asio::system_error se) { UT_DEBUGMSG(("Connection attempt failed: %s\n", se.what())); // make sure we close the socket after a failed attempt, as it // may have been opened by the connect() call. try { session_ptr->getSocket().close(); } catch(...) {} } iterator++; } if (!connected) { UT_DEBUGMSG(("Giving up to connecting to server!\n")); _teardownAndDestroyHandler(); return CONNECT_FAILED; } session_ptr->asyncReadHeader(); m_bConnected = true; // todo: ask it to the socket // Add a buddy TCPBuddyPtr pBuddy = boost::shared_ptr<TCPBuddy>(new TCPBuddy(this, session_ptr->getRemoteAddress(), boost::lexical_cast<std::string>(session_ptr->getRemotePort()))); addBuddy(pBuddy); m_clients.insert(std::pair<TCPBuddyPtr, boost::shared_ptr<Session> >(pBuddy, session_ptr)); } catch (asio::system_error se) { UT_DEBUGMSG(("Failed to resolve %s:%d: %s\n", getProperty("server").c_str(), _getPort(getProperties()), se.what())); _teardownAndDestroyHandler(); return CONNECT_FAILED; } } if (!m_bConnected) return CONNECT_FAILED; // we are connected now, time to start sending out messages (such as events) pManager->registerEventListener(this); // signal all listeners we are logged in AccountOnlineEvent event; // TODO: fill the event AbiCollabSessionManager::getManager()->signal(event); return CONNECT_SUCCESS; }
bool SocketConnection::listen() { ConnectionDescriptionPtr description = _getDescription(); LBASSERT( description->type == CONNECTIONTYPE_TCPIP || description->type == CONNECTIONTYPE_SDP ); if( !isClosed( )) return false; _setState( STATE_CONNECTING ); sockaddr_in address; const size_t size = sizeof( sockaddr_in ); if( !_parseAddress( description, address )) { LBWARN << "Can't parse connection parameters" << std::endl; return false; } if( !_createSocket()) return false; const bool bound = (::bind( _readFD, (sockaddr *)&address, size ) == 0); if( !bound ) { LBWARN << "Could not bind socket " << _readFD << ": " << lunchbox::sysError << " to " << inet_ntoa( address.sin_addr ) << ":" << ntohs( address.sin_port ) << " AF " << (int)address.sin_family << std::endl; close(); return false; } else if( address.sin_port == 0 ) LBINFO << "Bound to port " << _getPort() << std::endl; const bool listening = (::listen( _readFD, SOMAXCONN ) == 0); if( !listening ) { LBWARN << "Could not listen on socket: " << lunchbox::sysError << std::endl; close(); return false; } // get socket parameters socklen_t used = size; getsockname( _readFD, (struct sockaddr *)&address, &used ); description->port = ntohs( address.sin_port ); std::string hostname = description->getHostname(); if( hostname.empty( )) { if( address.sin_addr.s_addr == INADDR_ANY ) { char cHostname[256] = {0}; gethostname( cHostname, 256 ); hostname = cHostname; description->setHostname( hostname ); } else description->setHostname( inet_ntoa( address.sin_addr )); } #ifndef _WIN32 //fcntl( _readFD, F_SETFL, O_NONBLOCK ); #endif _initAIOAccept(); _setState( STATE_LISTENING ); LBINFO << "Listening on " << description->getHostname() << "[" << inet_ntoa( address.sin_addr ) << "]:" << description->port << " (" << description->toString() << ")" << std::endl; return true; }
UINT32 _ossSocket::getPeerPort () { return _getPort ( &_peerAddress ) ; }
UINT32 _ossSocket::getLocalPort () { return _getPort ( &_sockAddress ) ; }