示例#1
0
bool Connection::send( const Connections& connections, Packet& packet,
                       const void* data, const uint64_t dataSize,
                       const bool isLocked )
{
    if( connections.empty( ))
        return true;

    if( dataSize <= 8 ) // fits in existing packet
    {
        if( dataSize != 0 )
            memcpy( (char*)(&packet) + packet.size-8, data, dataSize );
        return send( connections, packet, isLocked );
    }

    const uint64_t headerSize  = packet.size - 8;
    const uint64_t size        = headerSize + dataSize;

    if( size > EQ_ASSEMBLE_THRESHOLD )
    {
        // OPT: lock the connection and use two send() to avoid big memcpy
        packet.size = size;
        bool success = true;

        for( Connections::const_iterator i= connections.begin(); 
             i<connections.end(); ++i )
        {        
            ConnectionPtr connection = *i;

            if( !isLocked )
                connection->lockSend();

            if( !connection->send( &packet, headerSize, true ) ||
                !connection->send( data, dataSize, true ))
            {
                success = false;
            }
            if( !isLocked )
                connection->unlockSend();    
        }
        return success;
    }

    char*          buffer = (char*)alloca( size );
    memcpy( buffer, &packet, packet.size-8 );
    memcpy( buffer + packet.size-8, data, dataSize );

    ((Packet*)buffer)->size = size;

    bool success = true;
    for( Connections::const_iterator i = connections.begin(); 
         i < connections.end(); ++i )
    {        
        ConnectionPtr connection = *i;
        if( !connection->send( buffer, size, isLocked ))
            success = false;
    }

    return success;
}
示例#2
0
int LuaChat::broadcastOps(lua_State* L) {
    luaL_checkany(L, 2);
    if (lua_type(L, 2) != LUA_TTABLE)
        return luaL_error(L, "broadcastOps requires a table as the second argument.");

    string message = luaL_checkstring(L, 1);
    message += " ";
    json_t* json = luaToJson(L);
    const char* jsonstr = json_dumps(json, JSON_COMPACT);
    message += jsonstr;
    free((void*) jsonstr);
    json_decref(json);
    lua_pop(L, 2);
    MessagePtr outMessage(MessageBuffer::FromString(message));
    const oplist_t ops = ServerState::getOpList();
    for (oplist_t::const_iterator i = ops.begin(); i != ops.end(); ++i) {
        string name(*i);
        int length = name.length();
        for (int x = 0; x < length; ++x) {
            name[x] = tolower(name[x]);
        }
        ConnectionPtr con = ServerState::getConnection(name);
        if (con != 0) {
            con->send(outMessage);
        }
    }
    return 0;
}
示例#3
0
bool LocalNode::_connect( NodePtr node, ConnectionPtr connection )
{
    EQASSERT( connection.isValid( ));
    EQASSERT( node->getNodeID() != getNodeID( ));

    if( !node.isValid() || _state != STATE_LISTENING ||
        !connection->isConnected() || node->_state != STATE_CLOSED )
    {
        return false;
    }

    _addConnection( connection );

    // send connect packet to peer
    NodeConnectPacket packet;
    packet.requestID = registerRequest( node.get( ));
    packet.nodeID    = _id;
    packet.nodeType  = getType();
    connection->send( packet, serialize( ));

    bool connected = false;
    if( !waitRequest( packet.requestID, connected, 10000 /*ms*/ ))
    {
        EQWARN << "Node connection handshake timeout - peer not a Collage node?"
               << std::endl;
        return false;
    }
    if( !connected )
        return false;

    EQASSERT( node->_id != NodeID::ZERO );
    EQASSERTINFO( node->_id != _id, _id );
    EQINFO << node << " connected to " << *(Node*)this << std::endl;
    return true;
}
示例#4
0
文件: channel.cpp 项目: f-list/fserv
void Channel::sendToChannel(ConnectionPtr src, string& message) {
    MessagePtr outMessage(MessageBuffer::fromString(message));
    for (chconlist_t::iterator i = participants.begin(); i != participants.end(); ++i) {
        ConnectionPtr p = *i;
        if (p != src)
            p->send(outMessage);
    }
}
void BufferConnection::sendBuffer( ConnectionPtr connection )
{
    if( _buffer.isEmpty( ))
        return;

    if( !connection )
    {
        EQWARN << "NULL connection during buffer write" << std::endl;
        return;
    }

    EQCHECK( connection->send( _buffer.getData(), _buffer.getSize() ));
    _buffer.setSize( 0 );
}
示例#6
0
OCommand::~OCommand()
{
    if( _impl->isLocked )
    {
        LBASSERT( _impl->size > 0 );
        const uint64_t size = _impl->size + getBuffer().getSize();
        const size_t minSize = Buffer::getMinSize();
        const Connections& connections = getConnections();
        if( size < minSize ) // Fill send to minimal size
        {
            const size_t delta = minSize - size;
            void* padding = alloca( delta );
            for( ConnectionsCIter i = connections.begin();
                 i != connections.end(); ++i )
            {
                ConnectionPtr connection = *i;
                connection->send( padding, delta, true );
            }
        }
        for( ConnectionsCIter i = connections.begin();
             i != connections.end(); ++i )
        {
            ConnectionPtr connection = *i;
            connection->unlockSend();
        }
        _impl->isLocked = false;
        _impl->size = 0;
        reset();
    }
    else
        disable();

    if( _impl->dispatcher )
    {
        LBASSERT( _impl->localNode );

        // #145 proper local command dispatch?
        LBASSERT( _impl->size == 0 );
        const uint64_t size = getBuffer().getSize();
        BufferPtr buffer = _impl->localNode->allocBuffer( size );
        buffer->swap( getBuffer( ));
        reinterpret_cast< uint64_t* >( buffer->getData( ))[ 0 ] = size;

        ICommand cmd( _impl->localNode, _impl->localNode, buffer, false );
        _impl->dispatcher->dispatchCommand( cmd );
    }

    delete _impl;
}
示例#7
0
bool Connection::send( const Connections& connections, Packet& packet,
                       const void* const* items, const uint64_t* sizes, 
                       const size_t nItems )
{
    if( connections.empty( ))
        return true;

    packet.size -= 8;
    const uint64_t headerSize = packet.size;
    for( size_t i = 0; i < nItems; ++i )
    {
        EQASSERT( sizes[i] > 0 );
        packet.size += sizes[ i ] + sizeof( uint64_t );
    }

    bool success = true;
    for( Connections::const_iterator i = connections.begin(); 
         i < connections.end(); ++i )
    {        
        ConnectionPtr connection = *i;
        connection->lockSend();
            
        if( !connection->send( &packet, headerSize, true ))
            success = false;

        for( size_t j = 0; j < nItems; ++j )
            if( !connection->send( &sizes[j], sizeof(uint64_t), true ) ||
                !connection->send( items[j], sizes[j], true ))
            {
                success = false;
            }

        connection->unlockSend();
    }
    return success;
}
示例#8
0
bool Connection::send( const Connections& connections,
                       const Packet& packet, const bool isLocked )
{
    if( connections.empty( ))
        return true;

    bool success = true;
    for( Connections::const_iterator i= connections.begin(); 
         i<connections.end(); ++i )
    {        
        ConnectionPtr connection = *i;
        if( !connection->send( &packet, packet.size, isLocked ))
            success = false;
    }
    return success;
}
示例#9
0
	void Instance::exit()
	{
		try
		{
			ConnectionPtr conn = getConnection("ua");
			seq_t seq = conn->getNextSeq();

			MsgBody body;
			user_access_server::client_methods::rpc::UnbindRequest unbind_req;
			body.addRequest(user_access_server::client_methods::rpc::CmdID_Unbind, seq, 0, unbind_req);

			conn->send(rpc::OP_REQUEST, body);
		}
		catch (...)
		{
		}
		closeAllConnections();
	}
