void I_IpServerTransport::setAllowedClientIps(
        const std::vector<std::string> &allowedClientIps)
    {
        WriteLock writeLock(mReadWriteMutex);
        mAllowedIps.assign(allowedClientIps.begin(), allowedClientIps.end());

        // translate the ips into 32 bit values, network order
        mAllowedAddrs.clear();
        for (unsigned int i=0; i<mAllowedIps.size(); i++)
        {
            const std::string &ip = mAllowedIps[i];
            hostent *hostDesc = ::gethostbyname( ip.c_str() );
            if (hostDesc == NULL)
            {
                int err = Platform::OS::BsdSockets::GetLastError();
                std::string strErr = Platform::OS::GetErrorString(err);
                RCF_TRACE("gethostbyname() failed")(ip)(err)(strErr);
                mAllowedAddrs.push_back(INADDR_NONE);
            }
            else
            {
                in_addr addr = *((in_addr*) hostDesc->h_addr_list[0]);
                mAllowedAddrs.push_back(addr.s_addr);
            }
        }
    }
Exemple #2
0
 void operator()()
 {
     try
     {
         RcfClient<I_Echo> echo(ip, port);
         std::string s0 = "something special";
         for (int i=0;i<10; i++)
         {
             try
             {
                 std::string s = echo.echo(s0); 
                 BOOST_CHECK(s0 == s);
             }
             catch(const RCF::Exception &e)
             {
                 RCF_TRACE("")(e); // since we're overloading the server there will be some exceptions
             }
         }
     }
     catch(...)
     {
         BOOST_CHECK(1==0);
     }
 }
