Ejemplo n.º 1
0
	void write(const QByteArray &buf, const QHostAddress &addr, int port)
	{
		QByteArray packet = allocate->encode(buf, addr, port);

		if(debugLevel >= TurnClient::DL_Packet)
		{
			StunMessage msg = StunMessage::fromBinary(packet);
			if(!msg.isNull())
			{
				emit q->debugLine("STUN SEND");
				emit q->debugLine(StunTypes::print_packet_str(msg));
			}
			else
				emit q->debugLine("Sending ChannelData-based data packet");
		}

		writeItems += WriteItem(packet.size(), addr, port);
		++outPendingWrite;
		if(udp)
		{
			emit q->outgoingDatagram(packet);
		}
		else
		{
			if(tls)
				tls->write(packet);
			else
				bs->write(packet);
		}
	}
Ejemplo n.º 2
0
	QByteArray processNonPoolPacket(const QByteArray &buf, bool notStun, QHostAddress *addr, int *port)
	{
		if(notStun)
		{
			// not stun?  maybe it is a data packet
			QByteArray data = allocate->decode(buf, addr, port);
			if(!data.isNull())
			{
				if(debugLevel >= TurnClient::DL_Packet)
					emit q->debugLine("Received ChannelData-based data packet");
				return data;
			}
		}
		else
		{
			// packet might be stun not owned by pool.
			//   let's see
			StunMessage message = StunMessage::fromBinary(buf);
			if(!message.isNull())
			{
				QByteArray data = allocate->decode(message, addr, port);

				if(!data.isNull())
				{
					if(debugLevel >= TurnClient::DL_Packet)
						emit q->debugLine("Received STUN-based data packet");
					return data;
				}
				else
				{
					if(debugLevel >= TurnClient::DL_Packet)
						emit q->debugLine("Warning: server responded with an unexpected STUN packet, skipping.");
				}

				return QByteArray();
			}
		}

		if(debugLevel >= TurnClient::DL_Packet)
			emit q->debugLine("Warning: server responded with what doesn't seem to be a STUN or data packet, skipping.");
		return QByteArray();
	}
Ejemplo n.º 3
0
	void tryRequest()
	{
		emit q->createMessage(pool->d->generateId());

		if(origMessage.isNull())
		{
			// since a transaction is not cancelable nor reusable,
			//   there's no DOR-SR issue here
			QMetaObject::invokeMethod(q, "error", Qt::QueuedConnection,
				Q_ARG(XMPP::StunTransaction::Error, StunTransaction::ErrorGeneric));
			return;
		}

		StunMessage out = origMessage;

		out.setClass(StunMessage::Request);
		id = QByteArray((const char *)out.id(), 12);

		if(!stuser.isEmpty())
		{
			QList<StunMessage::Attribute> list = out.attributes();
			StunMessage::Attribute attr;
			attr.type = StunTypes::USERNAME;
			attr.value = StunTypes::createUsername(QString::fromUtf8(StunUtil::saslPrep(stuser.toUtf8()).toByteArray()));
			list += attr;
			out.setAttributes(list);

			key = StunUtil::saslPrep(stpass.toUtf8()).toByteArray();
		}
		else if(!pool->d->nonce.isEmpty())
		{
			QList<StunMessage::Attribute> list = out.attributes();
			{
				StunMessage::Attribute attr;
				attr.type = StunTypes::USERNAME;
				attr.value = StunTypes::createUsername(QString::fromUtf8(StunUtil::saslPrep(pool->d->user.toUtf8()).toByteArray()));
				list += attr;
			}
			{
				StunMessage::Attribute attr;
				attr.type = StunTypes::REALM;
				attr.value = StunTypes::createRealm(pool->d->realm);
				list += attr;
			}
			{
				StunMessage::Attribute attr;
				attr.type = StunTypes::NONCE;
				attr.value = StunTypes::createNonce(pool->d->nonce);
				list += attr;
			}
			out.setAttributes(list);

			QCA::SecureArray buf;
			buf += StunUtil::saslPrep(pool->d->user.toUtf8());
			buf += QByteArray(1, ':');
			buf += StunUtil::saslPrep(pool->d->realm.toUtf8());
			buf += QByteArray(1, ':');
			buf += StunUtil::saslPrep(pool->d->pass);

			key = QCA::Hash("md5").process(buf).toByteArray();
		}

		if(!key.isEmpty())
			packet = out.toBinary(StunMessage::MessageIntegrity | StunMessage::Fingerprint, key);
		else
			packet = out.toBinary(StunMessage::Fingerprint);

		if(packet.isEmpty())
		{
			// since a transaction is not cancelable nor reusable,
			//   there's no DOR-SR issue here
			QMetaObject::invokeMethod(q, "error", Qt::QueuedConnection,
				Q_ARG(XMPP::StunTransaction::Error, StunTransaction::ErrorGeneric));
			return;
		}

		active = true;
		tries = 1; // we transmit immediately here, so count it

		if(mode == StunTransaction::Udp)
		{
			last_interval = rm * rto;
			t->start(rto);
			rto *= 2;
		}
		else if(mode == StunTransaction::Tcp)
		{
			t->start(ti);
		}
		else
			Q_ASSERT(0);

#ifdef STUNTRANSACTION_DEBUG
		time.start();
#endif
		pool->d->insert(q);
		transmit();
	}
