/**
 * Return a map from a credential byte to the corresponding connections ids.
 *
 * The connection ids retrieved here can be used to map a source address
 * which connected to your socket to a connection ID (for error reporting) and further, to a contact
 * (by using contactsForConnections()).
 *
 * This method is only useful if this tube was offered using an Unix socket and passing credential
 * bytes was enabled (\c requireCredentials == true).
 *
 * Note that this function will only return valid data after the tube has been opened.
 *
 * This method requires StreamTubeChannel::FeatureConnectionMonitoring to be ready.
 *
 * \return The map from credential bytes to the corresponding connection ids.
 * \sa connectionsForSourceAddresses()
 */
QHash<uchar, uint> OutgoingStreamTubeChannel::connectionsForCredentials() const
{
    if (addressType() != SocketAddressTypeUnix && addressType() != SocketAddressTypeAbstractUnix) {
        warning() << "OutgoingStreamTubeChannel::connectionsForCredentials() makes sense "
                "just when offering an Unix socket";
        return QHash<uchar, uint>();
    }

    if (accessControl() != SocketAccessControlCredentials) {
        warning() << "OutgoingStreamTubeChannel::connectionsForCredentials() makes sense "
                "just when offering an Unix socket requiring credentials";
        return QHash<uchar, uint>();
    }

    if (isValid() || !isDroppingConnections() ||
            !requestedFeatures().contains(StreamTubeChannel::FeatureConnectionMonitoring)) {
        if (!isReady(StreamTubeChannel::FeatureConnectionMonitoring)) {
            warning() << "StreamTubeChannel::FeatureConnectionMonitoring must be ready before "
                "calling OutgoingStreamTubeChannel::connectionsForCredentials()";
            return QHash<uchar, uint>();
        }

        if (state() != TubeChannelStateOpen) {
            warning() << "OutgoingStreamTubeChannel::connectionsForCredentials() makes sense "
                "just when the tube is opened";
            return QHash<uchar, uint>();
        }
    }

    return mPriv->connectionsForCredentials;
}
/**
 * Return a map from a source address to the corresponding connections ids.
 *
 * The connection ids retrieved here can be used to map a source address
 * which connected to your socket to a connection ID (for error reporting) and further, to a contact
 * (by using contactsForConnections()).
 *
 * This method is only useful if a TCP socket was offered on this tube and the connection manager
 * supports #SocketAccessControlPort, which can be discovered using
 * supportsIPv4SocketsWithSpecifiedAddress() and supportsIPv6SocketsWithSpecifiedAddress() for IPv4
 * and IPv6 sockets respectively.
 *
 * Note that this function will only return valid data after the tube has been opened.
 *
 * This method requires StreamTubeChannel::FeatureConnectionMonitoring to be ready.
 *
 * \return The map from source addresses as (QHostAddress, port in native byte order) pairs to the
 *     corresponding connection ids.
 * \sa connectionsForCredentials()
 */
QHash<QPair<QHostAddress, quint16>, uint> OutgoingStreamTubeChannel::connectionsForSourceAddresses() const
{
    if (addressType() != SocketAddressTypeIPv4 && addressType() != SocketAddressTypeIPv6) {
        warning() << "OutgoingStreamTubeChannel::connectionsForSourceAddresses() makes sense "
                "just when offering a TCP socket";
        return QHash<QPair<QHostAddress, quint16>, uint>();
    }

    if (isValid() || !isDroppingConnections() ||
            !requestedFeatures().contains(StreamTubeChannel::FeatureConnectionMonitoring)) {
        if (!isReady(StreamTubeChannel::FeatureConnectionMonitoring)) {
            warning() << "StreamTubeChannel::FeatureConnectionMonitoring must be ready before "
                "   calling connectionsForSourceAddresses";
            return QHash<QPair<QHostAddress, quint16>, uint>();
        }

        if (state() != TubeChannelStateOpen) {
            warning() << "OutgoingStreamTubeChannel::connectionsForSourceAddresses() makes sense "
                "just when the tube is open";
            return QHash<QPair<QHostAddress, quint16>, uint>();
        }
    }

    return mPriv->connectionsForSourceAddresses;
}
Example #3
0
void CTestUtilClass::TestUtilClass_Step4L()
	{
	//
	// Test ParseRxResultsForCSCAResponse
	//
	// fill data with garbage
	RMobilePhone::TMobileAddress addr;
	addr.iTypeOfNumber=RMobilePhone::ESubscriberNumber;
	addr.iNumberPlan=RMobilePhone::EDataNumberPlan;
	addr.iTelNumber.Copy(_L("000111000111000111000111"));

	// setup a response to be parsed
	_LIT8(KAddressValue,"01632960000");
	_LIT8(KAddressType,"129");
	TPtrC8 addressValue(KAddressValue);
	TPtrC8 addressType(KAddressType);

	// Parse reponse and validate output
	INFO_PRINTF1(_L(".."));
	TESTL(KErrNone == CATSmsUtils::CopyAddressStringToAddressStruct(addressValue,addressType,addr));
	if(addr.iTypeOfNumber!=RMobilePhone::EUnknownNumber ||
	   addr.iNumberPlan!=RMobilePhone::EIsdnNumberPlan || 
	   addr.iTelNumber.Compare(_L("01632960000"))!=0)
		TESTL(KErrCorrupt);
	}
