void SharedDaemon::AddNewClient(const std::string &host, const stringVector &args, void *cbdata)
{
    /// Send appropriate message for TCP or WebConnection
    void** data = (void**)cbdata;
    ConnectionType typeOfConnection = *((ConnectionType*)(data[0]));
    QAbstractSocket* socket = static_cast<QAbstractSocket*>(data[1]);
    ViewerState* viewerState = static_cast<ViewerState*>(data[2]);

    JSONNode node;

    QString hostname = typeOfConnection == TcpConnection ? socket->localAddress().toString():
                        dynamic_cast<QWsSocket*>(socket)->internalSocket()->localAddress().toString();

    if(hostMap.contains(hostname)) hostname = hostMap[hostname];

    node["host"] = hostname.toStdString(); //host
    node["port"]  = args[7]; //port
    node["version"] = args[2]; //version
    node["securityKey"] = args[9]; //key
    node["numStates"] = viewerState->GetNumStateObjects(); //number of states

    JSONNode::JSONArray rpc_array = JSONNode::JSONArray();

    for(size_t i = 0; i < ViewerRPC::MaxRPC; ++i) {
        rpc_array.push_back(ViewerRPC::ViewerRPCType_ToString((ViewerRPC::ViewerRPCType)i));
    }
    node["rpc_array"] = rpc_array;

    if(typeOfConnection == TcpConnection)
    {
        QTcpSocket *tsocket = dynamic_cast<QTcpSocket*>(socket);

        std::string message = node.ToString();
        tsocket->write(message.c_str(),message.length());

        if(tsocket->state() != QAbstractSocket::UnconnectedState)
            tsocket->waitForBytesWritten();
        tsocket->disconnectFromHost();
        if(tsocket->state() != QAbstractSocket::UnconnectedState)
            tsocket->waitForDisconnected();
        //HKTODO: Do not delete connection (test fix for ORNL machines)
        //tsocket->deleteLater();
    }
    else
    {
        QWsSocket *wsocket = dynamic_cast<QWsSocket*>(socket);

        wsocket->write(QString(node.ToString().c_str()));
        wsocket->flush();
        if(wsocket->internalSocket()->state() != QAbstractSocket::UnconnectedState)
            wsocket->internalSocket()->waitForBytesWritten();

        wsocket->close("");
        wsocket->internalSocket()->disconnectFromHost();
        if(wsocket->internalSocket()->state() != QAbstractSocket::UnconnectedState)
            wsocket->internalSocket()->waitForDisconnected();
        wsocket->deleteLater();
    }
}
Exemple #2
0
void QIOServer::sendMessage(const QString &message)
{
    QWsSocket * client;
    foreach ( client, _clients )
    {
        //QMetaObject::invokeMethod(client, "write", Q_ARG(const QString &, message));
        client->write( message );
    }
Exemple #3
0
void SharedDaemon::AddNewClient(const std::string &host, const stringVector &args, void *cbdata)
{
    /// Send appropriate message for TCP or WebConnection
    void** data = (void**)cbdata;
    ConnectionType typeOfConnection = *((ConnectionType*)(data[0]));
    QAbstractSocket* socket = static_cast<QAbstractSocket*>(data[1]);

    JSONNode node;

    node["host"] = args[5]; //host
    node["port"]  = args[7]; //port
    node["version"] = args[2]; //version
    node["securityKey"] = args[9]; //key

    if(typeOfConnection == TcpConnection)
    {
        QTcpSocket *tsocket = dynamic_cast<QTcpSocket*>(socket);

        std::string message = node.ToString();
        tsocket->write(message.c_str(),message.length());
        tsocket->waitForBytesWritten();
        tsocket->disconnectFromHost();
        tsocket->waitForDisconnected();
        tsocket->deleteLater();
    }
    else
    {
        QWsSocket *wsocket = dynamic_cast<QWsSocket*>(socket);

        wsocket->write(QString(node.ToString().c_str()));
        wsocket->flush();
        wsocket->internalSocket()->waitForBytesWritten();

        wsocket->close();
        wsocket->internalSocket()->disconnectFromHost();
        wsocket->internalSocket()->waitForDisconnected();
        wsocket->deleteLater();
    }
}
Exemple #4
0
void SharedDaemon::handleConnection()
{
    QTcpSocket *socket = nextPendingConnection();

    if ( !socket ) return;

    //the connecting socket should have sent password..
    //the client should be sending a password..
    socket->waitForReadyRead();

    if (!socket->bytesAvailable())
    {
        //std::cout << "no bytes available to read" << std::endl;
        socket->close();
        return;
    }

    QAbstractSocket* finalSocket = NULL;
    ConnectionType typeOfConnection = TcpConnection;

    QByteArray result = socket->readAll();
    QString input(result);

    /// initial connection must pass password, but can optionally pass
    /// whether the client canRender and what the threshold value should be..
    std::string lpasswd = "";
    bool canRender = false;

    /// check if this is a WebSocketConnection
    QString response = "";

    if(input.startsWith("{") && ParseInput(input,lpasswd,canRender))
    {
        finalSocket = socket;
        typeOfConnection = TcpConnection;
    } /// check if this is a WebSocketConnection..
    else if(QWsSocket::initializeWebSocket(result,response))
    {
        /// this is a websocket connection, respond and get frame..
        socket->write(response.toAscii());
        socket->flush();

        QEventLoop loop;

        matched_input = "";

        QWsSocket* wssocket = new QWsSocket(socket);

        connect(wssocket,SIGNAL(frameReceived(QString)),
                this,SLOT(getPasswordMessage(QString)));

        connect(wssocket,SIGNAL(frameReceived(QString)),
                &loop,SLOT(quit()));

        /// wait for password to be sent ..
        /// std::cout << "waiting for password from websocket" << std::endl;
        loop.exec();

        disconnect(wssocket,SIGNAL(frameReceived(QString)),
                this,SLOT(getPasswordMessage(QString)));

        disconnect(wssocket,SIGNAL(frameReceived(QString)),
                &loop,SLOT(quit()));

        //std::cout << matched_input.toStdString() << std::endl;

        if( !ParseInput(matched_input,lpasswd,canRender) )
        {
            //std::cout << "passwords do not match: "
            //          << matched_password.toStdString()
            //          << " " << password << std::endl;

            disconnect(wssocket,SIGNAL(frameReceived(QString)),
                    this,SLOT(getPasswordMessage(QString)));
            wssocket->close("passwords do not match or operation timed out");
            socket->waitForDisconnected();

            wssocket->deleteLater();
            return;
        }

        finalSocket = wssocket;
        typeOfConnection = WSocketConnection;

    } /// not sure what connection this is, reject it..
    else
    {
        //send rejection notice..
        std::string errorString = "Unknown connection..";
        socket->write(errorString.c_str(),errorString.length());
        socket->disconnectFromHost();
        socket->waitForDisconnected();
        return;
    }

    //passwords match enable RemoteProcess and get port remote Process is listening to.
    //send host,port,security_key and whatever else so that remote machine can successfully reverse connect
    std::string program = "remoteApp";
    std::string clientName = "newclient1";

    ViewerClientConnection *newClient = new
            ViewerClientConnection(subject->GetViewerState(),
                                   this,
                                   clientName.c_str(),
                                   true);

    newClient->SetExternalClient(true);
    newClient->SetAdvancedRendering(canRender);
    stringVector args;

    /// assign whether connection is of type WebSocket or TCPConnection
    /// Register Type & Register Callback
    RemoteProcess::SetCustomConnectionCallback(createCustomConnection,&typeOfConnection);

    void* data[2];
    data[0] = &typeOfConnection;
    data[1] = (void*)finalSocket;
    newClient->LaunchClient(program,args,AddNewClient,data,0,0);

    RemoteProcess::SetCustomConnectionCallback(0,0); /// reset connection..

    /// Now that client has launched RemoveCallback..
    subject->AddNewViewerClientConnection(newClient);
}
Exemple #5
0
void QWsServer::dataReceived()
{
	QTcpSocket * tcpSocket = qobject_cast<QTcpSocket*>( sender() );
	if (tcpSocket == 0)
		return;

	bool allHeadersFetched = false;

	const QLatin1String emptyLine("\r\n");

	while ( tcpSocket->canReadLine() )
	{
		QString line = tcpSocket->readLine();

		if (line == emptyLine)
		{
			allHeadersFetched = true;
			break;
		}

		headerBuffer[ tcpSocket ].append(line);
	}

	if (!allHeadersFetched)
	    return;

	QString request( headerBuffer[ tcpSocket ].join("") );

	QRegExp regExp;
	regExp.setMinimal( true );
	
	// Extract mandatory datas
	// Version
	regExp.setPattern( QWsServer::regExpVersionStr );
	regExp.indexIn(request);
	QString versionStr = regExp.cap(1);
	EWebsocketVersion version;
	if ( ! versionStr.isEmpty() )
	{
		version = (EWebsocketVersion)versionStr.toInt();
	}
	else if ( tcpSocket->bytesAvailable() >= 8 )
	{
		version = WS_V0;
		request.append( tcpSocket->read(8) );
	}
	else
	{
		version = WS_VUnknow;
	}

	// Resource name
	regExp.setPattern( QWsServer::regExpResourceNameStr );
	regExp.indexIn(request);
	QString resourceName = regExp.cap(1);
	
	// Host (address & port)
	regExp.setPattern( QWsServer::regExpHostStr );
	regExp.indexIn(request);
	QString host = regExp.cap(1);
	QStringList hostTmp = host.split(':');
	QString hostAddress = hostTmp[0];
	QString hostPort;
	if ( hostTmp.size() > 1 )
        hostPort = hostTmp.last(); // fix for IPv6
	
	// Key
	QString key, key1, key2, key3;
	if ( version >= WS_V4 )
	{
		regExp.setPattern( QWsServer::regExpKeyStr );
		regExp.indexIn(request);
		key = regExp.cap(1);
	}
	else
	{
		regExp.setPattern( QWsServer::regExpKey1Str );
		regExp.indexIn(request);
		key1 = regExp.cap(1);
		regExp.setPattern( QWsServer::regExpKey2Str );
		regExp.indexIn(request);
		key2 = regExp.cap(1);
		regExp.setPattern( QWsServer::regExpKey3Str );
		regExp.indexIn(request);
		key3 = regExp.cap(1);
	}
	
	////////////////////////////////////////////////////////////////////

	// If the mandatory fields are not specified, we abord the connection to the Websocket server
	if ( version == WS_VUnknow || resourceName.isEmpty() || hostAddress.isEmpty() || ( key.isEmpty() && ( key1.isEmpty() || key2.isEmpty() || key3.isEmpty() ) ) )
	{
		// Send bad request response
		QString response = QWsServer::composeBadRequestResponse( QList<EWebsocketVersion>() << WS_V6 << WS_V7 << WS_V8 << WS_V13 );
		tcpSocket->write( response.toUtf8() );
		tcpSocket->flush();
		return;
	}
	
	////////////////////////////////////////////////////////////////////
	
	// Extract optional datas

	// Origin
	regExp.setPattern( QWsServer::regExpOriginStr );
	if ( regExp.indexIn(request) == -1 )
	{
		regExp.setPattern( QWsServer::regExpOrigin2Str );
		regExp.indexIn(request);
	}
	QString origin = regExp.cap(1);

	// Protocol
	regExp.setPattern( QWsServer::regExpProtocolStr );
	regExp.indexIn(request);
	QString protocol = regExp.cap(1);

	// Extensions
	regExp.setPattern( QWsServer::regExpExtensionsStr );
	regExp.indexIn(request);
	QString extensions = regExp.cap(1);
	
	////////////////////////////////////////////////////////////////////
	
	// Compose opening handshake response
	QString response;

	if ( version >= WS_V6 )
	{
		QString accept = computeAcceptV4( key );
		response = QWsServer::composeOpeningHandshakeResponseV6( accept, protocol );
	}
	else if ( version >= WS_V4 )
	{
		QString accept = computeAcceptV4( key );
		QString nonce = generateNonce();
		response = QWsServer::composeOpeningHandshakeResponseV4( accept, nonce, protocol );
	}
	else
	{
		QString accept = computeAcceptV0( key1, key2, key3 );
		response = QWsServer::composeOpeningHandshakeResponseV0( accept, origin, hostAddress, hostPort, resourceName , protocol );
	}
	
	// Handshake OK, disconnect readyRead
	disconnect( tcpSocket, SIGNAL(readyRead()), this, SLOT(dataReceived()) );

	// Send opening handshake response
	if ( version == WS_V0 )
        tcpSocket->write( response.toLatin1() );
	else
		tcpSocket->write( response.toUtf8() );
	tcpSocket->flush();

	QWsSocket * wsSocket = new QWsSocket( this, tcpSocket, version );
	wsSocket->setResourceName( resourceName );
	wsSocket->setHost( host );
	wsSocket->setHostAddress( hostAddress );
	wsSocket->setHostPort( hostPort.toInt() );
	wsSocket->setOrigin( origin );
	wsSocket->setProtocol( protocol );
	wsSocket->setExtensions( extensions );
	wsSocket->serverSideSocket = true;
	
	// ORIGINAL CODE
	//int socketDescriptor = tcpSocket->socketDescriptor();
	//incomingConnection( socketDescriptor );
	
	// CHANGED CODE FOR LINUX COMPATIBILITY
	addPendingConnection( wsSocket );
	emit newConnection();
}
void SharedDaemon::handleConnection()
{
    QTcpSocket *socket = nextPendingConnection();

    if ( !socket ) return;

    //the connecting socket should have sent password..
    //the client should be sending a password..
    socket->waitForReadyRead();

    if (!socket->bytesAvailable())
    {
        //std::cout << "no bytes available to read" << std::endl;
        socket->close();
        return;
    }
    std::cout << "user: "******" is attempting to connect" << std::endl;

    QAbstractSocket* finalSocket = NULL;
    ConnectionType typeOfConnection = TcpConnection;

    QByteArray result = socket->readAll();
    QString input(result);

    /// initial connection must pass password, but can optionally pass
    /// whether the client canRender and what the threshold value should be..
    JSONNode output;

    /// check if this is a WebSocketConnection
    QString response = "";
    if(input.startsWith("{") && ParseInput(input,output))
    {
        finalSocket = socket;
        typeOfConnection = TcpConnection;
    } /// check if this is a WebSocketConnection..
    else if(QWsSocket::initializeWebSocket(result,response))
    {
        /// this is a websocket connection, respond and get frame..
        socket->write(response.toLatin1());
        socket->flush();

        QEventLoop loop;

        matched_input = "";

        QWsSocket* wssocket = new QWsSocket(socket);

        connect(wssocket,SIGNAL(frameReceived(QString)),
                this,SLOT(getPasswordMessage(QString)));

        connect(wssocket,SIGNAL(frameReceived(QString)),
                &loop,SLOT(quit()));

        /// wait for password to be sent ..
        /// std::cout << "waiting for password from websocket" << std::endl;
        loop.exec();

        disconnect(wssocket,SIGNAL(frameReceived(QString)),
                this,SLOT(getPasswordMessage(QString)));

        disconnect(wssocket,SIGNAL(frameReceived(QString)),
                &loop,SLOT(quit()));

        //std::cout << matched_input.toStdString() << std::endl;

        if( !ParseInput(matched_input,output) )
        {
            //std::cout << "passwords do not match: "
            //          << matched_password.toStdString()
            //          << " " << password << std::endl;

            wssocket->close("passwords do not match or operation timed out");

            if(socket->state() != QAbstractSocket::UnconnectedState)
                socket->waitForDisconnected();

            wssocket->deleteLater();
            return;
        }

        finalSocket = wssocket;
        typeOfConnection = WSocketConnection;

    } /// not sure what connection this is, reject it..
    else
    {
        //send rejection notice..
        std::string errorString = "Unknown connection..";
        socket->write(errorString.c_str(),errorString.length());
        socket->disconnectFromHost();
        socket->waitForDisconnected();
        return;
    }

    //passwords match enable RemoteProcess and get port remote Process is listening to.
    //send host,port,security_key and whatever else so that remote machine can successfully reverse connect
    std::string program = "remoteApp";
    std::string clientName = "newclient1";

    ViewerClientConnection *newClient = new
            ViewerClientConnection(subject->GetViewerState(),
                                   this,
                                   clientName.c_str(),
                                   true);

    ViewerClientAttributes& clientAtts = newClient->GetViewerClientAttributes();
    JSONNode::JSONObject jo = output.GetJsonObject();

    clientAtts.SetExternalClient(true);

    if(jo.count("name") == 0 || jo["name"].GetString().size() == 0)
        clientAtts.SetTitle(socket->peerAddress().toString().toStdString());
    else
        clientAtts.SetTitle(jo["name"].GetString());

    if(jo.count("windowIds") > 0 && jo["windowIds"].GetType() == JSONNode::JSONARRAY)
    {
        const JSONNode::JSONArray& array = jo["windowIds"].GetArray();

        for(size_t i = 0; i < array.size(); ++i)
        {
            const JSONNode& node = array[i];

            if(node.GetType() != JSONNode::JSONINTEGER)
                continue;

            std::cout << clientAtts.GetTitle() <<  " requesting window: " << node.GetInt() << " " << std::endl;
            clientAtts.GetWindowIds().push_back(node.GetInt());
        }
    }

    if(jo.count("geometry") > 0)
    {
        std::string geometry = jo["geometry"].GetString();

        /// split into width & height...
        size_t index = geometry.find("x");
        if(index != std::string::npos && index != 0 && index != geometry.size()-1)
        {
            int geometryWidth = atoi(geometry.substr(0,index).c_str());
            int geometryHeight = atoi(geometry.substr(index+1).c_str());

            clientAtts.SetImageWidth(geometryWidth);
            clientAtts.SetImageHeight(geometryHeight);
            //std::cout << "geometry: " << clientAtts.clientWidth << " " << clientAtts.clientHeight << std::endl;
        }
    }

    /// advanced rendering can be true or false (image only), or string none,image,data
    if(jo.count("canRender") == 0) {
        clientAtts.SetRenderingType(ViewerClientAttributes::None);
        clientAtts.GetRenderingTypes().push_back(ViewerClientAttributes::None);
    }
    else
    {
        const JSONNode& node = jo["canRender"];
        QString type = node.GetString().c_str();
        type = type.toLower();

        /// TODO: remove the boolean check and make all current clients comply..
        if(node.GetType() == JSONNode::JSONBOOL) {
            clientAtts.SetRenderingType( node.GetBool() ? ViewerClientAttributes::Image :
                                                          ViewerClientAttributes::None);
            clientAtts.GetRenderingTypes().push_back(node.GetBool() ? ViewerClientAttributes::Image :
                                                                      ViewerClientAttributes::None);
        }
        else if(node.GetType() == JSONNode::JSONSTRING)
        {
            if(type == "image") {
                clientAtts.SetRenderingType(ViewerClientAttributes::Image);
                clientAtts.GetRenderingTypes().push_back((int)ViewerClientAttributes::Image);
            }
            else if(type == "data") {
                clientAtts.SetRenderingType(ViewerClientAttributes::Data);
                clientAtts.GetRenderingTypes().push_back((int)ViewerClientAttributes::Data);
            }
            else {
                clientAtts.SetRenderingType(ViewerClientAttributes::None);
                clientAtts.GetRenderingTypes().push_back((int)ViewerClientAttributes::None);
            }
        }
        else
        {
            clientAtts.SetRenderingType(ViewerClientAttributes::None);
            clientAtts.GetRenderingTypes().push_back((int)ViewerClientAttributes::None);
        }
    }
    stringVector args;

    /// assign whether connection is of type WebSocket or TCPConnection
    /// Register Type & Register Callback
    RemoteProcess::SetCustomConnectionCallback(createCustomConnection,&typeOfConnection);

    TRY
    {
        void* data[3];
        data[0] = &typeOfConnection;
        data[1] = (void*)finalSocket;
        data[2] = (void*)subject->GetViewerState();

        newClient->LaunchClient(program,args,AddNewClient,data,0,0);

        /// Now that client has launched RemoveCallback..
        subject->AddNewViewerClientConnection(newClient);
        std::cout << "user: "******" successfully connected" << std::endl;
    }
    CATCHALL
    {
        std::cout << "user: "******" failed to connected" << std::endl;
        delete newClient;
    }
    ENDTRY

    RemoteProcess::SetCustomConnectionCallback(0,0); /// reset connection..
}