MMulticastSocketDevice::MMulticastSocketDevice(
    QString sAddress, quint16 nPort, u_char ttl) :
    MSocketDevice(MSocketDevice::Datagram),
    m_address(sAddress), m_port(nPort)
{
#if 0
    ttl = UPnp::GetConfiguration()->GetValue( "UPnP/TTL", 4 );
#endif

    if (ttl == 0)
        ttl = 4;

    setProtocol(IPv4);
    setSocket(createNewSocket(), MSocketDevice::Datagram);

    m_imr.imr_multiaddr.s_addr = inet_addr(sAddress.toLatin1().constData());
    m_imr.imr_interface.s_addr = htonl(INADDR_ANY);

    if (setsockopt(socket(), IPPROTO_IP, IP_ADD_MEMBERSHIP,
                   (const char *)&m_imr, sizeof( m_imr )) < 0)
    {
        LOG(VB_GENERAL, LOG_ERR, LOC + "setsockopt - IP_ADD_MEMBERSHIP " + ENO);
    }

    if (setsockopt(socket(), IPPROTO_IP, IP_MULTICAST_TTL,
                   (const char *)&ttl, sizeof(ttl)) < 0)
    {
        LOG(VB_GENERAL, LOG_ERR, LOC + "setsockopt - IP_MULTICAST_TTL " + ENO);
    }

    setAddressReusable(true);

    if (!bind(m_address, m_port))
        LOG(VB_GENERAL, LOG_ERR, LOC + "bind failed");
}
/*!
    Creates a QSocketDevice object for a stream or datagram socket.

    The \a type argument must be either \c QSocketDevice::Stream for a
    reliable, connection-oriented TCP socket, or \c
    QSocketDevice::Datagram for an unreliable UDP socket.

    The \a protocol indicates whether the socket should be of type IPv4
    or IPv6. Passing \c Unknown is not meaningful in this context and you
    should avoid using (it creates an IPv4 socket, but your code is not easily
    readable).

    The argument \a dummy is necessary for compatibility with some
    compilers.

    \sa blocking() protocol()
*/
QSocketDevice::QSocketDevice( Type type, Protocol protocol, int )
    : fd( -1 ), t( type ), p( 0 ), pp( 0 ), e( NoError ),
      d(new QSocketDevicePrivate(protocol))
{
#if defined(QSOCKETDEVICE_DEBUG)
    qDebug( "QSocketDevice: Created QSocketDevice object %p, type %d",
	    this, type );
#endif
    init();
    setSocket( createNewSocket(), type );
}
Ejemplo n.º 3
0
/*!
    Creates a Q3SocketDevice object for a stream or datagram socket.

    The \a type argument must be either Q3SocketDevice::Stream for a
    reliable, connection-oriented TCP socket, or \c
    Q3SocketDevice::Datagram for an unreliable UDP socket.

    The socket is created as an IPv4 socket.

    \sa blocking() protocol()
*/
Q3SocketDevice::Q3SocketDevice( Type type )
    : fd( -1 ), t( type ), p( 0 ), pp( 0 ), e( NoError ),
      d(new Q3SocketDevicePrivate(IPv4))
{
#if defined(Q3SOCKETDEVICE_DEBUG)
    qDebug( "Q3SocketDevice: Created Q3SocketDevice object %p, type %d",
	    this, type );
#endif
    init();
    setSocket( createNewSocket(), type );
}
Ejemplo n.º 4
0
/*!
    Creates a MSocketDevice object for a stream or datagram socket.

    The \a type argument must be either MSocketDevice::Stream for a
    reliable, connection-oriented TCP socket, or \c
    MSocketDevice::Datagram for an unreliable UDP socket.
    The socket protocol type is defaulting to unknown leaving it to
    connect() to determine if an IPv6 or IPv4 type is required.

    \sa blocking() protocol()
*/
MSocketDevice::MSocketDevice(Type type)
        : fd(-1), t(type), p(0), pp(0), e(NoError),
        d(new MSocketDevicePrivate(Unknown))
{
#if defined(MSOCKETDEVICE_DEBUG)
    qDebug("MSocketDevice: Created MSocketDevice object %p, type %d",
           this, type);
#endif
    init();
    setSocket(createNewSocket(), type);
}
void
SocketBasedConnectionInterface::establishConnectionsWithPeerSlaves(const eclmplConfigFileTable&
                                                                   connTable) {
    for (unsigned int i = 1; i < numberOfConnections; i++) {
        if (i < connectionId) {
            int newSocketFd;
            struct sockaddr_in addr;
            int addrLen = sizeof(addr);
            ASSERT(socket[connectionId]->wAccept(newSocketFd, (struct sockaddr*)&addr, &addrLen) != -1);

            // Need to make sure that the socket referred to by i in socket[i] actually
            // corresponds to the correct simulation manager with id i.
            int id = 1;
            while (id < connectionId) {
                struct hostent* net = gethostbyname(((connTable.getEntry(id))[0]).c_str());
                struct in_addr entryAddr;
                entryAddr.s_addr = *((long*)(net->h_addr_list[0]));

                // Compare the address of the current entry with the address of the
                // connection that was just received. If it matches, then use the current id.
                if (entryAddr.s_addr == addr.sin_addr.s_addr) {
                    break;
                } else {
                    id++;
                }
            }

            ASSERT((socket[id] = new eclmplSocket(newSocketFd, addr, (int)addrLen)) != 0);
            setDefaultSocketOptions(id);
        } else if (i > connectionId) {
            createNewSocket(i, SOCK_STREAM); // SOCK_STREAM --> TCP
            setDefaultSocketOptions(i);

            // Establish connection with slave i.
            std::vector<std::string> args = connTable.getEntry(i);
            ASSERT(args.size() == 3);
            // args[0]==hostname, args[1]==executable, args[2]==portNumber
            std::string slaveHost = args[0];
            int slavePort = std::stoi(args[2]);
#ifdef DEBUG_SOCKET_CONN_START
            std::cerr << connectionId << ": Trying to connect to slave " << slaveHost << slavePort << std::endl;
#endif
            ASSERT(socket[i]->wConnect(slaveHost.c_str(), slavePort) != -1);
#ifdef DEBUG_SOCKET_CONN_START
            std::cerr << connectionId << ": Connected to slave " << slaveHost << slavePort << std::endl;
#endif
        }
    }
} // End of establishConnectionsWithPeerSlaves(...).
Ejemplo n.º 6
0
/*!
    Creates a MSocketDevice object for a stream or datagram socket.

    The \a type argument must be either MSocketDevice::Stream for a
    reliable, connection-oriented TCP socket, or \c
    MSocketDevice::Datagram for an unreliable UDP socket.
    The socket protocol type is defaulting to unknown leaving it to
    connect() to determine if an IPv6 or IPv4 type is required.

    \sa blocking() protocol()
*/
MSocketDevice::MSocketDevice(Type type)
    : fd(-1), t(type), p(0), pp(0), e(NoError),
      d(new MSocketDevicePrivate(Unknown))

      //  d(new MSocketDevicePrivate(IPv4))
{
#if defined(MSOCKETDEVICE_DEBUG)
    qDebug("MSocketDevice: Created MSocketDevice object %p, type %d",
           this, type);
#endif
    init();

    // For the time being, if it's of type Datagram create the socket now
    // rather than later during connect (since there wont be one with udp)

    if (type == Datagram)
        setSocket(createNewSocket(), type);
}
Ejemplo n.º 7
0
QMulticastSocket::QMulticastSocket( QString sAddress, quint16 nPort, quint8 ttl )
                 : MSocketDevice( MSocketDevice::Datagram )
{
    m_address.setAddress( sAddress );
    m_port = nPort;

    //  ttl = UPnp::GetConfiguration()_pConfig->GetValue( "UPnP/TTL", 4 );

    if (ttl == 0)
        ttl = 4;

    // Force to IPv4 until a proper upnp spec is complete for ipv6 as well.
    setProtocol(IPv4);
    setSocket(createNewSocket(), MSocketDevice::Datagram);

    // ----------------------------------------------------------------------
    // Set the numer of subnets to traverse (TTL)
    // ----------------------------------------------------------------------

    setsockopt( socket(), IPPROTO_IP, IP_MULTICAST_TTL, (char *)(&ttl), sizeof(ttl) );

    setAddressReusable( true );

    // ----------------------------------------------------------------------
    // bind to the local address/port (win32 requires QHostAddress::Any be used
    // ----------------------------------------------------------------------

    if (bind( QHostAddress::Any, m_port ) == false)
       VERBOSE(VB_IMPORTANT, QString( "QMulticastSocket: bind failed (%1)" ).arg(  GET_SOCKET_ERROR ));

    // ----------------------------------------------------------------------
    // Now join the Multicast group
    // ----------------------------------------------------------------------

    QByteArray addr = sAddress.toLatin1();

    struct ip_mreq  imr;

    imr.imr_multiaddr.s_addr = inet_addr( addr.constData() );
    imr.imr_interface.s_addr = htonl(INADDR_ANY);       

    if ( setsockopt( socket(), IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *)(&imr), sizeof( imr )) != 0) 
        VERBOSE(VB_IMPORTANT, QString( "QMulticastSocket: setsockopt - IP_ADD_MEMBERSHIP Error (%1)" ).arg( GET_SOCKET_ERROR ));
}
Ejemplo n.º 8
0
/*!
    Connects to the IP address and port specified by \a addr and \a
    port. Returns true if it establishes a connection; otherwise returns false.
    If it returns false, error() explains why.

    Note that error() commonly returns NoError for non-blocking
    sockets; this just means that you can call connect() again in a
    little while and it'll probably succeed.
*/
bool MSocketDevice::connect( const QHostAddress &addr, quint16 port )
{
    if ( !isValid() )
    {
#if !defined(QT_NO_IPV6)
        if ( addr.protocol() == QAbstractSocket::IPv6Protocol ) {
            setProtocol(IPv6);
            VERBOSE(VB_SOCKET, "MSocketDevice::connect: setting Protocol to IPv6");
        }
        else   
#endif
        if ( addr.protocol() == QAbstractSocket::IPv4Protocol ) {
            setProtocol(IPv4);
            VERBOSE(VB_SOCKET, "MSocketDevice::connect: setting Protocol to IPv4");
        }

        VERBOSE(VB_SOCKET, "MSocketDevice::connect: attempting to create new socket");
        MSocketDevice::setSocket( createNewSocket(), t);
    
       // If still not valid, give up.
       if ( !isValid() )
           return false;
    }

    pa = addr;
    pp = port;

    struct sockaddr_in a4;
    struct sockaddr *aa;
    QT_SOCKLEN_T aalen;

#if !defined(QT_NO_IPV6)
    struct sockaddr_in6 a6;

    if ( addr.protocol() == QAbstractSocket::IPv6Protocol ) {
	memset( &a6, 0, sizeof(a6) );
	a6.sin6_family = AF_INET6;
	a6.sin6_port = htons( port );
	Q_IPV6ADDR ip6 = addr.toIPv6Address();
	memcpy( &a6.sin6_addr.s6_addr, &ip6, sizeof(ip6) );

	aalen = sizeof( a6 );
	aa = (struct sockaddr *)&a6;
    } else
#endif
    if ( addr.protocol() == QAbstractSocket::IPv4Protocol ) {
	memset( &a4, 0, sizeof(a4) );
	a4.sin_family = AF_INET;
	a4.sin_port = htons( port );
	a4.sin_addr.s_addr = htonl( addr.toIPv4Address() );

	aalen = sizeof(a4);
	aa = (struct sockaddr *)&a4;
    } else {
	e = Impossible;
	return false;
    }

    int r = QT_SOCKET_CONNECT( fd, aa, aalen );
    if ( r == 0 ) {
	fetchConnectionParameters();
	return true;
    }
    if ( errno == EISCONN || errno == EALREADY || errno == EINPROGRESS ) {
	fetchConnectionParameters();
	return true;
    }
    if ( e != NoError || errno == EAGAIN || errno == EWOULDBLOCK ) {
	return false;
    }
    switch( errno ) {
    case EBADF:
    case ENOTSOCK:
	e = Impossible;
	break;
    case EFAULT:
    case EAFNOSUPPORT:
	e = InternalError;
	break;
    case ECONNREFUSED:
	e = ConnectionRefused;
	break;
    case ETIMEDOUT:
    case ENETUNREACH:
	e = NetworkFailure;
	break;
    case EADDRINUSE:
	e = NoResources;
	break;
    case EACCES:
    case EPERM:
	e = Inaccessible;
	break;
    default:
	e = UnknownError;
	break;
    }
    return false;
}
// Slaves establish connections with master and other slaves.
void
SocketBasedConnectionInterface::establishConnections(const slaveStartupInfo& info) {
    ASSERT(connectionId != 0); // Only slaves executes this method.
#if 0
    std::cerr << "info.configTableEntry.size()=" << info.configTableEntry.size() << std::endl;
#endif
    ASSERT(info.configTableEntry.size() == 2);
    hostName = info.configTableEntry[0];

    // Create a vector of numberOfConnections number of socket pointers.
    createSocketPtrVector();

    // Set seed for random number generator.
    srand(93);

    // Create master socket and find an unused portnumber for it, bind and listen to it.
    createNewSocket(connectionId, SOCK_STREAM); // SOCK_STREAM --> TCP
    setDefaultSocketOptions(connectionId);
    std::string myPort = std::to_string(obtainAndBindUnusedPort(connectionId));

    // Establish connection with master.
    ASSERT(info.masterContactInfo.nrOfContactArguments() == 2);
    std::vector<std::string> args = info.masterContactInfo.contactArguments();
    // args[0]==hostname, args[1]==portNumber
    std::string masterHost = args[0];
    int masterPort = std::stoi(args[1]);
    unsigned int masterId = 0;
    createNewSocket(masterId, SOCK_STREAM); // SOCK_STREAM --> TCP
    setDefaultSocketOptions(masterId);
#ifdef DEBUG_SOCKET_CONN_START
    std::cerr << connectionId << ": Connecting to master " << masterHost << " " << masterPort <<
              std::endl;
#endif
    ASSERT(socket[masterId]->wConnect(masterHost.c_str(), masterPort) != -1);

#ifdef DEBUG_SOCKET_CONN_START
    std::cerr << connectionId << ": Done connecting to master. Now sending our portnumber (" << myPort
              << ") to master." << std::endl;
    std::cerr << connectionId << ": _____________ mtu="<<mtu<<", myPortLen="<<(strlen(
                                                                                   myPort.c_str())+1)<<"_____________" << std::endl;
#endif
    // Send a message to master containing our portnumber.
    unsigned int msgSize = mtu;
    char msg[mtu];
    ASSERT(mtu > static_cast<unsigned int>(strlen(myPort.c_str())+1));
    strcpy(msg, myPort.c_str());
    msgSize = static_cast<unsigned int>(strlen(myPort.c_str())+1);
    SocketBasedConnectionInterface::send(msgSize, msg, masterId);

#ifdef DEBUG_SOCKET_CONN_START
    std::cerr << connectionId <<
              ": Done sending portnumber to master. Now waiting to receive configFileTable." << std::endl;
#endif
    eclmplConfigFileTable connTable;
    // Receive serializedConnTable from master.
    msgSize = mtu;
    while (SocketBasedConnectionInterface::recv(msgSize, msg, masterId) == false) {
        msgSize = mtu; // Max allowed recv size.
    }
    ASSERT(masterId == 0); // masterId is a return parameter from recv.
    eclmplConfigFileTable localConnTable;
    localConnTable.deserialize(msg);

#ifdef DEBUG_SOCKET_CONN_START
    std::cerr << connectionId << ": Done receiving configFileTable=";
    __eclmpl__printCharStr(msg, msgSize);
    std::cerr << std::endl;
#endif
#ifdef DEBUG_SOCKET_CONN_START
    std::cerr << connectionId << ": Deserialized configFileTable=\n" << localConnTable << std::endl <<
              std::endl;
#endif
#ifdef DEBUG_SOCKET_CONN_START
    std::cerr << connectionId << ": Now going to establish connections with other slaves." << std::endl;
#endif
    // Establish connections with other slaves.
    establishConnectionsWithPeerSlaves(localConnTable);

#ifdef DEBUG_SOCKET_CONN_START
    std::cerr << connectionId << ": Done connecting to slaves. Now waiting to synchronize with master.."
              << std::endl;
#endif
    // Let master know we're done with connection establishment and Wait
    // for synchronize message from master.
    synchronizeWithMaster();
#ifdef DEBUG_SOCKET_CONN_START
    std::cerr << connectionId << ": Done synchronizing with master. Now ready to start communicating."
              << std::endl;
#endif

#if 0
    std::cerr << connectionId << ": DOOOOOOOOOONNNNNNNNEEEEEEEE__ ";
    for (unsigned int i = 0; i < numberOfConnections; i++) {
        std::cerr << socket[i]->getPortNumber() << " ";
    }
    std::cerr << std::endl;
#endif
} // End of establishConnections(...).
// Master establishes connection with slaves after forking them off.
void
SocketBasedConnectionInterface::establishConnections(const int* const argc,
                                                     const char* const* const* const argv,
                                                     const eclmplConfigFileTable& connTable) {

    ASSERT(connectionId == 0); // Only master executes this method.
    ASSERT(connTable.getNumberOfEntries() == numberOfConnections);
    std::vector<std::string> masterEntry = connTable.getEntry(0);
    ASSERT(masterEntry.size() == 2);

    // Create a vector of numberOfConnections number of socket pointers.
    createSocketPtrVector();

    // Set seed for random number generator.
    srand(93);

    // Create master socket and find an unused portnumber for it, bind and listen to it.
    createNewSocket(connectionId, SOCK_STREAM); // SOCK_STREAM --> TCP
    setDefaultSocketOptions(connectionId);
    std::string myPort = std::to_string(obtainAndBindUnusedPort(connectionId));

    eclmplConfigFileTable localConnTable = connTable;
    // Add portnumber info to localConnTable.
    localConnTable.addToEntry(myPort, (int)connectionId);

    // Start slaves and distribute updated connTable.
    eclmplContactInfo myContactInfo;
    myContactInfo.setProvidedBy(connectionId);
    std::vector<std::string> contactInfo;
    hostName = masterEntry[0];
    contactInfo.push_back(masterEntry[0]);
    contactInfo.push_back(myPort);
    myContactInfo.setContactArguments(contactInfo);
#if 0
    for (int i =0; i<connTable.getNumberOfEntries(); i++) {
        for (int j=0; j<connTable.getEntry(i).size(); j++) {
            std::cout << " " << connTable.getEntry(i)[j];
        }
        std::cout << std::endl;
    }
    std::cout << "NumberCons: " << numberOfConnections << std::endl;
#endif
    for (unsigned int i = 1; i < numberOfConnections; i++) {
        forkOffSlave(argc, argv, connTable, myContactInfo, i);
        int newSocketFd;
        struct sockaddr_in addr;
        int addrLen = sizeof(addr);
        ASSERT(socket[0]->wAccept(newSocketFd, (struct sockaddr*)&addr, &addrLen) != -1);
        ASSERT((socket[i] = new eclmplSocket(newSocketFd, addr, (int)addrLen)) != 0);
        setDefaultSocketOptions(i);

#ifdef DEBUG_SOCKET_CONN_START
        std::cerr << "0: Forked off slave " << i << ". Now waiting for its portnumber." << std::endl;
#endif
        // Receive portnumber where i is listening.
        unsigned int msgSize = mtu;
        char msg[mtu];
        while (SocketBasedConnectionInterface::recv(msgSize, msg, i) == false) {
            msgSize = mtu; // Max allowed recv size.
        }
        std::string slavePortNr = std::to_string(atoi(msg));
#ifdef DEBUG_SOCKET_CONN_START
        std::cerr << "0: Received portnumber " << slavePortNr << "from slave " << i << "." << std::endl;
#endif

        // Add portnumber info to localConnTable.
        localConnTable.addToEntry(slavePortNr, (int)i);
    }

#ifdef DEBUG_SOCKET_CONN_START
    std::cerr << "0: Done forking off slaves. Now about to distributeConfigFileTable" << std::endl;
#endif
    // Send serializedConnTable to slaves.
    distributeConfigFileTable(localConnTable);

#ifdef DEBUG_SOCKET_CONN_START
    std::cerr << "0: Done with distributeConfigFileTable. Now about to synchronize with slaves." <<
              std::endl;
#endif
    // Synchronize with slaves.
    synchronizeWithSlaves();

#ifdef DEBUG_SOCKET_CONN_START
    std::cerr << "0: Done synchronizing with slaves. Now ready to start communicating." << std::endl;
#endif
    // We're now ready to be used by some application...
} // End of establishConnections(...).
Ejemplo n.º 11
0
bool MSocketDevice::connect( const QHostAddress &addr, quint16 port )
{
    if ( !isValid() )
    {
#if !defined(QT_NO_IPV6)
        if ( addr.protocol() == QAbstractSocket::IPv6Protocol ) {
            setProtocol(IPv6);
            LOG(VB_SOCKET, LOG_INFO,
                "MSocketDevice::connect: setting Protocol to IPv6");
        }
        else
#endif  
        if ( addr.protocol() == QAbstractSocket::IPv4Protocol ) {
            setProtocol(IPv4);
            LOG(VB_SOCKET, LOG_INFO,
                "MSocketDevice::connect: setting Protocol to IPv4");
        }

        LOG(VB_SOCKET, LOG_INFO,
            "MSocketDevice::connect: attempting to create new socket");
        MSocketDevice::setSocket( createNewSocket(), t);

       // If still not valid, give up.
       if ( !isValid() )
       return false;
    }

    pa = addr;
    pp = port;

    struct sockaddr_in a4;
    struct sockaddr *aa;
    SOCKLEN_T aalen;

#if !defined(QT_NO_IPV6)
    qt_sockaddr_in6 a6;

    if ( initialized >= 0x20 && addr.protocol() == QAbstractSocket::IPv6Protocol ) {
        memset(&a6, 0, sizeof(a6));
	a6.sin6_family = AF_INET6;
	a6.sin6_port = htons( port );
	Q_IPV6ADDR ip6 = addr.toIPv6Address();
	memcpy( &a6.sin6_addr.qt_s6_addr, &ip6, sizeof(ip6) );

	aalen = sizeof( a6 );
	aa = (struct sockaddr *)&a6;
    } else
#endif
    if ( addr.protocol() == QAbstractSocket::IPv4Protocol ) {
	memset(&a4, 0, sizeof(a4));
	a4.sin_family = AF_INET;
	a4.sin_port = htons(port);
	a4.sin_addr.s_addr = htonl(addr.toIPv4Address());

	aalen = sizeof(a4);
	aa = (struct sockaddr *)&a4;
    } else {
	e = Impossible;
	return false;
    }

    int r = ::connect( fd, aa, aalen );

    if ( r == SOCKET_ERROR )
    {
	switch( WSAGetLastError() ) {
	    case WSANOTINITIALISED:
		e = Impossible;
		break;
	    case WSAENETDOWN:
		e = NetworkFailure;
		break;
	    case WSAEADDRINUSE:
	    case WSAEINPROGRESS:
	    case WSAENOBUFS:
		e = NoResources;
		break;
	    case WSAEINTR:
		e = UnknownError; // ### ?
		break;
	    case WSAEALREADY:
		// ### ?
		break;
	    case WSAEADDRNOTAVAIL:
		e = ConnectionRefused; // ### ?
		break;
	    case WSAEAFNOSUPPORT:
	    case WSAEFAULT:
		e = InternalError;
		break;
	    case WSAEINVAL:
		break;
	    case WSAECONNREFUSED:
		e = ConnectionRefused;
		break;
	    case WSAEISCONN:
		goto successful;
	    case WSAENETUNREACH:
	    case WSAETIMEDOUT:
		e = NetworkFailure;
		break;
	    case WSAENOTSOCK:
		e = Impossible;
		break;
	    case WSAEWOULDBLOCK:
		break;
	    case WSAEACCES:
		e = Inaccessible;
		break;
	    case 10107:
		// Workaround for a problem with the WinSock Proxy Server. See
		// also support/arc-12/25557 for details on the problem.
		goto successful;
	    default:
		e = UnknownError;
		break;
	}
	return false;
    }
successful:
    fetchConnectionParameters();
    return true;
}