Source Code (Use browser search to find items of interest.)

Class Index

kdelibs'DCOPServer (./kdelibs/dcop/dcopserver.h:51)

class DCOPServer : public QObject
{
    Q_OBJECT
public:
    DCOPServer();
    ~DCOPServer();

    void* watchConnection( IceConn iceConn );
    void removeConnection( void* data );
    void processMessage( IceConn iceConn, int opcode, unsigned long length, Bool swap);
    void ioError( IceConn iceConn );

    virtual bool receive(const QCString &app, const QCString &obj,
			 const QCString &fun, const QByteArray& data,
			 QCString& replyType, QByteArray &replyData, IceConn iceConn);

private slots:
    void newClient( int socket );
    void processData( int socket );

private:
    int majorOpcode;
    QList<DCOPListener> listener;
    QDict<DCOPConnection> appIds;
    QPtrDict<DCOPConnection> clients;

    class DCOPServerPrivate;
    DCOPServerPrivate *d;
};

kdelibs'DCOPServer::processMessage() (./kdelibs/dcop/dcopserver.cpp:356)

void DCOPServer::processMessage( IceConn iceConn, int opcode,
				 unsigned long length, Bool /*swap*/)
{
    switch( opcode ) {
    case DCOPSend:
    case DCOPReplyDelayed:
	{
	    DCOPMsg *pMsg = 0;
	    IceReadMessageHeader(iceConn, sizeof(DCOPMsg), DCOPMsg, pMsg);
	    QByteArray ba( length );
	    IceReadData(iceConn, length, ba.data() );
	    QDataStream ds( ba, IO_ReadOnly );
	    QCString appFrom, app;
	    ds >> appFrom >> app;
	    DCOPConnection* target = appIds.find( app );
	    DCOPConnection* conn = clients.find( iceConn );
	    if ( opcode == DCOPReplyDelayed )
		{
// 		    qDebug("DCOPServer::Got DCOPReplyDelayed (from: \"%s\" to: \"%s\")",
// 			   appFrom.data(), app.data());
		    if ( !target )
			qWarning("DCOPServer::DCOPReplyDelayed for unknown connection.");
		    else if ( !conn )
			qWarning("DCOPServer::DCOPReplyDelayed from unknown connection.");
		    else
			{
			    if (iceConn != target->waitingOn)
				qWarning("DCOPServer::DCOPReplyDelayed from/to does not match. (#1)");

			    if (!conn->waitingForDelayedReply.remove( target->iceConn ))
				qWarning("DCOPServer::DCOPReplyDelayed from/to does not match. (#2)");

			    target->waitingOn = 0;
			}
		}
	    if ( target ) {
		IceGetHeader( target->iceConn, majorOpcode, opcode,
			      sizeof(DCOPMsg), DCOPMsg, pMsg );
		int datalen = ba.size();
		pMsg->length += datalen;
		IceSendData(target->iceConn, datalen, (char *) ba.data());
	    } else if ( app == "DCOPServer" ) {
		QCString obj, fun;
		QByteArray data;
		ds >> obj >> fun >> data;
		QCString replyType;
		QByteArray replyData;
		if ( !receive( app, obj, fun, data, replyType, replyData, iceConn ) ) {
		    qWarning("%s failure: object '%s' has no function '%s'", app.data(), obj.data(), fun.data() );
		}
	    } else if ( app[app.length()-1] == '*') {
		// handle a multicast.
		QDictIterator<DCOPConnection> aIt(appIds);
		int l = app.length()-1;
		for ( ; aIt.current(); ++aIt)
		    {
			DCOPConnection *client = aIt.current();
			if (!l || (strncmp(client->appId.data(), app.data(), l) == 0))
			    {
				IceGetHeader(client->iceConn, majorOpcode, DCOPSend,
					     sizeof(DCOPMsg), DCOPMsg, pMsg);
				int datalen = ba.size();
				pMsg->length += datalen;
				IceSendData(client->iceConn, datalen, (char *) ba.data());
			    }
		    }
	    }
	}
	break;
    case DCOPCall:
	{
	    DCOPMsg *pMsg = 0;
	    IceReadMessageHeader(iceConn, sizeof(DCOPMsg), DCOPMsg, pMsg);
	    QByteArray ba( length );
	    IceReadData(iceConn, length, ba.data() );
	    QDataStream ds( ba, IO_ReadOnly );
	    QCString appFrom, app;
	    ds >> appFrom >> app;
	    DCOPConnection* conn = clients.find( iceConn );
	    DCOPConnection* target = appIds.find( app );
	    int datalen = ba.size();
	    if ( target ) {
		target->waitingForReply.append( iceConn );
		conn->waitingOn = target->iceConn;
		IceGetHeader( target->iceConn, majorOpcode, DCOPCall,
			      sizeof(DCOPMsg), DCOPMsg, pMsg );
		pMsg->length += datalen;
		IceSendData(target->iceConn, datalen, (char *) ba.data());
	    } else {
		QCString replyType;
		QByteArray replyData;
		bool b = FALSE;
		if ( app == "DCOPServer" ) {
		    QCString obj, fun;
		    QByteArray data;
		    ds >> obj >> fun >> data;
		    b = receive( app, obj, fun, data, replyType, replyData, iceConn );
		    if ( !b )
			qWarning("%s failure: object '%s' has no function '%s'", app.data(), obj.data(), fun.data() );
		}

		if (b)
		    {
			QByteArray reply;
			QDataStream replyStream( reply, IO_WriteOnly );
			replyStream << replyType << replyData.size();
			int datalen = reply.size() + replyData.size();
			IceGetHeader( iceConn, majorOpcode, DCOPReply,
				      sizeof(DCOPMsg), DCOPMsg, pMsg );
			pMsg->length += datalen;
			IceSendData( iceConn, reply.size(), (char *) reply.data());
			IceSendData( iceConn, replyData.size(), (char *) replyData.data());
		    }
		else
		    {
			QByteArray reply;
			IceGetHeader( iceConn, majorOpcode, DCOPReplyFailed,
				      sizeof(DCOPMsg), DCOPMsg, pMsg );
			pMsg->length += reply.size();
			IceSendData( iceConn, reply.size(), (char *) reply.data());
		    }
	    }
	}
	break;
    case DCOPReply:
    case DCOPReplyFailed:
    case DCOPReplyWait:
	{
	    DCOPMsg *pMsg = 0;
	    IceReadMessageHeader(iceConn, sizeof(DCOPMsg), DCOPMsg, pMsg);
	    QByteArray ba( length );
	    IceReadData(iceConn, length, ba.data() );
	    DCOPConnection* conn = clients.find( iceConn );
	    DCOPConnection* connreply = clients.find( conn->waitingForReply.take(0) );
	    if ( !conn )
		qWarning("DCOPServer::DCOPReply from unknown connection.");
	    else if ( !connreply )
		qWarning("DCOPServer::DCOPReply for unknown connection.");
	    else if ( connreply->waitingOn != conn->iceConn )
		qWarning("DCOPServer::Unexpected DCOPReply[Wait|Failed].");
	    else {
		if ( opcode == DCOPReplyWait ) {
		    conn->waitingForDelayedReply.append( connreply->iceConn );
		} else {
		    connreply->waitingOn = 0;
		}
		IceGetHeader( connreply->iceConn, majorOpcode, opcode,
			      sizeof(DCOPMsg), DCOPMsg, pMsg );
		int datalen = ba.size();
		pMsg->length += datalen;
		IceSendData(connreply->iceConn, datalen, (char *) ba.data());
	    }
	}
	break;
    default:
	qWarning("DCOPServer::processMessage unknown message");
    }
}



