void Synchronizer::_registerWndClass() // Win32-only
{
 	if (sm_iClass)
 	{
 		UT_DEBUGMSG(("Skipping window class registration\n"));
 		return;
 	}
  
 	AbiCollabSessionManager * pSessionManager = AbiCollabSessionManager::getManager();
 	UT_return_if_fail(pSessionManager);
  
 	HINSTANCE hInstance = pSessionManager->getInstance();
 	UT_return_if_fail(hInstance);
  
 	WNDCLASS wc;
 	wc.style = CS_HREDRAW | CS_VREDRAW;
 	wc.lpfnWndProc = Synchronizer::s_wndProc;
 	wc.cbClsExtra = 0;
 	wc.cbWndExtra = 0;
 	wc.hInstance = hInstance;
 	wc.hIcon = NULL;
 	wc.hCursor = NULL;
 	wc.hbrBackground = NULL;
 	wc.lpszMenuName =  NULL;
 	wc.lpszClassName = SYNC_CLASSNAME;
  
 	sm_iClass = RegisterClass(&wc);
 	UT_return_if_fail(sm_iClass);
 	
 	sm_iMessageWindows = 0;
}
void AP_UnixDialog_CollaborationAddBuddy::_populateWindowData()
{
	// populate the account combobox
	GtkListStore* store = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_POINTER);
	GtkTreeIter iter;
	AbiCollabSessionManager* pManager = AbiCollabSessionManager::getManager();

	for (UT_uint32 i = 0; i < pManager->getAccounts().size(); i++)
	{
		AccountHandler* pHandler = pManager->getAccounts()[i];
		if (pHandler && pHandler->allowsManualBuddies())
		{
			gtk_list_store_append (store, &iter);
			gtk_list_store_set (store, &iter,
						DESC_COLUMN, pHandler->getDescription().utf8_str(),
						HANDLER_COLUMN, pHandler,
						-1);
		}
	}
	m_model = GTK_TREE_MODEL (store);
	gtk_combo_box_set_model(GTK_COMBO_BOX(m_wAccount), m_model);

	// if we have at least one account, then make sure the first one is selected
	if (pManager->getAccounts().size() > 0)
	{
		gtk_combo_box_set_active(GTK_COMBO_BOX(m_wAccount), 0);
	}
	else
	{
		// nope, we don't have any account :'-(
		gtk_combo_box_set_active(GTK_COMBO_BOX(m_wAccount), -1);
	}
}
bool TelepathyAccountHandler::disconnect()
{
	UT_DEBUGMSG(("TelepathyAccountHandler::disconnect()\n"));
	UT_return_val_if_fail(m_pTpClient, false);

	AbiCollabSessionManager* pManager = AbiCollabSessionManager::getManager();
	UT_return_val_if_fail(pManager, false);

	// unregister as a telepathy client
	tp_base_client_unregister(m_pTpClient);
	m_pTpClient = NULL;

	// tear down all active rooms
	for (std::vector<TelepathyChatroomPtr>::iterator it = m_chatrooms.begin(); it != m_chatrooms.end(); it++)
		(*it)->stop();

	// we are disconnected now, no need to receive events anymore
	pManager->unregisterEventListener(this);

	// signal all listeners we are logged out
	AccountOfflineEvent event;
	AbiCollabSessionManager::getManager()->signal(event);

	return true;
}
示例#4
0
void TCPAccountHandler::addBuddy(BuddyPtr pBuddy)
{
	UT_DEBUGMSG(("TCPAccountHandler::addBuddy()\n"));
	UT_return_if_fail(pBuddy);
	
	AbiCollabSessionManager* pManager = AbiCollabSessionManager::getManager();
	UT_return_if_fail(pManager);
	
	if (getProperty("allow-all") == "true")
	{
		const UT_GenericVector<AbiCollab *> pSessions = pManager->getSessions();
		for (UT_sint32 i = 0; i < pSessions.size(); i++)
		{
			AbiCollab* pSession = pSessions.getNthItem(i);
			UT_continue_if_fail(pSession);
			
			if (pSession->getAclAccount() != this)
				continue;
			
			pSession->appendAcl(pBuddy->getDescriptor(false).utf8_str());
		}
	}
	
	AccountHandler::addBuddy(pBuddy);
}
GtkListStore* AP_UnixDialog_CollaborationAccounts::_constructModel()
{
	GtkTreeIter iter;
	GtkListStore* model = gtk_list_store_new (4, G_TYPE_BOOLEAN, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_POINTER);

	AbiCollabSessionManager* pManager = AbiCollabSessionManager::getManager();
	for (UT_uint32 i = 0; i < pManager->getAccounts().size(); i++)
	{
		AccountHandler* pHandler = pManager->getAccounts()[i];
		if (pHandler)
		{
			UT_DEBUGMSG(("Got account: %s of type %s\n", 
					pHandler->getDescription().utf8_str(), 
					pHandler->getDisplayType().utf8_str()
				));
			
			gtk_list_store_append (model, &iter);	
			gtk_list_store_set (model, &iter, 
					ONLINE_COLUMN, pHandler->isOnline(),
					DESC_COLUMN, pHandler->getDescription().utf8_str(), 
					TYPE_COLUMN, pHandler->getDisplayType().utf8_str(), 
					HANDLER_COLUMN, pHandler,
					-1);
		}
	}
	
	return model;
}
void TelepathyAccountHandler::handleMessage(DTubeBuddyPtr pBuddy, const std::string& packet_str)
{
	UT_DEBUGMSG(("TelepathyAccountHandler::handleMessage()\n"));
	UT_return_if_fail(pBuddy);

	AbiCollabSessionManager* pManager = AbiCollabSessionManager::getManager();
	UT_return_if_fail(pManager);

	TelepathyChatroomPtr pChatroom = pBuddy->getChatRoom();
	UT_return_if_fail(pChatroom);

	// construct the packet
	Packet* pPacket = _createPacket(packet_str, pBuddy);
	UT_return_if_fail(pPacket);

	switch (pPacket->getClassType())
	{
		case PCT_GetSessionsEvent:
		{
			if (pChatroom->isLocallyControlled())
			{
				// return only the session that belongs to the chatroom that the buddy is in
				GetSessionsResponseEvent gsre;
				gsre.m_Sessions[pChatroom->getSessionId()] = pChatroom->getDocName();
				send(&gsre, pBuddy);
			}
			else
				UT_DEBUGMSG(("Ignoring GetSessionsEvent, we are not controlling session '%s'\n", pChatroom->getSessionId().utf8_str()));

			break;
		}
		case PCT_GetSessionsResponseEvent:
		{
			// check if we received 1 (and only 1) session, and join it
			// immediately if that is the case

			GetSessionsResponseEvent* gsre = static_cast<GetSessionsResponseEvent*>( pPacket );
			UT_return_if_fail(gsre->m_Sessions.size() == 1);
			std::map<UT_UTF8String,UT_UTF8String>::iterator it=gsre->m_Sessions.begin();
			DocHandle* pDocHandle = new DocHandle((*it).first, (*it).second);

			// store the session id
			pChatroom->setSessionId(pDocHandle->getSessionId());

			// join the session
			UT_DEBUGMSG(("Got a running session (%s - %s), let's join it immediately\n", pDocHandle->getSessionId().utf8_str(), pDocHandle->getName().utf8_str()));
			pManager->joinSessionInitiate(pBuddy, pDocHandle);
			DELETEP(pDocHandle);
			break;
		}
		default:
			// let the default handler handle it
			AccountHandler::handleMessage(pPacket, pBuddy);
			break;
	}
}
示例#7
0
/*!
 * This virtual method is called if the attached document is deleted with an attached
 * AbiCollab_Export connected to the document.
 */
