Ejemplo n.º 1
0
/*! initialize pipeline
 */
void GroupSockPipeline::initialize(void)
{
    UInt32         index,len;
    UInt32         nextPort;
    std::string    nextHost;
    BinaryMessage  message;

    for(index = 0 ; index<_sockets.size() ; ++index)
    {
        len = _sockets[index].recv(message);
        if(len == 0)
            throw ReadError("Channel closed\n");
        nextHost = message.getString();
        nextPort = message.getUInt32();

        message.clear();
        if(index == 0)
        {
            message.putUInt32(true);
            _sockets[_sockets.size()-1].send(message);
            for(;;)
            {
                try
                {
                    _next.connect(SocketAddress(nextHost.c_str(),
                                                nextPort));
                    break;
                }
                catch(...)
                {
                }
            }
        }
        else
        {
            message.clear();
            message.putUInt32(false);
            message.putString(nextHost);
            message.putUInt32(nextPort);
            _sockets[index-1].send(message);
        }
    }
    _initialized = true;
}
void ClusterServer::acceptClient(void)
{
    BinaryMessage  msg;
    DgramSocket    serviceSock;
    SocketAddress  addr;
    std::string    service;
    std::string    connectionType;
    UInt32         readable;
    bool           connected=false;
    std::string    address;
    bool           bound = false;

    SINFO << "Waiting for request of "
          << _serviceName
          << std::endl;

    try
    {
        if(!_requestAddress.empty())
        {
            // create connection

            _connection = ConnectionFactory::the()->createPoint(
                              _connectionType);

            if(_connection)
            {
                // set interface
                _connection->setInterface(_interface);
                // bind connection
                try
                {
                    // bind to requested address
                    _boundAddress = _connection->bind(_requestAddress);
                    bound = true;
                }
                catch(...)
                {
                    SINFO << "Unable to bind, use name as symbolic "
                          << "service name"
                          << std::endl;
                }
            }
        }

        serviceSock.open();
        serviceSock.setReusePort(true);

        // join to multicast group
        if(!_serviceGroup.empty())
        {
            SocketAddress groupAddress =
                SocketAddress(_serviceGroup.c_str(),
                              _servicePort);

            if(groupAddress.isMulticast())
            {
                SINFO << "wait for request on multicast:"
                      << _serviceGroup << std::endl;

                serviceSock.bind(SocketAddress(SocketAddress::ANY,
                                               _servicePort));
                serviceSock.join(SocketAddress(groupAddress));
            }
            else
            {
                SINFO << "wait for request by broadcast:"
                      << _serviceGroup << std::endl;
                serviceSock.bind(SocketAddress(groupAddress));
            }
        }
        else
        {
            SINFO << "wait for request by broadcast" << std::endl;
            serviceSock.bind(SocketAddress(SocketAddress::ANY,
                                           _servicePort));
        }

        while(!connected)
        {
            try
            {
                if(_connection)
                    readable = serviceSock.waitReadable(.01);
                else
                    readable = true;

                if(readable)
                {
                    serviceSock.recvFrom(msg,addr);

                    service        = msg.getString();
                    connectionType = msg.getString();

                    SINFO << "Request for "
                          << service << " "
                          << connectionType
                          << std::endl;

                    if(service == _serviceName)
                    {
                        // remove old connection if typename missmaches
                        if(_connection &&
                                _connection->getType()->getName() != connectionType)
                        {
                            delete _connection;
                            _connection = NULL;
                        }

                        // try to create connection
                        if(!_connection)
                        {
                            // create connection
                            _connection =
                                ConnectionFactory::the()->createPoint(
                                    connectionType);

                            if(_connection)
                            {
                                // set interface
                                _connection->setInterface(_interface);
                                // bind connection
                                _boundAddress = _connection->bind(
                                                    _requestAddress);

                                bound = true;
                            }
                            else
                            {
                                SINFO << "Unknown connection type '"
                                      << connectionType << "'" << std::endl;
                            }
                        }

                        if(_connection)
                        {
                            msg.clear    (             );
                            msg.putString(_serviceName );
                            msg.putString(_boundAddress);
                            serviceSock.sendTo(msg, addr);

                            SINFO << "Response "
                                  << connectionType << ":"
                                  << _boundAddress
                                  << std::endl;
                        }
                    }
                }
            }

            catch(SocketConnReset &e)
            {
                // ignore if there is a connection. This can happen, if
                // a client has send a request. The server has send an
                // answer meanwile the client has send a second request
                // the client gets the answer to the first request and
                // the server tries to send a second answer. The second
                // answer can not be delivered because the client has
                // closed its service port. This is a win-socket problem.

                SWARNING << e.what() << std::endl;

                // if there is no connection, then its a real problem
                if(!_connection)
                    throw;
            }
            catch(OSG_STDEXCEPTION_NAMESPACE::exception &e)
            {
                SWARNING << e.what() << std::endl;
            }
            try
            {
                // try to accept
                if(bound && _connection && _connection->acceptGroup(0.2) >= 0)
                {
                    connected = true;
                    SINFO << "Connection accepted "
                          << _boundAddress
                          << std::endl;
                }
            }

            catch(OSG_STDEXCEPTION_NAMESPACE::exception &e)
            {
                SWARNING << e.what() << std::endl;
            }
        }

        serviceSock.close();
    }

    catch(OSG_STDEXCEPTION_NAMESPACE::exception &)
    {
        throw;
    }
}