DLLEXPORT double udp_send(double handle, const char *host, double port) {
    uint16_t intPort;
    try {
        intPort = numeric_cast<uint16_t> (port);
    } catch (bad_numeric_cast &e) {
        intPort = 0;
    }

    if (intPort == 0) {
        return false;
    }

    BufferPtr buffer = handles.find<Buffer> (handle);
    if(buffer) {
        if(!defaultUdpSocket) {
            defaultUdpSocket = UdpSocket::bind(0);
        }
        defaultUdpSocket->write(buffer->getData(), buffer->size());
        defaultUdpSocket->send(host, intPort);
        return true;
    }

    boost::shared_ptr<UdpSocket> sock = handles.find<UdpSocket>(handle);
    if(sock) {
        return sock->send(host, intPort);
    }
    return false;
}
Ejemplo n.º 2
0
//----------------------------------------------------------------------
// read
//----------------------------------------------------------------------
void Connection::recvNB( BufferPtr buffer, const uint64_t bytes )
{
    LBASSERT( !_impl->buffer );
    LBASSERT( _impl->bytes == 0 );
    LBASSERT( buffer );
    LBASSERT( bytes > 0 );
    LBASSERTINFO( bytes < LB_BIT48,
                  "Out-of-sync network stream: read size " << bytes << "?" );

    _impl->buffer = buffer;
    _impl->bytes = bytes;
    buffer->reserve( buffer->getSize() + bytes );
    readNB( buffer->getData() + buffer->getSize(), bytes );
}
Ejemplo n.º 3
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;
}
Ejemplo n.º 4
0
bool Connection::recvSync( BufferPtr& outBuffer, const bool block )
{
    LBASSERTINFO( _impl->buffer,
                  "No pending receive on " << getDescription()->toString( ));

    // reset async IO data
    outBuffer = _impl->buffer;
    const uint64_t bytes = _impl->bytes;
    _impl->buffer = 0;
    _impl->bytes = 0;

    if( _impl->state != STATE_CONNECTED || !outBuffer || bytes == 0 )
        return false;
    LBASSERTINFO( bytes < LB_BIT48,
                  "Out-of-sync network stream: read size " << bytes << "?" );
#ifdef STATISTICS
    _impl->inBytes += bytes;
#endif

    // 'Iterators' for receive loop
    uint8_t* ptr = outBuffer->getData() + outBuffer->getSize();
    uint64_t bytesLeft = bytes;
    int64_t got = readSync( ptr, bytesLeft, block );

    // WAR: fluke notification: On Win32, we get occasionally a data
    // notification and then deadlock when reading from the connection. The
    // callee (Node::handleData) will flag the first read, the underlying
    // SocketConnection will not block and we will restore the AIO operation if
    // no data was present.
    if( got == READ_TIMEOUT )
    {
        _impl->buffer = outBuffer;
        _impl->bytes = bytes;
        outBuffer = 0;
        return true;
    }

    // From here on, receive loop until all data read or error
    while( true )
    {
        if( got < 0 ) // error
        {
            const uint64_t read = bytes - bytesLeft;
            outBuffer->resize( outBuffer->getSize() + read );
            if( bytes == bytesLeft )
                LBDEBUG << "Read on dead connection" << std::endl;
            else
                LBERROR << "Error during read after " << read << " bytes on "
                        << _impl->description << std::endl;
            return false;
        }
        else if( got == 0 )
        {
            // ConnectionSet::select may report data on an 'empty' connection.
            // If we have nothing read so far, we have hit this case.
            if( bytes == bytesLeft )
                return false;
            LBVERB << "Zero bytes read" << std::endl;
        }
        if( bytesLeft > static_cast< uint64_t >( got )) // partial read
        {
            ptr += got;
            bytesLeft -= got;

            readNB( ptr, bytesLeft );
            got = readSync( ptr, bytesLeft, true );
            continue;
        }

        // read done
        LBASSERTINFO( static_cast< uint64_t >( got ) == bytesLeft,
                      got << " != " << bytesLeft );

        outBuffer->resize( outBuffer->getSize() + bytes );
#ifndef NDEBUG
        if( bytes <= 1024 && ( lunchbox::Log::topics & LOG_PACKETS ))
        {
            ptr -= (bytes - bytesLeft); // rewind
            LBINFO << "recv:" << lunchbox::format( ptr, bytes ) << std::endl;
        }
#endif
        return true;
    }

    LBUNREACHABLE;
    return true;
}