void ABI_Collab_Export::removeDocument(void)
{
	UT_DEBUGMSG(("ABI_Collab_Export::removeDocument()\n"));

	// inform the session manager that this session is being (forcefully) closed
	AbiCollabSessionManager* pManager = AbiCollabSessionManager::getManager();
	UT_return_if_fail(pManager);
	
	// WARNING: Don't do anything after this line, as the disconnectSession() call will
	// have destroyed ourselves (yes, that is ugly).
	pManager->disconnectSession(m_pAbiCollab);
}
void AbiCollab::initiateSessionTakeover(BuddyPtr pNewMaster)
{
    UT_return_if_fail(pNewMaster);
    UT_DEBUGMSG(("AbiCollab::initiateSessionTakeover() - pNewMaster: %s\n", pNewMaster->getDescriptor(true).utf8_str()));

    AbiCollabSessionManager* pManager = AbiCollabSessionManager::getManager();
    UT_return_if_fail(pManager);

    // this could lead to us never exiting; add a timeout or something somewhere :)
    pManager->beginAsyncOperation(this);

    // NOTE: we only allow slaves in the session takeover process
    // that are on the same account as the proposed master is. The
    // others are dropped from the session. At least for now.
    // TODO: implement me

    // reset any old session takeover state
    m_bProposedController = false;
    m_pProposedController = pNewMaster;
    m_vApprovedReconnectBuddies.clear();
    m_mAckedSessionTakeoverBuddies.clear();
    m_bSessionFlushed = false;
    if (m_vOutgoingQueue.size() > 0)
        UT_ASSERT_HARMLESS(UT_SHOULD_NOT_HAPPEN);
    m_vOutgoingQueue.clear();

    // send a SessionTakeoverRequest packet to the new master
    std::vector<std::string> buddyIdentifiers;
    for (std::map<BuddyPtr, std::string>::iterator it = m_vCollaborators.begin(); it != m_vCollaborators.end(); it++)
    {
        BuddyPtr pBuddy = (*it).first;
        UT_continue_if_fail(pBuddy);
        if (pNewMaster != pBuddy)
            buddyIdentifiers.push_back(pBuddy->getDescriptor(true).utf8_str());
    }
    SessionTakeoverRequestPacket strp_promote(m_sId, m_pDoc->getDocUUIDString(), true, buddyIdentifiers);
    pNewMaster->getHandler()->send(&strp_promote, pNewMaster);

    // send a SessionTakeoverRequest packet to the other slaves (if any)
    buddyIdentifiers.clear();
    buddyIdentifiers.push_back(pNewMaster->getDescriptor(true).utf8_str());
    SessionTakeoverRequestPacket strp_normal(m_sId, m_pDoc->getDocUUIDString(), false, buddyIdentifiers);
    for (std::map<BuddyPtr, std::string>::iterator it = m_vCollaborators.begin(); it != m_vCollaborators.end(); it++)
    {
        BuddyPtr pBuddy = (*it).first;
        UT_continue_if_fail(pBuddy);
        if (pNewMaster != pBuddy)
            pBuddy->getHandler()->send(&strp_normal, pBuddy);
    }

    m_eTakeoveState = STS_SENT_TAKEOVER_REQUEST;
}
void AP_Dialog_CollaborationShare::share(AccountHandler* pAccount, const std::vector<std::string>& vAcl)
{
	UT_DEBUGMSG(("AP_Dialog_CollaborationShare::_share()\n"));

	AbiCollabSessionManager* pManager = AbiCollabSessionManager::getManager();
	UT_return_if_fail(pManager);

	// determine which document to share
	XAP_Frame* pFrame = XAP_App::getApp()->getLastFocussedFrame();
	UT_return_if_fail(pFrame);

	PD_Document* pDoc = static_cast<PD_Document *>(pFrame->getCurrentDoc());
	UT_return_if_fail(pDoc);

	AbiCollab* pSession = NULL;
	if (!pManager->isInSession(pDoc))
	{
		UT_DEBUGMSG(("Sharing document...\n"));

		// FIXME: this can cause a race condition: the other side can already be
		// offered the session before we actually started it!
		
		// Tell the account handler that we start a new session, so
		// it set up things if needed. This call may just setup some stuff 
		// for a new session, or it might actually start a new session.
		bool b = pAccount->startSession(pDoc, m_vAcl, &pSession);
		if (!b)
		{
			XAP_App::getApp()->getLastFocussedFrame()->showMessageBox(
						"There was an error sharing this document!", 
						XAP_Dialog_MessageBox::b_O, XAP_Dialog_MessageBox::a_OK);
			return;
		}
		
		// start the session ourselves when the account handler did not...
		if (!pSession)
		{
			// ... and start the session!
			UT_UTF8String sSessionId("");
			// TODO: we could use/generate a proper descriptor when there is only
			// 1 account where we share this document over
			pSession = pManager->startSession(pDoc, sSessionId, pAccount, true, NULL, "");
		}
	}
	else
	{
		pSession = pManager->getSession(pDoc);
	}

	UT_return_if_fail(pSession);
	pManager->updateAcl(pSession, pAccount, vAcl);
}
void AP_UnixDialog_CollaborationShare::_populateWindowData()
{
	AbiCollabSessionManager* pManager = AbiCollabSessionManager::getManager();
	UT_return_if_fail(pManager);

	// populate the account combobox
	GtkListStore* store = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_POINTER);
	GtkTreeIter iter;

	AccountHandler* pShareeableAcount = _getShareableAccountHandler();
	if (pShareeableAcount)
	{
			gtk_list_store_append (store, &iter);
			gtk_list_store_set (store, &iter,
						0, pShareeableAcount->getDescription().utf8_str(),
						1, pShareeableAcount,
						-1);
			gtk_widget_set_sensitive(m_wAccount, false);
	}
	else
	{
		for (std::vector<AccountHandler*>::const_iterator cit = pManager->getAccounts().begin(); cit != pManager->getAccounts().end(); cit++)
		{
			AccountHandler* pAccount = *cit;
			UT_continue_if_fail(pAccount);

			if (!pAccount->isOnline() || !pAccount->canManuallyStartSession())
				continue;

			gtk_list_store_append (store, &iter);
			gtk_list_store_set (store, &iter,
						0, pAccount->getDescription().utf8_str(),
						1, pAccount,
						-1);
		}
		gtk_widget_set_sensitive(m_wAccount, true);
	}
	m_pAccountModel = GTK_TREE_MODEL (store);
	gtk_combo_box_set_model(GTK_COMBO_BOX(m_wAccount), m_pAccountModel);

	// if we have at least one account handler, then make sure the first one is selected
	if (pManager->getRegisteredAccountHandlers().size() > 0)
	{
		gtk_combo_box_set_active(GTK_COMBO_BOX(m_wAccount), 0);
	}
	else
	{
		// nope, we don't have any account handler :'-(
		gtk_combo_box_set_active(GTK_COMBO_BOX(m_wAccount), -1);
	}
}
示例#11
0
void TCPAccountHandler::handleEvent(boost::shared_ptr<Session> session_ptr)
{
	UT_DEBUGMSG(("TCPAccountHandler::handleEvent()\n"));
	UT_return_if_fail(session_ptr);

	AbiCollabSessionManager* pManager = AbiCollabSessionManager::getManager();
	UT_return_if_fail(pManager);

	// make sure we have handled _all_ packets in the queue before checking
	// the disconnected status
	bool disconnected = !session_ptr->isConnected();
	_handleMessages(session_ptr);
	
	// check the connection status
	if (disconnected)
	{
		UT_DEBUGMSG(("Socket is not connected anymore!\n"));
		// drop all buddies that were on this connection
		std::map<TCPBuddyPtr, boost::shared_ptr<Session> >::iterator next;
		for (std::map<TCPBuddyPtr, boost::shared_ptr<Session> >::iterator it = m_clients.begin(); it != m_clients.end(); it = next)
		{
			next = it;
			next++;
		
			UT_continue_if_fail((*it).first);
			UT_continue_if_fail((*it).second);

			TCPBuddyPtr pB = (*it).first;
			
			if ((*it).second == session_ptr)
			{
				UT_DEBUGMSG(("Lost connection to %s buddy %s:%s\n", getProperty("server") == "" ? "client" : "server", pB->getAddress().c_str(), pB->getPort().c_str()));
				// drop this buddy from all sessions
				pManager->removeBuddy(pB, false);
				
				// erase the buddy <-> session mapping
				m_clients.erase(it);
				
				deleteBuddy(pB);
			}
		}

		// if we were connected to a server, then we are basically disconnected now
		if (getProperty("server") != "")
			disconnect();
	}

	// check other things here if needed...
}
示例#12
0
bool s_abicollab_join(AV_View* /*v*/, EV_EditMethodCallData* /*d*/)
{
	AbiCollabSessionManager* pManager = AbiCollabSessionManager::getManager();
	UT_return_val_if_fail(pManager, false);
	
	// Get the current view that the user is in.
	XAP_Frame *pFrame = XAP_App::getApp()->getLastFocussedFrame();
	// Get an Accounts dialog instance
	XAP_DialogFactory* pFactory = static_cast<XAP_DialogFactory *>(XAP_App::getApp()->getDialogFactory());
	UT_return_val_if_fail(pFactory, false);
	AP_Dialog_CollaborationJoin* pDialog = static_cast<AP_Dialog_CollaborationJoin*>(
				pFactory->requestDialog(AbiCollabSessionManager::getManager()->getDialogJoinId())
			);
	// Run the dialog
	pDialog->runModal(pFrame);
	// Handle the dialog outcome
	AP_Dialog_CollaborationJoin::tAnswer answer = pDialog->getAnswer();
	BuddyPtr pBuddy = pDialog->getBuddy();
	DocHandle* pDocHandle = pDialog->getDocHandle();
	pFactory->releaseDialog(pDialog);
	
	switch (answer)
	{
		case AP_Dialog_CollaborationJoin::a_OPEN:
			{
				UT_return_val_if_fail(pBuddy && pDocHandle, false);
				// Check if we have already joined this session. If so, then just
				// ignore the request. Otherwise actually join the session.
				AbiCollab* pSession = pManager->getSessionFromSessionId(pDocHandle->getSessionId());
				if (pSession)
				{
					UT_DEBUGMSG(("Already connected to session, just raising the associated frame\n"));

					// Just raise a frame that contains this session, instead of
					// opening the document again
					XAP_Frame* pFrameForSession = pManager->findFrameForSession(pSession);
					UT_return_val_if_fail(pFrameForSession, false);
					pFrameForSession->raise();
				}
				else
					pManager->joinSessionInitiate(pBuddy, pDocHandle);	
			}
			break;
		case AP_Dialog_CollaborationJoin::a_CANCEL:
			break;
	}	
	
	return true;
}
AbiCollab* AP_Dialog_CollaborationShare::_getActiveSession()
{
	AbiCollabSessionManager* pManager = AbiCollabSessionManager::getManager();
	UT_return_val_if_fail(pManager, NULL);

	XAP_Frame* pFrame = XAP_App::getApp()->getLastFocussedFrame();
	UT_return_val_if_fail(pFrame, NULL);

	PD_Document* pDoc = static_cast<PD_Document *>(pFrame->getCurrentDoc());
	UT_return_val_if_fail(pDoc, NULL);

	if (!pManager->isInSession(pDoc))
		return NULL;

	return pManager->getSession(pDoc);
}
示例#14
0
/*!
 * This virtual method is called from the AbiWord main tree upon doing a replace document with an attached
 * AbiCollab_Export connected to the document.
 *
 * Note: this is a really weird signal, coming from a PD_Document
 * Note: If anything, a Frame should emit this signal to its listeners
 */