/**
 * Accept an incoming stream tube as a Unix socket.
 *
 * This method accepts an incoming connection request for a stream tube. It can be called
 * only if the tube is in the #TubeStateLocalPending state.
 *
 * An Unix socket (can be used with QLocalSocket or alike) will be opened by the connection manager
 * as the local tube endpoint. This is only supported if supportsUnixSocketsOnLocalhost() is \c
 * true.
 *
 * You can also specify whether the CM should require an SCM_CREDS or SCM_CREDENTIALS message
 * upon connection instead of accepting every incoming connection from localhost. This provides
 * additional security, but requires sending the byte retrieved from
 * PendingStreamTubeConnection::credentialByte() in-line in the socket byte stream (in a credentials
 * message if available on the platform), which might not be compatible with all protocols or
 * libraries. Also, only connection managers for which supportsUnixSocketsWithCredentials() is \c
 * true support this type of access control.
 *
 * This method requires IncomingStreamTubeChannel::FeatureCore to be ready.
 *
 * \param requireCredentials Whether the CM should require an SCM_CREDS or SCM_CREDENTIALS message
 *                           upon connection.
 * \return A PendingStreamTubeConnection which will emit PendingStreamTubeConnection::finished
 *         when the stream tube is ready to be used
 *         (hence in the #TubeStateOpen state).
 * \sa StreamTubeChannel::supportsUnixSocketsOnLocalhost(),
 *     StreamTubeChannel::supportsUnixSocketsWithCredentials(),
 *     StreamTubeChannel::supportsAbstractUnixSocketsOnLocalhost(),
 *     StreamTubeChannel::supportsAbstractUnixSocketsWithCredentials()
 */