kdelibs'DCOPServer::DCOPServer() (./kdelibs/dcop/dcopserver.cpp:590)

DCOPServer::DCOPServer()
    : QObject(0,0), appIds(200), clients(200)
{
    extern int _IceLastMajorOpcode; // from libICE
    if (_IceLastMajorOpcode < 1 )
	registerXSM();

    the_server = this;
    if (( majorOpcode = IceRegisterForProtocolReply ((char *) "DCOP",
						     (char *) DCOPVendorString,
						     (char *) DCOPReleaseString,
						     1, DCOPVersions,
						     1, (char **) DCOPAuthNames,
						     DCOPServerAuthProcs,
						     HostBasedAuthProc,
						     DCOPServerProtocolSetupProc,
						     NULL,	/* IceProtocolActivateProc - we don't care about
								   when the Protocol Reply is sent, because the
								   session manager can not immediately send a
								   message - it must wait for RegisterClient. */
						     NULL	/* IceIOErrorProc */
						     )) < 0)
	{
	    qWarning("Could not register DCOP protocol with ICE");
	}

    char errormsg[256];
    if (!IceListenForConnections (&numTransports, &listenObjs,
				  256, errormsg))
	{
	    fprintf (stderr, "%s\n", errormsg);
	    exit (1);
	} else {
	    // publish available transports.
	    QCString fName = ::getenv("HOME");
	    fName += "/.DCOPserver";
	    FILE *f;
	    f = ::fopen(fName.data(), "w+");
	    fprintf(f, IceComposeNetworkIdList(numTransports, listenObjs));
	    fprintf(f, "\n%i\n", getpid());
	    fclose(f);
	}

    if (!SetAuthentication(numTransports, listenObjs, &authDataEntries))
	qFatal("DCOPSERVER: authentication setup failed.");

    IceAddConnectionWatch (DCOPWatchProc, (IcePointer) this);

    listener.setAutoDelete( TRUE );
    DCOPListener* con;
    for ( int i = 0; i < numTransports; i++) {
	con = new DCOPListener( listenObjs[i] );
	listener.append( con );
	connect( con, SIGNAL( activated(int) ), this, SLOT( newClient(int) ) );
    }
    char c;
    (void) write(ready[1], &c, 1); // dcopserver is started
    close(ready[1]);
}