void ABI_Collab_Export::setNewDocument(PD_Document * /*pDoc*/)
{
	UT_DEBUGMSG(("ABI_Collab_Export::setNewDocument()\n"));
	
	// inform the session manager to kill off this session, as that is the only
	// thing we can do if the document is replaced
	AbiCollabSessionManager* pManager = AbiCollabSessionManager::getManager();
	UT_return_if_fail(pManager);

	// WARNING: Don't do anything after this line, as the disconnectSession() call will
	// have destroyed ourselves (yes, that is ugly).
	pManager->disconnectSession(m_pAbiCollab);

	// FIXME: The AbiCollab destructor will unregister this object as a PD_Document listener,
	// while the PD_Document will also unregister us as soon as this function returns.
	// Unregistering the same object twice works, but it is ugly as hell. Fix this someday.
}
bool AP_Dialog_CollaborationShare::_populateShareState(BuddyPtr pBuddy)
{
	AbiCollabSessionManager* pManager = AbiCollabSessionManager::getManager();
	UT_return_val_if_fail(pManager, false);

	PD_Document *pDoc = static_cast<PD_Document*>(XAP_App::getApp()->getLastFocussedFrame()->getCurrentDoc());
	UT_return_val_if_fail(pDoc, false);

	if (!pManager->isInSession(pDoc))
	{
		AccountHandler* pHandler = pBuddy->getHandler();
		UT_return_val_if_fail(pHandler, false);
	
		return pHandler->defaultShareState(pBuddy);
	}

	return _inAcl(m_vAcl, pBuddy);
}
ConnectResult TelepathyAccountHandler::connect()
{
	UT_DEBUGMSG(("TelepathyAccountHandler::connect()\n"));

	AbiCollabSessionManager* pManager = AbiCollabSessionManager::getManager();
	UT_return_val_if_fail(pManager, CONNECT_FAILED);

	UT_return_val_if_fail(m_pTpClient == NULL, CONNECT_INTERNAL_ERROR);

	// inform telepathy that we can handle incoming AbiCollab tubes

	GError *error = NULL;
	TpDBusDaemon* dbus = tp_dbus_daemon_dup (&error);
	UT_return_val_if_fail(dbus, CONNECT_FAILED);

	m_pTpClient = tp_simple_handler_new(dbus,
					TRUE, FALSE, "AbiCollab", FALSE,
					handle_dbus_channel, this, NULL);

	tp_base_client_take_handler_filter(m_pTpClient,
					tp_asv_new (
						TP_PROP_CHANNEL_CHANNEL_TYPE, G_TYPE_STRING, TP_IFACE_CHANNEL_TYPE_DBUS_TUBE,
						TP_PROP_CHANNEL_TARGET_HANDLE_TYPE, G_TYPE_UINT, TP_HANDLE_TYPE_ROOM,
						TP_PROP_CHANNEL_TYPE_DBUS_TUBE_SERVICE_NAME, G_TYPE_STRING, INTERFACE,
						NULL
					)
				);

	if (!tp_base_client_register(m_pTpClient, &error))
	{
		UT_DEBUGMSG(("Error registering tube handler: %s", error->message));
		UT_ASSERT_HARMLESS(UT_SHOULD_NOT_HAPPEN);
	}

	UT_DEBUGMSG(("Tube handler setup, listening for incoming tubes...\n"));

	// we are connected now, time to start sending out messages (such as events)
	pManager->registerEventListener(this);
	// signal all listeners we are logged in
	AccountOnlineEvent event;
	pManager->signal(event);

	return CONNECT_SUCCESS;
}
TCPWin32AccountHandler::TCPWin32AccountHandler()
	: TCPAccountHandler(),
	m_pWin32Dialog(NULL),
	m_hInstance(NULL),
	m_hServerEntry(NULL),
	m_hPortEntry(NULL),
	m_hServerRadio(NULL),
	m_hJoinRadio(NULL),
	m_hServerLabel(NULL),
	m_hPortLabel(NULL),
	m_hAllowAllCheck(NULL),
	m_hAutoconnectCheck(NULL)
{
	AbiCollabSessionManager * pSessionManager = AbiCollabSessionManager::getManager();
	if (pSessionManager)
	{
		m_hInstance = pSessionManager->getInstance();
	}
}
void TelepathyAccountHandler::buddyDisconnected(TelepathyChatroomPtr pChatroom, TpHandle disconnected)
{
	UT_DEBUGMSG(("TelepathyAccountHandler::buddyDisconnected() - handle: %d\n", disconnected));
	UT_return_if_fail(pChatroom);

	AbiCollabSessionManager* pManager = AbiCollabSessionManager::getManager();
	UT_return_if_fail(pManager);

	DTubeBuddyPtr pBuddy = pChatroom->getBuddy(disconnected);
	bool isController = pChatroom->isController(pBuddy);

	pManager->removeBuddy(pBuddy, false);
	pChatroom->removeBuddy(disconnected);
	if (isController)
	{
		UT_DEBUGMSG(("The master buddy left; stopping the chatroom!\n"));
		pChatroom->stop();
	}
}
示例#19
0
bool XMPPAccountHandler::disconnect()
{
	UT_DEBUGMSG(("XMPPAccountHandler::disconnect()\n"));

	AbiCollabSessionManager* pManager = AbiCollabSessionManager::getManager();
	UT_return_val_if_fail(pManager, false);

	// we are disconnected now, no need to receive events anymore
	pManager->unregisterEventListener(this);

	tearDown();
	
	// signal all listeners we are logged out
	AccountOfflineEvent event;
	// TODO: fill the event
	AbiCollabSessionManager::getManager()->signal(event);
	
	return true;
}
Synchronizer::Synchronizer(boost::function<void ()>  signalhandler) // Win32 Implementation
	: m_signalhandler(signalhandler),
 	m_hWnd(0),
	m_bIsProcessing(false),
	m_iDeferredMessages(0),
	m_bIsDestroyed(NULL)
{
	UT_DEBUGMSG(("Synchronizer()\n"));
	AbiCollabSessionManager * pSessionManager = AbiCollabSessionManager::getManager();
	UT_return_if_fail(pSessionManager);

 	HINSTANCE hInstance = pSessionManager->getInstance();
 	UT_return_if_fail(hInstance);

	_registerWndClass();
	
	// HWND_MESSAGE as parent HWND is Win2k/xp/vista only - replaced with 0
	// (also HWND_MESSAGE doesn't compile in MinGW, weird bug.  --RP 8 August 2007)
	
	m_hWnd = CreateWindow(SYNC_CLASSNAME,
			"AbiCollab",
			0,
			CW_USEDEFAULT,
			SW_HIDE,
			CW_USEDEFAULT,
			CW_USEDEFAULT,
			HWND_MESSAGE,
			NULL,
			hInstance,
			(void *) this
		);
	UT_DEBUGMSG(("Created message window: HWND 0x%x\n", m_hWnd));
	switch ((INT_PTR)m_hWnd)
	{
		case NULL:
			UT_DEBUGMSG(("Win32 error: %d.\n", GetLastError()));
			break;
		default:
			sm_iMessageWindows++;
			break;
			// ok!
	};
}
示例#21
0
/*!
 * returns true if at least one account is online
 */