PendingStreamTubeConnection *IncomingStreamTubeChannel::acceptTubeAsUnixSocket(
        bool requireCredentials)
{
    if (!isReady(IncomingStreamTubeChannel::FeatureCore)) {
        warning() << "IncomingStreamTubeChannel::FeatureCore must be ready before "
                "calling acceptTubeAsUnixSocket";
        return new PendingStreamTubeConnection(TP_QT_ERROR_NOT_AVAILABLE,
                QLatin1String("Channel not ready"),
                IncomingStreamTubeChannelPtr(this));
    }

    // The tube must be in local pending state
    if (state() != TubeChannelStateLocalPending) {
        warning() << "You can accept tubes only when they are in LocalPending state";
        return new PendingStreamTubeConnection(TP_QT_ERROR_NOT_AVAILABLE,
                QLatin1String("Channel not ready"),
                IncomingStreamTubeChannelPtr(this));
    }

    SocketAccessControl accessControl = requireCredentials ?
            SocketAccessControlCredentials :
            SocketAccessControlLocalhost;
    setAddressType(SocketAddressTypeUnix);
    setAccessControl(accessControl);

    // Fail early if the combination is not supported
    if ((accessControl == SocketAccessControlLocalhost &&
            addressType() == SocketAddressTypeUnix &&
            !supportsUnixSocketsOnLocalhost()) ||
        (accessControl == SocketAccessControlCredentials &&
            addressType() == SocketAddressTypeUnix &&
            !supportsUnixSocketsWithCredentials()) ||
        (accessControl == SocketAccessControlLocalhost &&
            addressType() == SocketAddressTypeAbstractUnix &&
           !supportsAbstractUnixSocketsOnLocalhost()) ||
        (accessControl == SocketAccessControlCredentials &&
           addressType() == SocketAddressTypeAbstractUnix &&
           !supportsAbstractUnixSocketsWithCredentials())) {
        warning() << "You requested an address type/access control combination "
                "not supported by this channel";
        return new PendingStreamTubeConnection(TP_QT_ERROR_NOT_IMPLEMENTED,
                QLatin1String("The requested address type/access control "
                        "combination is not supported"),
                IncomingStreamTubeChannelPtr(this));
    }

    QDBusVariant accessControlParam;
    uchar credentialByte = 0;
    if (accessControl == SocketAccessControlLocalhost) {
        accessControlParam.setVariant(qVariantFromValue(static_cast<uint>(0)));
    } else if (accessControl == SocketAccessControlCredentials) {
        if (mPriv->initRandom) {
            qsrand(QTime::currentTime().msec());
            mPriv->initRandom = false;
        }
        credentialByte = static_cast<uchar>(qrand());
        accessControlParam.setVariant(qVariantFromValue(credentialByte));
    } else {
        Q_ASSERT(false);
    }

    // Perform the actual call
    PendingVariant *pv = new PendingVariant(
            interface<Client::ChannelTypeStreamTubeInterface>()->Accept(
                    addressType(),
                    accessControl,
                    accessControlParam),
            IncomingStreamTubeChannelPtr(this));

    PendingStreamTubeConnection *op = new PendingStreamTubeConnection(pv, addressType(),
            requireCredentials, credentialByte, IncomingStreamTubeChannelPtr(this));
    return op;
}
/**
 * Accept an incoming stream tube as a TCP socket.
 *
 * This method accepts an incoming connection request for a stream tube. It can be called
 * only if the tube is in the #TubeStateLocalPending state.
 *
 * The connection manager will open a TCP socket for the application to connect to. The address of
 * the socket will be returned in PendingStreamTubeConnection::ipAddress() once the operation has
 * finished successfully.
 *
 * This overload lets you specify an allowed address/port combination for connecting to the CM
 * socket. Connections with other source addresses won't be accepted. The accessors
 * supportsIPv4SocketsWithSpecifiedAddress() and supportsIPv6SocketsWithSpecifiedAddress() can be
 * used to verify that the connection manager supports this kind of access control; otherwise, this
 * method will always fail unless QHostAddress::Any (or QHostAddress::AnyIPv4 in Qt5) or
 * QHostAddress::AnyIPv6 is passed, in which case the behavior is identical to the always supported
 * acceptTubeAsTcpSocket() overload.
 *
 * Note that when using QHostAddress::Any (or QHostAddress::AnyIPv4 in Qt5) or
 * QHostAddress::AnyIPv6, \a allowedPort is ignored.
 *
 * This method requires IncomingStreamTubeChannel::FeatureCore to be ready.
 *
 * \param allowedAddress An allowed address for connecting to the socket.
 * \param allowedPort An allowed port for connecting to the socket.
 * \return A PendingStreamTubeConnection which will emit PendingStreamTubeConnection::finished
 *         when the stream tube is ready to be used
 *         (hence in the #TubeStateOpen state).
 */