kdelibs'DCOPServer::~DCOPServer() (./kdelibs/dcop/dcopserver.cpp:650)

DCOPServer::~DCOPServer()
{
    IceFreeListenObjs (numTransports, listenObjs);

    QCString fName;
    fName = ::getenv("DCOPSERVER");
    if (fName.isNull()) {
	fName = ::getenv("HOME");
	fName += "/.DCOPserver";
	unlink(fName.data());
    }

    FreeAuthenticationData(numTransports, authDataEntries);
}


/*!
  Called from our IceIoErrorHandler
 */

kdelibs'DCOPServer::ioError() (./kdelibs/dcop/dcopserver.cpp:669)

void DCOPServer::ioError( IceConn iceConn )
{
    IceSetShutdownNegotiation (iceConn, False);
    IceCloseConnection( iceConn );
}



kdelibs'DCOPServer::processData() (./kdelibs/dcop/dcopserver.cpp:676)

void DCOPServer::processData( int /*socket*/ )
{
    (void ) IceProcessMessages( ((DCOPConnection*)sender())->iceConn, 0, 0 );
}


kdelibs'DCOPServer::newClient() (./kdelibs/dcop/dcopserver.cpp:681)

void DCOPServer::newClient( int /*socket*/ )
{
    IceAcceptStatus status;
    IceConn iceConn = IceAcceptConnection( ((DCOPListener*)sender())->listenObj, &status);
    IceSetShutdownNegotiation( iceConn, False );

    IceConnectStatus cstatus;
    while ((cstatus = IceConnectionStatus (iceConn))==IceConnectPending) {
	qApp->processOneEvent();
    }
    if (cstatus != IceConnectAccepted) {
	if (cstatus == IceConnectIOError)
	    qWarning ("IO error opening ICE Connection!\n");
	else
	    qWarning ("ICE Connection rejected!\n");
	IceCloseConnection (iceConn);
    }
}


