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); } } }
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); } }
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); } }