示例#10
0
		AckChatMsg::AckChatMsg(InstancePtr instance, const UserID& target_uid, msg_id_t msg_id, AckChatMsg::CallbackPtr cb)
		{
			if (!msg_id)
				throw AppException("msg id is null");

			instant_messaging_server::methods::rpc::AckChatMsgRequest ack_chat_req;
			ack_chat_req.mutable_sender_usr_id()->set_uid(target_uid.uid);
			if (!target_uid.domain.empty())
				ack_chat_req.mutable_sender_usr_id()->set_domain(target_uid.domain);
			ack_chat_req.set_msg_id(msg_id);

			ConnectionPtr conn = instance->getConnection("ua");
			seq_t seq = conn->getNextSeq();

			MsgBody body;
			body.addTarget("im");
			body.addRequest(instant_messaging_server::methods::rpc::CmdID_AckChatMsg, seq, 0, ack_chat_req);

			conn->send(rpc::OP_REQUEST, body);
			conn->addRequest(seq, cb);
		}
示例#11
0
void OCommand::sendData( const void* buffer, const uint64_t size,
                         const bool last )
{
    LBASSERT( !_impl->dispatcher );
    LBASSERT( last );
    LBASSERTINFO( size >= 16, size );
    LBASSERT( getBuffer().getData() == buffer );
    LBASSERT( getBuffer().getSize() == size );
    LBASSERT( getBuffer().getMaxSize() >= COMMAND_MINSIZE );

    // Update size field
    uint8_t* bytes = getBuffer().getData();
    reinterpret_cast< uint64_t* >( bytes )[ 0 ] = _impl->size + size;
    const uint64_t sendSize = _impl->isLocked ? size : LB_MAX( size,
                                                               COMMAND_MINSIZE);
    const Connections& connections = getConnections();
    for( ConnectionsCIter i = connections.begin(); i != connections.end(); ++i )
    {
        ConnectionPtr connection = *i;
        connection->send( bytes, sendSize, _impl->isLocked );
    }
}
示例#12
0
		AckGroupSysMsg::AckGroupSysMsg(InstancePtr instance, const GroupID& group_id, const string& channel, msg_id_t sysmsg_id, AckGroupSysMsg::CallbackPtr cb)
		{
			if (!sysmsg_id)
				throw AppException("sysmsg id is null");

			group_messaging_server::methods::rpc::AckGrpSysMsgRequest ack_sys_req;
			if (!channel.empty())
				ack_sys_req.set_channel(channel);
			ack_sys_req.set_sysmsg_id(sysmsg_id);

			ConnectionPtr conn = instance->getConnection("ua");
			seq_t seq = conn->getNextSeq();

			Uri target;
			createUri(&target, "grp", group_id);

			MsgBody body;
			body.addTarget(target);
			body.addRequest(group_messaging_server::methods::rpc::CmdID_AckGrpSysMsg, seq, 0, ack_sys_req);

			conn->send(rpc::OP_REQUEST, body);
			conn->addRequest(seq, cb);
		}