kdelibs'DCOPServer::watchConnection() (./kdelibs/dcop/dcopserver.cpp:700)

void* DCOPServer::watchConnection( IceConn iceConn )
{
    DCOPConnection* con = new DCOPConnection( iceConn );
    connect( con, SIGNAL( activated(int) ), this, SLOT( processData(int) ) );

    clients.insert(iceConn, con );

    return (void*) con;
}


kdelibs'DCOPServer::removeConnection() (./kdelibs/dcop/dcopserver.cpp:710)

void DCOPServer::removeConnection( void* data )
{
    DCOPConnection* conn = (DCOPConnection*)data;
    clients.remove(conn->iceConn );

    if (conn->waitingOn) {
	DCOPConnection* target = clients.find( conn->waitingOn );
	// We are expecting a response from 'target'.
	// We should be in either target->waitingForReply
	int i;
	while ((i = target->waitingForReply.findRef( conn->iceConn )) != -1) {
	    target->waitingForReply.take(i);
	    target->waitingForReply.insert(i,0);
	}
	// or in target->waitingForDelayedReply
	target->waitingForDelayedReply.remove( conn->iceConn );
    }

    // Send DCOPReplyFailed to all in conn->waitingForReply
    while (!conn->waitingForReply.isEmpty()) {
	IceConn iceConn = conn->waitingForReply.take(0);
	if (iceConn)
	    {
		DCOPConnection* target = clients.find( iceConn );
// 		if (target->waitingOn != conn->iceConn)
// 		    qDebug("DCOP: waitingForReply list corrupted.");
		target->waitingOn = 0L;
// 		qDebug("DCOP aborting call from '%s' to '%s'", target->appId.data(), conn->appId.data() );
		QByteArray reply;
		DCOPMsg *pMsg;
		IceGetHeader( iceConn, majorOpcode, DCOPReplyFailed,
			      sizeof(DCOPMsg), DCOPMsg, pMsg );
		pMsg->length += reply.size();
		IceSendData( iceConn, reply.size(), (char *) reply.data());
	    }
    }

    // Send DCOPReplyFailed to all in conn->waitingForDelayedReply
    while (!conn->waitingForDelayedReply.isEmpty()) {
	IceConn iceConn = conn->waitingForDelayedReply.take();
	if (iceConn)
	    {
		DCOPConnection* target = clients.find( iceConn );
// 		if (target->waitingOn != conn->iceConn)
// 		    qDebug("DCOP waitingForDelayedReply list corrupt.");
		target->waitingOn = 0L;
// 		qDebug("DCOP aborting (delayed) call from '%s' to '%s'", target->appId.data(), conn->appId.data() );
		QByteArray reply;
		DCOPMsg *pMsg;
		IceGetHeader( iceConn, majorOpcode, DCOPReplyFailed,
			      sizeof(DCOPMsg), DCOPMsg, pMsg );
		pMsg->length += reply.size();
		IceSendData( iceConn, reply.size(), (char *) reply.data());
	    }
    }

    // Send DCOPReplyDelayed with 0 seq to all in conn->waitingDelayedReply
    if ( !conn->appId.isNull() ) {
	qDebug("DCOP:  unregister '%s'", conn->appId.data() );
	appIds.remove( conn->appId );

	QPtrDictIterator<DCOPConnection> it( clients );
	QByteArray data;
	QDataStream datas( data, IO_WriteOnly );
	datas << conn->appId;
	QByteArray ba;
	QDataStream ds( ba, IO_WriteOnly );
	ds << QCString("DCOPServer") << QCString("")
	   << QCString("") << QCString("applicationRemoved(QCString)") << data;
	int datalen = ba.size();
	DCOPMsg *pMsg = 0;
	while ( it.current() ) {
	    DCOPConnection* c = it.current();
	    ++it;
	    if ( c->notifyRegister && (c != conn) ) {
		IceGetHeader( c->iceConn, majorOpcode, DCOPSend,
			      sizeof(DCOPMsg), DCOPMsg, pMsg );
		pMsg->length += datalen;
		IceSendData(c->iceConn, datalen, (char *) ba.data());
	    }
	}
    }
    delete conn;
}