Exemple #3
0
int test_main(int argc, char **argv)
{
    //util::CommandLineOption<int> port("port", util::Ports::getNext(), "port number");
    util::CommandLine::getSingleton().parse(argc, argv);

    int port = 0;

    std::vector<std::string> ips;
    ips.push_back("www.usatoday.com");
    ips.push_back("www.sunet.se");
    ips.push_back("www.google.com");

    X x;
    {
        port = util::Ports::getNext();
        RCF::RcfServer server(port);
        server.setAllowedClientIps(ips);
        server.bind<I_X>(x);
        server.start();

        try 
        {
            RcfClient<I_X> client("localhost", port);
            client.f();
            BOOST_CHECK(1==0);
        }
        catch(const RCF::Exception &e)
        {
            RCF_TRACE("")(e);
            BOOST_CHECK(1==1);
        }

        ips = server.getAllowedClientIps();
        ips.push_back("localhost");
        server.setAllowedClientIps(ips);

        RcfClient<I_X> client("localhost", port);
        client.f();
    }

    // test interface restriction

    // loopback interface
    std::vector<std::string> interfaces;
    interfaces.push_back("127.0.0.1");
    interfaces.push_back("localhost");
    
    for (unsigned int i=0; i<interfaces.size(); i++)
    {
        port = util::Ports::getNext();
        RCF::RcfServer server(port);
        server.bind<I_X>(x);
        server.setNetworkInterface(interfaces[i]);
        server.start();

        RcfClient<I_X>("localhost", port).f();
        BOOST_CHECK(1==1);
    }
    
    // erroneous interface
    {
        port = util::Ports::getNext();
        RCF::RcfServer server(port);
        server.bind<I_X>(x);
        server.setNetworkInterface("1.2.3.4");
        try 
        {
            server.start();
            BOOST_CHECK(1==0);
        }
        catch (const RCF::Exception &e)
        {
            BOOST_CHECK(1==1);
            RCF_TRACE("")(e);
        }
    }

    return boost::exit_success;
}
    void UdpServerTransport::open()
    {
        RCF_TRACE("")(mPort)(getNetworkInterface());

        // create and bind a socket for receiving UDP messages
        if (mFd == -1 && mPort >= 0)
        {
            int ret = 0;
            int err = 0;

            // create the socket
            mFd = static_cast<int>(socket(AF_INET, SOCK_DGRAM, 0));
            if (mFd == -1)
            {
                err = Platform::OS::BsdSockets::GetLastError();
                RCF_THROW(Exception(
                    RcfError_Socket, err, RcfSubsystem_Os, "socket() failed"))
                    (mFd);
            }

            // setup the address
            std::string networkInterface = getNetworkInterface();
            sockaddr_in serverAddr;
            memset(&serverAddr, 0, sizeof(serverAddr));
            serverAddr.sin_family = AF_INET;
            serverAddr.sin_port = htons( static_cast<u_short>(mPort) );
            if (networkInterface.size() > 0)
            {
                if (isdigit(networkInterface.at(0)))
                {
                    serverAddr.sin_addr.s_addr = inet_addr(
                        networkInterface.c_str());
                }
                else
                {
                    hostent *h = gethostbyname(networkInterface.c_str());
                    if (h)
                    {
                        serverAddr.sin_addr = * (in_addr *) h->h_addr_list[0];
                    }
                }
            }
            else
            {
                serverAddr.sin_addr.s_addr = INADDR_ANY;
            }

            // enable reception of broadcast messages
            int enable = 1;
            ret = setsockopt(mFd, SOL_SOCKET, SO_BROADCAST, (char *) &enable, sizeof(enable));
            err = Platform::OS::BsdSockets::GetLastError();
            if (ret)
            {
                RCF_TRACE("Failed to set SO_BROADCAST on listening udp socket")(ret)(err);
            }

            // Share the address binding, if appropriate.
            if (mEnableSharedAddressBinding)
            {
                enable = 1;

                // Set SO_REUSEADDR socket option.
                ret = setsockopt(mFd, SOL_SOCKET, SO_REUSEADDR, (char *) &enable, sizeof(enable));
                err = Platform::OS::BsdSockets::GetLastError();
                if (ret)
                {
                    RCF_TRACE("Failed to set SO_REUSEADDR on listening udp multicast socket")(ret)(err);
                }

                // On OS X and BSD variants, need to set SO_REUSEPORT as well.

#if (defined(__MACH__) && defined(__APPLE__)) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) 

                ret = setsockopt(mFd, SOL_SOCKET, SO_REUSEPORT, (char *) &enable, sizeof(enable));
                err = Platform::OS::BsdSockets::GetLastError();
                if (ret)
                {
                    RCF_TRACE("Failed to set SO_REUSEPORT on listening udp multicast socket")(ret)(err);
                }
#endif

            }
            

            // bind the socket
            ret = ::bind(mFd, (struct sockaddr*) &serverAddr, sizeof(serverAddr));
            if (ret < 0)
            {
                err = Platform::OS::BsdSockets::GetLastError();
                RCF_THROW(Exception(
                    RcfError_Socket, err, RcfSubsystem_Os, "bind() failed"))
                    (mFd)(mPort)(networkInterface)(ret);
            }
            RCF_ASSERT( mFd != -1 )(mFd);

            if (mMulticastIp.size() > 0)
            {
                // set socket option for receiving multicast messages
            
                ip_mreq imr;
                imr.imr_multiaddr.s_addr = inet_addr(mMulticastIp.c_str());
                imr.imr_interface.s_addr = INADDR_ANY;
                int ret = setsockopt(mFd,IPPROTO_IP, IP_ADD_MEMBERSHIP, (const char*) &imr, sizeof(imr));
                int err = Platform::OS::BsdSockets::GetLastError();

                RCF_VERIFY(
                    ret ==  0,
                    Exception(
                        RcfError_Socket,
                        err,
                        RcfSubsystem_Os,
                        "setsockopt() with IPPROTO_IP/IP_ADD_MEMBERSHIP failed"))
                        (mMulticastIp)(networkInterface);

                // TODO: enable source-filtered multicast messages
                //ip_mreq_source imr;
                //imr.imr_multiaddr.s_addr = inet_addr("232.5.6.7");
                //imr.imr_sourceaddr.s_addr = INADDR_ANY;//inet_addr("10.1.1.2");
                //imr.imr_interface.s_addr = INADDR_ANY;
                //int ret = setsockopt(mFd,IPPROTO_IP, IP_ADD_SOURCE_MEMBERSHIP, (const char*) &imr, sizeof(imr));
                //int err = Platform::OS::BsdSockets::GetLastError();
            }

            // set the socket to nonblocking mode
            Platform::OS::BsdSockets::setblocking(mFd, false);

            // retrieve the port number, if it's generated by the system
            if (mPort == 0 && (mPort = getFdPort(mFd)) == 0)
            {
                err = Platform::OS::BsdSockets::GetLastError();
                RCF_THROW(Exception(
                    RcfError_Socket, err, RcfSubsystem_Os, "getsockname() failed"))
                    (mFd)(mPort)(networkInterface)(ret);
            }
        }
    }
    void UdpServerTransport::cycle(
        int timeoutMs,
        const volatile bool &) //stopFlag
    {
        // poll the UDP socket for messages, and read a message if one is available

        fd_set fdSet;
        FD_ZERO(&fdSet);
        FD_SET( static_cast<SOCKET>(mFd), &fdSet);
        timeval timeout;
        timeout.tv_sec = timeoutMs/1000;
        timeout.tv_usec = 1000*(timeoutMs%1000);

        int ret = Platform::OS::BsdSockets::select(
            mFd+1,
            &fdSet,
            NULL,
            NULL,
            timeoutMs < 0 ? NULL : &timeout);

        int err = Platform::OS::BsdSockets::GetLastError();
        if (ret == 1)
        {
            SessionStatePtr sessionStatePtr = getCurrentUdpSessionStatePtr();
            if (sessionStatePtr.get() == NULL)
            {
                sessionStatePtr = SessionStatePtr(new SessionState(*this));
                SessionPtr sessionPtr = getSessionManager().createSession();
                sessionPtr->setProactor(*sessionStatePtr);
                sessionStatePtr->mSessionPtr = sessionPtr;
                setCurrentUdpSessionStatePtr(sessionStatePtr);

                RcfSessionPtr rcfSessionPtr = 
                    boost::static_pointer_cast<RcfSession>(sessionPtr);

                rcfSessionPtr->mIoState = RcfSession::Reading;
            }

            {
                // read a message

                boost::shared_ptr<std::vector<char> > &readVecPtr =
                    sessionStatePtr->mReadVecPtr;

                if (readVecPtr.get() == NULL || !readVecPtr.unique())
                {
                    readVecPtr.reset( new std::vector<char>());
                }
                std::vector<char> &buffer = *readVecPtr;

                sockaddr from;
                int fromlen = sizeof(from);
                memset(&from, 0, sizeof(from));
                buffer.resize(4);

                int len = Platform::OS::BsdSockets::recvfrom(
                    mFd,
                    &buffer[0],
                    4,
                    MSG_PEEK,
                    &from,
                    &fromlen);

                err = Platform::OS::BsdSockets::GetLastError();
                if (isClientAddrAllowed( *(sockaddr_in *) &from ) &&
                    (len == 4 || (len == -1 && err == Platform::OS::BsdSockets::ERR_EMSGSIZE)))
                {
                    sockaddr_in *remoteAddr = reinterpret_cast<sockaddr_in*>(&from);
                    sessionStatePtr->remoteAddress = IpAddress(*remoteAddr);
                    unsigned int dataLength = 0;
                    memcpy(&dataLength, &buffer[0], 4);
                    networkToMachineOrder(&dataLength, 4, 1);
                    if (dataLength <= static_cast<unsigned int>(getMaxMessageLength()))
                    {
                        buffer.resize(4+dataLength);
                        memset(&from, 0, sizeof(from));
                        fromlen = sizeof(from);

                        len = Platform::OS::BsdSockets::recvfrom(
                            mFd,
                            &buffer[0],
                            4+dataLength,
                            0,
                            &from,
                            &fromlen);

                        if (static_cast<unsigned int>(len) == 4+dataLength)
                        {
                            getSessionManager().onReadCompleted(sessionStatePtr->mSessionPtr);
                        }
                    }
                    else
                    {
                        ByteBuffer byteBuffer;
                        encodeServerError(byteBuffer, RcfError_ServerMessageLength);
                        byteBuffer.expandIntoLeftMargin(4);

                        * (boost::uint32_t *) ( byteBuffer.getPtr() ) =
                            static_cast<boost::uint32_t>(byteBuffer.getLength()-4);

                        RCF::machineToNetworkOrder(byteBuffer.getPtr(), 4, 1);

                        char *buffer = byteBuffer.getPtr();
                        std::size_t bufferLen = byteBuffer.getLength();

                        const sockaddr_in &remoteAddr =
                            sessionStatePtr->remoteAddress.getSockAddr();

                        int len = sendto(
                            mFd,
                            buffer,
                            static_cast<int>(bufferLen),
                            0,
                            (const sockaddr *) &remoteAddr,
                            sizeof(remoteAddr));

                        RCF_UNUSED_VARIABLE(len);
                        discardPacket(mFd);
                    }
                }
                else
                {
                    // discard the message (sender ip not allowed, or message format bad)
                    discardPacket(mFd);
                }
            }
        }
        else if (ret == 0)
        {
            RCF_TRACE("server udp poll - no messages")(mFd)(mPort);
        }
        else if (ret == -1)
        {
            RCF_THROW(
                Exception(
                    RcfError_Socket,
                    err,
                    RcfSubsystem_Os,
                    "udp server select() failed "))
                (mFd)(mPort)(err);
        }

    }