示例#13
0
bool LocalNode::_cmdConnect( Command& command )
{
    EQASSERT( !command.getNode().isValid( ));
    EQASSERT( _inReceiverThread( ));

    const NodeConnectPacket* packet = command.get< NodeConnectPacket >();
    ConnectionPtr connection = _incoming.getConnection();
    const NodeID& nodeID = packet->nodeID;

    EQVERB << "handle connect " << packet << std::endl;
    EQASSERT( nodeID != _id );
    EQASSERT( _connectionNodes.find( connection ) == _connectionNodes.end( ));

    NodePtr remoteNode;

    // No locking needed, only recv thread modifies
    NodeHash::const_iterator i = _nodes->find( nodeID );
    if( i != _nodes->end( ))
    {
        remoteNode = i->second;
        if( remoteNode->isConnected( ))
        {
            // Node exists, probably simultaneous connect from peer
            EQINFO << "Already got node " << nodeID << ", refusing connect"
                   << std::endl;

            // refuse connection
            NodeConnectReplyPacket reply( packet );
            connection->send( reply, serialize( ));

            // NOTE: There is no close() here. The reply packet above has to be
            // received by the peer first, before closing the connection.
            _removeConnection( connection );
            return true;
        }
    }

    // create and add connected node
    if( !remoteNode )
        remoteNode = createNode( packet->nodeType );

    std::string data = packet->nodeData;
    if( !remoteNode->deserialize( data ))
        EQWARN << "Error during node initialization" << std::endl;
    EQASSERTINFO( data.empty(), data );
    EQASSERTINFO( remoteNode->_id == nodeID,
                  remoteNode->_id << "!=" << nodeID );

    remoteNode->_outgoing = connection;
    remoteNode->_state    = STATE_CONNECTED;
    
    _connectionNodes[ connection ] = remoteNode;
    {
        base::ScopedMutex< base::SpinLock > mutex( _nodes );
        _nodes.data[ remoteNode->_id ] = remoteNode;
    }
    EQVERB << "Added node " << nodeID << std::endl;

    // send our information as reply
    NodeConnectReplyPacket reply( packet );
    reply.nodeID    = _id;
    reply.nodeType  = getType();

    connection->send( reply, serialize( ));    
    return true;
}