kdelibs'DCOPServer::receive() (./kdelibs/dcop/dcopserver.cpp:795)

bool DCOPServer::receive(const QCString &/*app*/, const QCString &/*obj*/,
			 const QCString &fun, const QByteArray& data,
			 QCString& replyType, QByteArray &replyData,
			 IceConn iceConn)
{
    if ( fun == "registerAs(QCString)" ) {
	QDataStream args( data, IO_ReadOnly );
	if (!args.atEnd()) {
	    QCString app2;
	    args >> app2;
	    QDataStream reply( replyData, IO_WriteOnly );
	    DCOPConnection* conn = clients.find( iceConn );
	    if ( conn && !app2.isEmpty() ) {
		if ( !conn->appId.isNull() &&
		     appIds.find( conn->appId ) == conn ) {
		    appIds.remove( conn->appId );
		}

		if ( conn->appId.isNull() )
		    qDebug("DCOP: register '%s'", app2.data() );
		else
		    qDebug("DCOP:  '%s' now known as '%s'", conn->appId.data(), app2.data() );

		conn->appId = app2;
		if ( appIds.find( app2 ) != 0 ) {
		    // we already have this application, unify
		    int n = 1;
		    QCString tmp;
		    do {
			n++;
			tmp.setNum( n );
			tmp.prepend("-");
			tmp.prepend( app2 );
		    } while ( appIds.find( tmp ) != 0 );
		    conn->appId = tmp;
		}
		appIds.insert( conn->appId, conn );

		QPtrDictIterator<DCOPConnection> it( clients );
		QByteArray data;
		QDataStream datas( data, IO_WriteOnly );
		datas << conn->appId;
		QByteArray ba;
		QDataStream ds( ba, IO_WriteOnly );
		ds <<QCString("DCOPServer") <<  QCString("") << QCString("")
		   << QCString("applicationRegistered(QCString)") << data;
		int datalen = ba.size();
		DCOPMsg *pMsg = 0;
		while ( it.current() ) {
		    DCOPConnection* c = it.current();
		    ++it;
		    if ( c->notifyRegister && (c != conn) ) {
			IceGetHeader( c->iceConn, majorOpcode, DCOPSend,
				      sizeof(DCOPMsg), DCOPMsg, pMsg );
			pMsg->length += datalen;
			IceWriteData( c->iceConn, datalen, (char *) ba.data());
			IceFlush( c->iceConn );
		    }
		}
	    }
	    replyType = "QCString";
	    reply << conn->appId;
	    return TRUE;
	}
    }
    else if ( fun == "registeredApplications()" ) {
	QDataStream reply( replyData, IO_WriteOnly );
	QCStringList applications;
	QDictIterator<DCOPConnection> it( appIds );
	while ( it.current() ) {
	    applications << it.currentKey().ascii();
	    ++it;
	}
	replyType = "QCStringList";
	reply << applications;
	return TRUE;
    } else if ( fun == "isApplicationRegistered(QCString)" ) {
	QDataStream args( data, IO_ReadOnly );
	if (!args.atEnd()) {
	    QCString s;
	    args >> s;
	    QDataStream reply( replyData, IO_WriteOnly );
	    int b = ( appIds.find( s ) != 0 );
	    replyType = "bool";
	    reply << b;
	    return TRUE;
	}
    } else if ( fun == "setNotifications(bool)" ) {
	QDataStream args( data, IO_ReadOnly );
	if (!args.atEnd()) {
	    Q_INT8 notifyActive;
	    args >> notifyActive;
	    DCOPConnection* conn = clients.find( iceConn );
	    if ( conn )
		conn->notifyRegister = (notifyActive != 0);
	    replyType = "void";
	    return TRUE;
	}
    }

    return FALSE;
}