PendingStreamTubeConnection *IncomingStreamTubeChannel::acceptTubeAsTcpSocket(
        const QHostAddress &allowedAddress,
        quint16 allowedPort)
{
    if (!isReady(IncomingStreamTubeChannel::FeatureCore)) {
        warning() << "IncomingStreamTubeChannel::FeatureCore must be ready before "
                "calling acceptTubeAsTcpSocket";
        return new PendingStreamTubeConnection(TP_QT_ERROR_NOT_AVAILABLE,
                QLatin1String("Channel not ready"),
                IncomingStreamTubeChannelPtr(this));
    }

    // The tube must be in local pending state
    if (state() != TubeChannelStateLocalPending) {
        warning() << "You can accept tubes only when they are in LocalPending state";
        return new PendingStreamTubeConnection(TP_QT_ERROR_NOT_AVAILABLE,
                QLatin1String("Channel not ready"),
                IncomingStreamTubeChannelPtr(this));
    }

    QVariant controlParameter;
    SocketAccessControl accessControl;
    QHostAddress hostAddress = allowedAddress;

#if QT_VERSION >= 0x050000
    if (hostAddress == QHostAddress::Any) {
        hostAddress = QHostAddress::AnyIPv4;
    }
#endif

    // Now, let's check what we need to do with accessControl. There is just one special case, Port.
    if (hostAddress != QHostAddress::Any &&
#if QT_VERSION >= 0x050000
        hostAddress != QHostAddress::AnyIPv4 &&
#endif
        hostAddress != QHostAddress::AnyIPv6) {
        // We need to have a valid QHostAddress AND Port.
        if (hostAddress.isNull() || allowedPort == 0) {
            warning() << "You have to set a valid allowed address+port to use Port access control";
            return new PendingStreamTubeConnection(TP_QT_ERROR_INVALID_ARGUMENT,
                    QLatin1String("The supplied allowed address and/or port was invalid"),
                    IncomingStreamTubeChannelPtr(this));
        }

        accessControl = SocketAccessControlPort;

        // IPv4 or IPv6?
        if (hostAddress.protocol() == QAbstractSocket::IPv4Protocol) {
            // IPv4 case
            SocketAddressIPv4 addr;
            addr.address = hostAddress.toString();
            addr.port = allowedPort;

            controlParameter = QVariant::fromValue(addr);
        } else if (hostAddress.protocol() == QAbstractSocket::IPv6Protocol) {
            // IPv6 case
            SocketAddressIPv6 addr;
            addr.address = hostAddress.toString();
            addr.port = allowedPort;

            controlParameter = QVariant::fromValue(addr);
        } else {
            // We're handling an IPv4/IPv6 socket only
            warning() << "acceptTubeAsTcpSocket can be called only with a QHostAddress "
                    "representing an IPv4 or IPv6 address";
            return new PendingStreamTubeConnection(TP_QT_ERROR_INVALID_ARGUMENT,
                    QLatin1String("Invalid host given"),
                    IncomingStreamTubeChannelPtr(this));
        }
    } else {
        // We have to do no special stuff here
        accessControl = SocketAccessControlLocalhost;
        // Since QDBusMarshaller does not like null variants, just add an empty string.
        controlParameter = QVariant(QString());
    }

    // Set the correct address type and access control
    setAddressType(hostAddress.protocol() == QAbstractSocket::IPv4Protocol ?
            SocketAddressTypeIPv4 :
            SocketAddressTypeIPv6);
    setAccessControl(accessControl);

    // Fail early if the combination is not supported
    if ((accessControl == SocketAccessControlLocalhost &&
            addressType() == SocketAddressTypeIPv4 &&
            !supportsIPv4SocketsOnLocalhost()) ||
        (accessControl == SocketAccessControlPort &&
            addressType() == SocketAddressTypeIPv4 &&
            !supportsIPv4SocketsWithSpecifiedAddress()) ||
        (accessControl == SocketAccessControlLocalhost &&
            addressType() == SocketAddressTypeIPv6 &&
            !supportsIPv6SocketsOnLocalhost()) ||
        (accessControl == SocketAccessControlPort &&
            addressType() == SocketAddressTypeIPv6 &&
            !supportsIPv6SocketsWithSpecifiedAddress())) {
        warning() << "You requested an address type/access control combination "
                "not supported by this channel";
        return new PendingStreamTubeConnection(TP_QT_ERROR_NOT_IMPLEMENTED,
                QLatin1String("The requested address type/access control "
                              "combination is not supported"),
                IncomingStreamTubeChannelPtr(this));
    }

    // Perform the actual call
    PendingVariant *pv = new PendingVariant(
            interface<Client::ChannelTypeStreamTubeInterface>()->Accept(
                    addressType(),
                    accessControl,
                    QDBusVariant(controlParameter)),
            IncomingStreamTubeChannelPtr(this));

    PendingStreamTubeConnection *op = new PendingStreamTubeConnection(pv, addressType(),
            false, 0, IncomingStreamTubeChannelPtr(this));
    return op;
}