static bool s_any_accounts_online(bool bIncludeNonManualShareAccounts = true)
{
	AbiCollabSessionManager* pManager = AbiCollabSessionManager::getManager();
	UT_return_val_if_fail(pManager, false);
	
	const std::vector<AccountHandler *>& vecAccounts = pManager->getAccounts();
	
	for (UT_uint32 i = 0; i < vecAccounts.size(); i++)
	{
		AccountHandler* pHandler = vecAccounts[i];
		if (pHandler && pHandler->isOnline())
		{
			if (bIncludeNonManualShareAccounts)
				return true;
			if (pHandler->canManuallyStartSession())
				return true;
		}
	}
	return false;
}
void Synchronizer::_unregisterWndClass() // Win32-only
{
 	UT_DEBUGMSG(("Synchronizer::_unregisterWndClass()\n"));
 	UT_return_if_fail(sm_iClass);
 	
 	if (sm_iMessageWindows > 0)
  	{
 		UT_DEBUGMSG(("%d message windows still exist, skipping unregistering\n", sm_iMessageWindows));
 		return;
  	}
 	
 	AbiCollabSessionManager * pManager = AbiCollabSessionManager::getManager();
 	UT_return_if_fail(pManager);
 
 	HINSTANCE hInstance = pManager->getInstance();
 	UT_return_if_fail(hInstance);
 
 	UT_DEBUGMSG(("Unregistrating message window class\n"));
 	UT_return_if_fail(UnregisterClass(SYNC_CLASSNAME, hInstance));
 	sm_iClass = 0;
}
示例#23
0
bool TCPAccountHandler::disconnect()
{
	UT_DEBUGMSG(("TCPAccountHandler::disconnect()\n"));

	if (!m_bConnected)
		return true;

	AbiCollabSessionManager* pManager = AbiCollabSessionManager::getManager();
	UT_return_val_if_fail(pManager, false);
	
	_teardownAndDestroyHandler();
	m_bConnected = false;

	// signal all listeners we are logged out
	AccountOfflineEvent event;
	// TODO: fill the event
	AbiCollabSessionManager::getManager()->signal(event);
	// we are disconnected now, no need to sent out messages (such as events) anymore
	pManager->unregisterEventListener(this);	
	return true;
}
void AbiCollab::_shutdownAsMaster()
{
    UT_DEBUGMSG(("AbiCollab::_shutdownAsMaster()\n"));
    UT_return_if_fail(m_pController == BuddyPtr());
    UT_return_if_fail(!m_bProposedController);

    AbiCollabSessionManager* pManager = AbiCollabSessionManager::getManager();
    UT_return_if_fail(pManager);

    // the session takeover is complete; inform everyone that all session data
    // is flushed, and that everyone should talk to the new master from now on
    SessionFlushedPacket sfp(m_sId, m_pDoc->getDocUUIDString());
    for (std::map<BuddyPtr, std::string>::iterator it = m_vCollaborators.begin(); it != m_vCollaborators.end(); it++)
    {
        BuddyPtr pBuddy = (*it).first;
        UT_continue_if_fail(pBuddy);
        pBuddy->getHandler()->send(&sfp, pBuddy);
    }

    // session takeover is done as far as the leaving session contoller is concerned
    pManager->endAsyncOperation(this);
}
void AP_Win32Dialog_CollaborationAccounts::_populateWindowData()
{
	AbiCollabSessionManager* pManager = AbiCollabSessionManager::getManager();
	UT_return_if_fail(pManager);

	m_bPopulating = true;

	// clear out the old contents, if any
	ListView_DeleteAllItems(m_hAccountList);

	for (UT_uint32 i = 0; i < pManager->getAccounts().size(); i++)
	{
		AccountHandler* pAccount = pManager->getAccounts()[i];
		UT_continue_if_fail(pAccount);

		UT_Win32LocaleString sAccountText = AP_Win32App::s_fromUTF8ToWinLocale(pAccount->getDescription().utf8_str());
		UT_Win32LocaleString sAccountTypeText = AP_Win32App::s_fromUTF8ToWinLocale(pAccount->getDisplayType().utf8_str());

		// insert a new account record
		LVITEMW lviAccount;
		lviAccount.mask = LVIF_STATE | LVIF_IMAGE | LVIF_PARAM;
		lviAccount.state = 1;
		lviAccount.iItem = i;
		lviAccount.iSubItem = 0;
		lviAccount.lParam = (LPARAM)pAccount;
		SendMessageW(m_hAccountList, LVM_INSERTITEMW, 0, (LPARAM) &lviAccount);
		ListView_SetCheckState(m_hAccountList, i, pAccount->isOnline());
		lviAccount.iSubItem=1;
		lviAccount.pszText= const_cast<LPWSTR>(sAccountText.c_str());
		SendMessageW(m_hAccountList, LVM_SETITEMTEXTW, i, (LPARAM) &lviAccount);
		lviAccount.iSubItem=2;
		lviAccount.pszText= const_cast<LPWSTR>(sAccountTypeText.c_str());
		SendMessageW(m_hAccountList, LVM_SETITEMTEXTW, i, (LPARAM) &lviAccount);
	}

	_updateSelection();

	m_bPopulating = false;
}
void AccountHandler::handleMessage(Packet* pPacket, BuddyPtr pBuddy)
{
	UT_return_if_fail(pPacket);
	UT_return_if_fail(pBuddy);	

	AbiCollabSessionManager* pManager = AbiCollabSessionManager::getManager();
	UT_return_if_fail(pManager);
	
	//
	// handle the incoming packet: first check for a protocol error, then ask the 
	// session manager to handle it, then try to handle it ourselves
	//
	if (_handleProtocolError(pPacket, pBuddy) ||
		pManager->processPacket(*this, pPacket, pBuddy))
	{
		DELETEP(pPacket);
		return;
	}

	// it seems we need to handle the packet ourselves
	_handlePacket(pPacket, pBuddy);
	DELETEP(pPacket);
}
示例#27
0
bool s_abicollab_record(AV_View* /*v*/, EV_EditMethodCallData* /*d*/)
{
	UT_DEBUGMSG(("s_abicollab_record\n"));
	// this option only works in debug mode
	AbiCollabSessionManager* pManager = AbiCollabSessionManager::getManager();
	XAP_Frame *pFrame = XAP_App::getApp()->getLastFocussedFrame();
	UT_return_val_if_fail(pFrame, false);
	PD_Document* pDoc = static_cast<PD_Document *>(pFrame->getCurrentDoc());
	UT_return_val_if_fail(pDoc, false);
	
	// retrieve session
	AbiCollab* session = pManager->getSession( pDoc );
	if (session)
	{
		if (session->isRecording()) {
			session->stopRecording();
			UT_ASSERT(!session->isRecording());
		} else {
			session->startRecording( new DiskSessionRecorder( session ) );
			UT_ASSERT(session->isRecording());
		}
	}
	return true;
}
void AccountHandler::_handlePacket(Packet* packet, BuddyPtr buddy)
{
	// packet and buddy must always be set
	UT_return_if_fail(packet);
	UT_return_if_fail(buddy);
	
	// as must the session manager
	AbiCollabSessionManager* pManager = AbiCollabSessionManager::getManager();
	UT_return_if_fail(pManager);
	
	// manager didn't handle it, see what we can do
	switch (packet->getClassType()) 
	{			
		case PCT_JoinSessionRequestEvent:
		{
			JoinSessionRequestEvent* jse = static_cast<JoinSessionRequestEvent*>(packet);
			
			// lookup session
			AbiCollab* pSession = pManager->getSessionFromSessionId(jse->getSessionId());
			UT_return_if_fail(pSession);

            // check if this buddy is allowed to access this document
            // TODO: this should be done for every session packet, not just join session packets
            if (!hasAccess(pSession->getAcl(), buddy))
            {
                // we should only reach this point if someone is brute forcing trying
                // out session IDs while not being on the ACL. Ban this uses.
                UT_ASSERT_HARMLESS(UT_SHOULD_NOT_HAPPEN);
                return;
            }
		
			// lookup exporter
			ABI_Collab_Export* pExport = pSession->getExport();
			UT_return_if_fail(pExport);
			
			// lookup adjusts
			const UT_GenericVector<ChangeAdjust *>* pExpAdjusts = pExport->getAdjusts();
			UT_return_if_fail(pExpAdjusts);
		
			PD_Document* pDoc = pSession->getDocument();

			// add this author to the document if we don't recognize him
			UT_sint32 iAuthorId = -1;
			UT_UTF8String buddyDescriptor = buddy->getDescriptor();
			UT_GenericVector<pp_Author*> authors = pDoc->getAuthors();
			UT_DEBUGMSG(("Scanning %d authors to see if we recognize this buddy\n", authors.getItemCount()));
			for (UT_sint32 i = 0; i < authors.getItemCount(); i++)
			{
				pp_Author* pAuthor = authors.getNthItem(i);
				UT_continue_if_fail(pAuthor);

				const gchar* szDescriptor = NULL;
				pAuthor->getProperty("abicollab-descriptor", szDescriptor);
				if (!szDescriptor)
					continue;

				if (buddyDescriptor != szDescriptor)
					continue;

				// yay, we know this author!
				iAuthorId = pAuthor->getAuthorInt();
				UT_DEBUGMSG(("Found known author with descriptior %s, id %d!\n", buddyDescriptor.utf8_str(), iAuthorId));
				break;
			}
			
			if (iAuthorId == -1)
			{
				// we don't know this author yet, create a new author object for him
				iAuthorId = pDoc->findFirstFreeAuthorInt();
				pp_Author * pA = pDoc->addAuthor(iAuthorId);
				PP_AttrProp * pPA = pA->getAttrProp();
				pPA->setProperty("abicollab-descriptor", buddyDescriptor.utf8_str());
				pDoc->sendAddAuthorCR(pA);
				UT_DEBUGMSG(("Added a new author to the documument with descriptor %s, id %d\n", buddyDescriptor.utf8_str(), iAuthorId));
			}
			
			// serialize entire document into string
			JoinSessionRequestResponseEvent jsre(jse->getSessionId(), iAuthorId);
			if (AbiCollabSessionManager::serializeDocument(pDoc, jsre.m_sZABW, false /* no base64 */) == UT_OK)
			{
				// set more document properties
				jsre.m_iRev = pDoc->getCRNumber();
				jsre.m_sDocumentId = pDoc->getDocUUIDString();
				if (pDoc->getFilename())
					jsre.m_sDocumentName = UT_go_basename_from_uri(pDoc->getFilename());
				
				// send to buddy!
				send(&jsre, buddy);
				
				// add this buddy to the collaboration session
				pSession->addCollaborator(buddy);
			}
			break;
		}
		
		case PCT_JoinSessionRequestResponseEvent:
		{
			JoinSessionRequestResponseEvent* jsre = static_cast<JoinSessionRequestResponseEvent*>( packet );
			PD_Document* pDoc = 0;
			if (AbiCollabSessionManager::deserializeDocument(&pDoc, jsre->m_sZABW, false) == UT_OK)
			{
				if (pDoc)
				{
					// NOTE: we could adopt the same document name here, but i'd
					// rather not at the moment - MARCM
					pDoc->forceDirty();
					if (jsre->m_sDocumentName.size() > 0)
					{
						gchar* fname = g_strdup(jsre->m_sDocumentName.utf8_str());
						pDoc->setFilename(fname);
					}
					// The default ownership when joining is FALSE, as that seems 
					// to make sense for the generic case. The person sharing the 
					// document by default owns the document (and is thus allowed
					// to modify the ACL).
					pManager->joinSession(jsre->getSessionId(), pDoc, jsre->m_sDocumentId, jsre->m_iRev, jsre->getAuthorId(), buddy, this, false, NULL);
				}
				else 
				{
					UT_DEBUGMSG(("AccountHandler::_handlePacket() - deserializing document failed!\n"));
				}
			}
			break;
		}
		
		case PCT_GetSessionsEvent:
		{
			GetSessionsResponseEvent gsre;
			const UT_GenericVector<AbiCollab *> sessions = pManager->getSessions();
			for (UT_sint32 i = 0; i < sessions.getItemCount(); i++)
			{
				AbiCollab* pSession = sessions.getNthItem(i);
				if (pSession && pSession->isLocallyControlled())
				{
                    // check if the buddy has access to this session
                    if (!hasAccess(pSession->getAcl(), buddy))
                    {
                        UT_DEBUGMSG(("Buddy %s denied access to session %s by ALC\n", buddy->getDescriptor(true).utf8_str(), pSession->getSessionId().utf8_str()));
                        continue;
                    }

					const PD_Document * pDoc = pSession->getDocument();
                    UT_continue_if_fail(pDoc);

                    // determine name
					UT_UTF8String documentBaseName;
					if (pDoc->getFilename())
						documentBaseName = UT_go_basename_from_uri(pDoc->getFilename());
					// set session info
					gsre.m_Sessions[ pSession->getSessionId() ] = documentBaseName;
				}
			}
			send(&gsre, buddy);
			break;
		}
		
		case PCT_GetSessionsResponseEvent:
		{
			GetSessionsResponseEvent* gsre = static_cast<GetSessionsResponseEvent*>( packet );
			UT_GenericVector<DocHandle*> vDocHandles;
			for (std::map<UT_UTF8String,UT_UTF8String>::iterator it=gsre->m_Sessions.begin(); it!=gsre->m_Sessions.end(); ++it) {
				DocHandle* pDocHandle = new DocHandle((*it).first, (*it).second);
				vDocHandles.addItem(pDocHandle);
			}
			pManager->setDocumentHandles(buddy, vDocHandles);
			break;
		}
		
		default:
		{
			UT_DEBUGMSG(("Unhandled packet class: 0x%x\n", packet->getClassType()));
			UT_ASSERT_HARMLESS(UT_SHOULD_NOT_HAPPEN);
			break;
		}
	}
}
示例#29
0
ConnectResult TCPAccountHandler::connect()
{
	UT_DEBUGMSG(("TCPAccountHandler::connect()\n"));

	AbiCollabSessionManager* pManager = AbiCollabSessionManager::getManager();
	UT_return_val_if_fail(pManager, CONNECT_INTERNAL_ERROR);

	UT_return_val_if_fail(!m_pDelegator, CONNECT_INTERNAL_ERROR);
	UT_return_val_if_fail(!m_bConnected, CONNECT_ALREADY_CONNECTED);
	UT_return_val_if_fail(!m_thread, CONNECT_INTERNAL_ERROR);
	m_io_service.reset();
	m_thread = new asio::thread(boost::bind(&asio::io_service::run, &m_io_service));

	// set up the connection
	if (getProperty("server") == "")
	{
		UT_sint32 port = _getPort(getProperties());
		UT_DEBUGMSG(("Start accepting connections on port %d...\n", port));

		try
		{
			IOServerHandler* pDelegator = new IOServerHandler(port, 
						boost::bind(&TCPAccountHandler::_handleAccept, this, _1, _2),
						boost::bind(&TCPAccountHandler::handleEvent, this, _1), m_io_service);
			m_pDelegator = pDelegator;
			m_bConnected = true; // todo: ask it to the acceptor
			pDelegator->run();
		}
		catch (asio::system_error se)
		{
			UT_DEBUGMSG(("Failed to start accepting connections: %s\n", se.what()));
			_teardownAndDestroyHandler();
			return CONNECT_FAILED;
		}
		catch (...)
		{
			UT_DEBUGMSG(("Caught unhandled server exception!\n"));
			_teardownAndDestroyHandler();
			return CONNECT_FAILED;
		}
	}
	else
	{
		UT_DEBUGMSG(("Connecting to server %s on port %d...\n", getProperty("server").c_str(), _getPort(getProperties())));

		try
		{
			asio::ip::tcp::resolver resolver(m_io_service);
			asio::ip::tcp::resolver::query query(getProperty("server"), getProperty("port"));
			asio::ip::tcp::resolver::iterator iterator(resolver.resolve(query));

			bool connected = false;
			boost::shared_ptr<Session> session_ptr(new Session(m_io_service, boost::bind(&TCPAccountHandler::handleEvent, this, _1)));
			while (iterator != tcp::resolver::iterator())
			{
				try
				{
					UT_DEBUGMSG(("Attempting to connect...\n"));
					session_ptr->connect(iterator);
					UT_DEBUGMSG(("Connected!\n"));
					connected = true;
					break;
				}
				catch (asio::system_error se)
				{
					UT_DEBUGMSG(("Connection attempt failed: %s\n", se.what()));
					// make sure we close the socket after a failed attempt, as it
					// may have been opened by the connect() call.
					try { session_ptr->getSocket().close(); } catch(...) {}
				}
				iterator++;
			}

			if (!connected)
			{
				UT_DEBUGMSG(("Giving up to connecting to server!\n"));
				_teardownAndDestroyHandler();
				return CONNECT_FAILED;
			}

			session_ptr->asyncReadHeader();
			m_bConnected = true; // todo: ask it to the socket
			// Add a buddy
			TCPBuddyPtr pBuddy = boost::shared_ptr<TCPBuddy>(new TCPBuddy(this, 
						session_ptr->getRemoteAddress(),
						boost::lexical_cast<std::string>(session_ptr->getRemotePort())));
			addBuddy(pBuddy);
			m_clients.insert(std::pair<TCPBuddyPtr, boost::shared_ptr<Session> >(pBuddy, session_ptr));
		}
		catch (asio::system_error se)
		{
			UT_DEBUGMSG(("Failed to resolve %s:%d: %s\n", getProperty("server").c_str(), _getPort(getProperties()), se.what()));
			_teardownAndDestroyHandler();
			return CONNECT_FAILED;
		}
	}
	
	if (!m_bConnected)
		return CONNECT_FAILED;

	// we are connected now, time to start sending out messages (such as events)
	pManager->registerEventListener(this);
	// signal all listeners we are logged in
	AccountOnlineEvent event;
	// TODO: fill the event
	AbiCollabSessionManager::getManager()->signal(event);

	return CONNECT_SUCCESS;
}
bool AbiCollab::_handleSessionTakeover(AbstractSessionTakeoverPacket* pPacket, BuddyPtr collaborator)
{
    UT_DEBUGMSG(("AbiCollab::_handleSessionTakeover()\n"));
    UT_return_val_if_fail(pPacket, false);
    UT_return_val_if_fail(collaborator, false);

    AbiCollabSessionManager* pManager = AbiCollabSessionManager::getManager();
    UT_return_val_if_fail(pManager, false);

    switch (m_eTakeoveState)
    {
    case STS_NONE:
    {
        // we only accept a SessionTakeoverRequest or MasterChangeRequest packet
        UT_return_val_if_fail(pPacket->getClassType() == PCT_SessionTakeoverRequestPacket, false);
        // we can only allow such a packet from the controller
        UT_return_val_if_fail(m_pController == collaborator, false);

        // handle the SessionTakeoverRequestPacket packet
        m_pProposedController = BuddyPtr();
        m_vApprovedReconnectBuddies.clear();
        SessionTakeoverRequestPacket* strp = static_cast<SessionTakeoverRequestPacket*>(pPacket);
        m_bProposedController = strp->promote();
        if (m_bProposedController)
        {
            for (std::vector<std::string>::const_iterator cit = strp->getBuddyIdentifiers().begin(); cit != strp->getBuddyIdentifiers().end(); cit++)
                m_vApprovedReconnectBuddies[*cit] = false;
        }
        else
        {
            UT_return_val_if_fail(strp->getBuddyIdentifiers().size() == 1, false);
            BuddyPtr pBuddy = pManager->constructBuddy(strp->getBuddyIdentifiers()[0], collaborator);
            UT_return_val_if_fail(pBuddy, false);
            m_pProposedController = pBuddy;
        }

        // inform the master that we received the takeover request
        SessionTakeoverAckPacket stap(m_sId, m_pDoc->getDocUUIDString());
        collaborator->getHandler()->send(&stap, collaborator);

        m_eTakeoveState = STS_SENT_TAKEOVER_ACK;
        return true;
    }
    return false;
    case STS_SENT_TAKEOVER_REQUEST:
    {
        // we only accept SessionTakeoverAck packets
        UT_return_val_if_fail(pPacket->getClassType() == PCT_SessionTakeoverAckPacket, false);
        // we can only receive SessionTakeoverAck packets when we are the master
        UT_return_val_if_fail(!m_pController, false);
        // we should have a proposed master
        UT_return_val_if_fail(m_pProposedController, false);
        // a slave should only ack once
        UT_return_val_if_fail(!_hasAckedSessionTakeover(collaborator), false);

        // handle the SessionTakeoverAck packet
        m_mAckedSessionTakeoverBuddies[collaborator] = true;

        // check if every slave has acknowledged the session takeover
        // TODO: handle dropouts
        if (m_vCollaborators.size() == 1 ||
                m_mAckedSessionTakeoverBuddies.size() == m_vCollaborators.size())
        {
            // ... our tour of duty is done
            _shutdownAsMaster();
            m_eTakeoveState = STS_NONE;
            return true;
        }
    }

    return true;
    case STS_SENT_TAKEOVER_ACK:
        // we only accept a SessionFlushed or SessionReconnectRequest packet
        UT_return_val_if_fail(
            pPacket->getClassType() == PCT_SessionFlushedPacket ||
            pPacket->getClassType() == PCT_SessionReconnectRequestPacket,
            false
        );

        if (pPacket->getClassType() == PCT_SessionReconnectRequestPacket)
        {
            // we only accept a SessionReconnectRequest when we are the proposed master
            UT_return_val_if_fail(m_bProposedController, false);

            // we only allow an incoming SessionReconnectRequest packet from a buddy
            // that is in the buddy list we received from the master, and we didn't receive
            // such a packet from him before
            bool allow = false;
            for (std::map<std::string, bool>::iterator it = m_vApprovedReconnectBuddies.begin(); it != m_vApprovedReconnectBuddies.end(); it++)
            {
                // TODO: is it a good idea to compare descriptors with full session information?
                if ((*it).first == collaborator->getDescriptor(true) && (*it).second == false)
                {
                    (*it).second = true;
                    allow = true;
                    break;
                }
            }
            UT_return_val_if_fail(allow, false);

            // handle the SessionReconnectRequest packet
            addCollaborator(collaborator);
            _checkRestartAsMaster();

            return true;
        }
        else if (pPacket->getClassType() == PCT_SessionFlushedPacket)
        {
            // we can only allow a SessionFlushed packet from the controller
            UT_return_val_if_fail(m_pController == collaborator, false);

            // handle the SessionFlushed packet
            m_bSessionFlushed = true;

            if (m_bProposedController)
            {
                // as far we we're concerned now, the old master is dead
                _becomeMaster();

                _checkRestartAsMaster();
                return true;
            }
            else
            {
                // as far we we're concerned now, the old master is dead
                _switchMaster();

                // inform the new master that we want to rejoin the session
                SessionReconnectRequestPacket srrp(m_sId, m_pDoc->getDocUUIDString());
                m_pProposedController->getHandler()->send(&srrp, m_pProposedController);

                m_eTakeoveState = STS_SENT_SESSION_RECONNECT_REQUEST;
            }

            return true;
        }

        return false;
    case STS_SENT_SESSION_RECONNECT_REQUEST:
    {
        // we only accept a SessionReconnectAck packet
        UT_return_val_if_fail(pPacket->getClassType() == PCT_SessionReconnectAckPacket, false);
        // we only accept said packet when we are a slave
        UT_return_val_if_fail(m_pController, false);
        // we only accept said packet when we are not the proposed master
        UT_return_val_if_fail(!m_bProposedController, false);
        // we only accept said packet from the proposed master
        UT_return_val_if_fail(m_pProposedController == collaborator, false);

        // handle the SessionReconnectAck packet
        SessionReconnectAckPacket* srap = static_cast<SessionReconnectAckPacket*>(pPacket);
        // Nuke the current collaboration state, and restart with the
        // given revision from the proposed master
        UT_return_val_if_fail(_restartAsSlave(srap->getDocUUID(), srap->getRev()), false);
    }
    return true;
    default:
        UT_ASSERT_HARMLESS(UT_SHOULD_NOT_HAPPEN);
        break;
    }

    return false;
}