Ejemplo n.º 4
0
void StunMessageTestSuite::testFullEncodeParse() 
{
    StunMessage msg ;
    StunMessage check ;
    bool bRC ;
    char szString[1024] ;
    uint16_t usValue ;
    bool bValue ;
    uint16_t values[16] ;
    size_t size ;

    // Valid empty state
    CPPUNIT_ASSERT(!msg.getMappedAddress(szString, usValue)) ;
    CPPUNIT_ASSERT(!msg.getResponseAddress(szString, usValue)) ;
    CPPUNIT_ASSERT(!msg.getChangePort()) ;
    CPPUNIT_ASSERT(!msg.getChangeIp()) ;
    CPPUNIT_ASSERT(!msg.getSourceAddress(szString, usValue)) ;
    CPPUNIT_ASSERT(!msg.getChangedAddress(szString, usValue)) ;
    CPPUNIT_ASSERT(!msg.getUsername(szString)) ;
    CPPUNIT_ASSERT(!msg.getPassword(szString)) ;
    CPPUNIT_ASSERT(!msg.getError(usValue, szString)) ;
    CPPUNIT_ASSERT(!msg.getUnknownAttributes(values, 16, size)) ;
    CPPUNIT_ASSERT(!msg.getReflectedFrom(szString, usValue)) ;
    CPPUNIT_ASSERT(!msg.getServer(szString)) ;

    // Set Values
    msg.setType(MSG_STUN_BIND_REQUEST) ;
    msg.allocTransactionId() ;
    msg.setMappedAddress("10.1.1.1", 1) ;
    msg.setResponseAddress("10.1.1.2", 2) ;
    msg.setChangePort(true) ;
    msg.setChangeIp(true) ;
    msg.setSourceAddress("10.1.1.3", 3) ;
    msg.setChangedAddress("10.1.1.4", 4) ;
    msg.setUsername("Username") ;
    msg.setPassword("Password") ;
    msg.setError(302, "Reason") ;
    msg.addUnknownAttribute(0x1234) ;
    msg.setReflectedFrom("10.1.1.5", 5) ;
    msg.setServer("Server") ;

    // Verify Values
    CPPUNIT_ASSERT(msg.getType() == MSG_STUN_BIND_REQUEST) ;

    bRC = msg.getMappedAddress(szString, usValue) ;
    CPPUNIT_ASSERT(bRC) ;
    CPPUNIT_ASSERT(strcmp(szString, "10.1.1.1") == 0) ;
    CPPUNIT_ASSERT(usValue == 1) ;

    bRC = msg.getResponseAddress(szString, usValue) ;
    CPPUNIT_ASSERT(bRC) ;
    CPPUNIT_ASSERT(strcmp(szString, "10.1.1.2") == 0) ;
    CPPUNIT_ASSERT(usValue == 2) ;

    bValue = msg.getChangePort() ;
    CPPUNIT_ASSERT(bValue == true) ;

    bValue = msg.getChangeIp() ;
    CPPUNIT_ASSERT(bValue == true) ;

    bRC = msg.getSourceAddress(szString, usValue) ;
    CPPUNIT_ASSERT(bRC) ;
    CPPUNIT_ASSERT(strcmp(szString, "10.1.1.3") == 0) ;
    CPPUNIT_ASSERT(usValue == 3) ;

    bRC = msg.getChangedAddress(szString, usValue) ;
    CPPUNIT_ASSERT(bRC) ;
    CPPUNIT_ASSERT(strcmp(szString, "10.1.1.4") == 0) ;
    CPPUNIT_ASSERT(usValue == 4) ;

    bRC = msg.getUsername(szString) ;
    CPPUNIT_ASSERT(bRC) ;
    CPPUNIT_ASSERT(strcmp(szString, "Username") == 0) ;

    bRC = msg.getPassword(szString) ;
    CPPUNIT_ASSERT(bRC) ;
    CPPUNIT_ASSERT(strcmp(szString, "Password") == 0) ;

    bRC = msg.getError(usValue, szString) ;
    CPPUNIT_ASSERT(bRC) ;
    CPPUNIT_ASSERT(usValue == 302) ;
    CPPUNIT_ASSERT(strcmp(szString, "Reason") == 0) ;

    bRC = msg.getUnknownAttributes(values, 16, size) ;
    CPPUNIT_ASSERT(bRC) ;
    CPPUNIT_ASSERT(size == 1) ;
    CPPUNIT_ASSERT(values[0] == 0x1234) ;
    
    bRC = msg.getReflectedFrom(szString, usValue) ;
    CPPUNIT_ASSERT(bRC) ;
    CPPUNIT_ASSERT(strcmp(szString, "10.1.1.5") == 0) ;
    CPPUNIT_ASSERT(usValue == 5) ;

    bRC = msg.getServer(szString) ;
    CPPUNIT_ASSERT(bRC) ;
    CPPUNIT_ASSERT(strcmp(szString, "Server") == 0) ;

    msg.setRequestXorOnly() ;

    char encoded[4096] ;
    size_t nLength ;
    if (msg.encode(encoded, 4096, nLength))
    {
        if (check.parse(encoded, nLength))
        {
            // Verify Values (again -- copy from above)
            CPPUNIT_ASSERT(msg.getType() == MSG_STUN_BIND_REQUEST) ;

            bRC = msg.getMappedAddress(szString, usValue) ;
            CPPUNIT_ASSERT(bRC) ;
            CPPUNIT_ASSERT(strcmp(szString, "10.1.1.1") == 0) ;
            CPPUNIT_ASSERT(usValue == 1) ;

            bRC = msg.getResponseAddress(szString, usValue) ;
            CPPUNIT_ASSERT(bRC) ;
            CPPUNIT_ASSERT(strcmp(szString, "10.1.1.2") == 0) ;
            CPPUNIT_ASSERT(usValue == 2) ;

            bValue = msg.getChangePort() ;
            CPPUNIT_ASSERT(bValue == true) ;

            bValue = msg.getChangeIp() ;
            CPPUNIT_ASSERT(bValue == true) ;

            bRC = msg.getSourceAddress(szString, usValue) ;
            CPPUNIT_ASSERT(bRC) ;
            CPPUNIT_ASSERT(strcmp(szString, "10.1.1.3") == 0) ;
            CPPUNIT_ASSERT(usValue == 3) ;

            bRC = msg.getChangedAddress(szString, usValue) ;
            CPPUNIT_ASSERT(bRC) ;
            CPPUNIT_ASSERT(strcmp(szString, "10.1.1.4") == 0) ;
            CPPUNIT_ASSERT(usValue == 4) ;

            bRC = msg.getUsername(szString) ;
            CPPUNIT_ASSERT(bRC) ;
            CPPUNIT_ASSERT(strcmp(szString, "Username") == 0) ;

            bRC = msg.getPassword(szString) ;
            CPPUNIT_ASSERT(bRC) ;
            CPPUNIT_ASSERT(strcmp(szString, "Password") == 0) ;

            bRC = msg.getError(usValue, szString) ;
            CPPUNIT_ASSERT(bRC) ;
            CPPUNIT_ASSERT(usValue == 302) ;
            CPPUNIT_ASSERT(strcmp(szString, "Reason") == 0) ;

            bRC = msg.getUnknownAttributes(values, 16, size) ;
            CPPUNIT_ASSERT(bRC) ;
            CPPUNIT_ASSERT(size == 1) ;
            CPPUNIT_ASSERT(values[0] == 0x1234) ;

            bRC = msg.getReflectedFrom(szString, usValue) ;
            CPPUNIT_ASSERT(bRC) ;
            CPPUNIT_ASSERT(strcmp(szString, "10.1.1.5") == 0) ;
            CPPUNIT_ASSERT(usValue == 5) ;

            bRC = msg.getServer(szString) ;
            CPPUNIT_ASSERT(bRC) ;
            CPPUNIT_ASSERT(strcmp(szString, "Server") == 0) ;
        }
        else
        {
            CPPUNIT_ASSERT(false) ;
        }
    }
    else
    {
        CPPUNIT_ASSERT(false) ;
    }
}
Ejemplo n.º 5
0
bool StunUtils::sendStunNatTest(OsDatagramSocket* pSocket,
                                const char* szServerIp,
                                const int port,
                                bool bChangePort,
                                bool bChangeIP,
                                char* szMappedIp,
                                unsigned short* piMappedPort,
                                char* szChangedIp,
                                unsigned short* piChangedPort) 
{
    StunMessage msgSend ;
    char cMsgSend[2048] ;
    StunMessage msgReceive ;
    char cMsgReceive[2048] ;
    size_t nLength ;
    bool bSuccess = false ;
    
    msgSend.setType(MSG_STUN_BIND_REQUEST) ;
    msgSend.allocTransactionId() ;
    msgSend.setRequestXorOnly() ;

    if (bChangePort)
    {
        msgSend.setChangePort(true) ;
    }
    if (bChangeIP)
    {
        msgSend.setChangeIp(true) ;
    }

    if (msgSend.encode(cMsgSend, sizeof(cMsgSend), nLength))
    {
        for (int i=0; (i<3) && (bSuccess == false); i++)
        {
            if (pSocket->write(cMsgSend, (int) nLength, szServerIp, port) > 0)
            {
                if (pSocket->isReadyToRead(500))
                {
                    int length = pSocket->read(cMsgReceive, sizeof(cMsgReceive)) ;
                    if ((length > 0) && msgReceive.parse(cMsgReceive, length))
                    {
                        if (msgReceive.getType() == MSG_STUN_BIND_RESPONSE)
                        {
                            bSuccess = true ;

                            // Get optional mapped address
                            if (szMappedIp && piMappedPort)
                            {
                                msgReceive.getMappedAddress(szMappedIp, *piMappedPort) ;
                            }

                            // Get optional changed address
                            if (szChangedIp && piChangedPort)
                            {
                                msgReceive.getChangedAddress(szChangedIp, *piChangedPort) ;                        
                            }
                        }
                        else
                        {
                            // Abort on error response
                            break ;
                        }
                    }
                }
            }
            else
            {
                break ;
            }
        }
    }
    else
    {
        assert(false) ;
    }

    return bSuccess ;
}