예제 #1
0
int
CCBServer::HandleRequestDisconnect( Stream * /*stream*/ )
{
	CCBServerRequest *request = (CCBServerRequest *)daemonCore->GetDataPtr();
	RemoveRequest( request );
	return KEEP_STREAM;
}
예제 #2
0
void
CCBServer::RemoveTarget( CCBTarget *target )
{
		// hang up on all requests for this target
	HashTable<CCBID,CCBServerRequest *> *trequests;
	while( (trequests = target->getRequests()) ) {
		CCBServerRequest *request = NULL;
		trequests->startIterations();
		if( trequests->iterate(request) ) {
			RemoveRequest( request );
			// note that trequests may point to a deleted hash table
			// at this point, so do not reference it anymore
		}
		else {
			break;
		}
	}

	if( m_targets.remove(target->getCCBID()) != 0 ) {
		EXCEPT("CCB: failed to remove target ccbid=%lu, %s",
			   target->getCCBID(), target->getSock()->peer_description());
	}

	dprintf(D_FULLDEBUG,"CCB: unregistered target daemon %s with ccbid %lu\n",
			target->getSock()->peer_description(),
			target->getCCBID());

	delete target;
}
예제 #3
0
void CServerBrowser::Set(const NETADDR &Addr, int Type, int Token, const CServerInfo *pInfo)
{
	CServerEntry *pEntry = 0;
	if(Type == IServerBrowser::SET_MASTER_ADD)
	{
		if(m_ServerlistType != IServerBrowser::TYPE_INTERNET)
			return;

		if(!Find(Addr))
		{
			pEntry = Add(Addr);
			QueueRequest(pEntry);
		}
	}
	else if(Type == IServerBrowser::SET_FAV_ADD)
	{
		if(m_ServerlistType != IServerBrowser::TYPE_FAVORITES)
			return;

		if(!Find(Addr))
		{
			pEntry = Add(Addr);
			QueueRequest(pEntry);
		}
	}
	else if(Type == IServerBrowser::SET_RECENT)
	{
		if(m_ServerlistType != IServerBrowser::TYPE_RECENT)
			return;

		if(!Find(Addr))
		{
			pEntry = Add(Addr);
			QueueRequest(pEntry);
		}
	}
	else if(Type == IServerBrowser::SET_TOKEN)
	{
		if(Token != m_CurrentToken)
			return;

		pEntry = Find(Addr);
		if(!pEntry)
			pEntry = Add(Addr);
		if(pEntry)
		{
			SetInfo(pEntry, *pInfo);
			if(m_ServerlistType == IServerBrowser::TYPE_LAN)
				pEntry->m_Info.m_Latency = min(static_cast<int>((time_get()-m_BroadcastTime)*1000/time_freq()), 999);
			else
				pEntry->m_Info.m_Latency = min(static_cast<int>((time_get()-pEntry->m_RequestTime)*1000/time_freq()), 999);
			RemoveRequest(pEntry);
		}
	}

	Sort();
}
예제 #4
0
NS_IMETHODIMP
nsGeolocationRequest::Cancel()
{
  NotifyError(nsIDOMGeoPositionError::PERMISSION_DENIED);

  // remove ourselves from the locators callback lists.
  mLocator->RemoveRequest(this);
  return NS_OK;
}
//---------------------------------------------------------
/// SendResponse
///
/// Sends the response either over sockets or shared memory
///
/// \param requestID the requestID to send the response to
/// \param cpsMimeType the mimetype to send the response as
/// \param cpsResponse the response to send
/// \param uResponseSize the size of the response being sent
/// \param bStreaming indicates that the response it to a streaming request
///
/// \return true if the response is 'sent' correctly; false otherwise
//---------------------------------------------------------
bool SendResponse(CommunicationID requestID, const char* cpsMimeType, const char* cpsResponse, unsigned int uResponseSize, bool bStreaming)
{
    // find out if this is a streaming response
    if (bStreaming)
    {
        Log(logTRACE, "Sending response over socket\n");
        // this is a streaming response
        // use the socket for comms

        return SendMimeResponse(requestID, cpsMimeType, cpsResponse, uResponseSize);
    }

    // use Shared memory if this is not a streaming response
    if (smLockPut("PLUGINS_TO_GPS", sizeof(requestID) + ((unsigned long) strlen(cpsMimeType) * sizeof(const char)) + uResponseSize, 3) == false)
    {
        Log(logASSERT, "Not enough space in shared memory for response.\n");
        return false;
    }

    NamedSemaphore semaphore;
    bool opened = semaphore.Open("PLUGINS_TO_GPS_SEMAPHORE");

    if (opened)
    {
        if (semaphore.Signal() == false)
        {
            Log(logWARNING, "Failed to signal PLUGINS_TO_GPS_SEMAPHORE. Response may be lost. Error is %d, Previous count is 0\n", osGetLastSystemError());
        }

        semaphore.Close();
    }
    else
    {
        Log(logWARNING, "Failed to open PLUGINS_TO_GPS_SEMAPHORE. Response may be delayed.\n");
    }

    bool bResult = (smPut("PLUGINS_TO_GPS", &requestID, sizeof(requestID)) &&
                    smPut("PLUGINS_TO_GPS", (void*)cpsMimeType, (unsigned long) strlen(cpsMimeType) * sizeof(const char)) &&
                    smPut("PLUGINS_TO_GPS", (void*)cpsResponse, uResponseSize));

    smUnlockPut("PLUGINS_TO_GPS");

    if (bResult == false)
    {
        Log(logASSERT, "Failed to put part of the response into shared memory\n");
    }
    else
    {
        // remove the request
        RemoveRequest(requestID);
    }

    return bResult;
}
예제 #6
0
void
CCBServer::RequestFinished( CCBServerRequest *request, bool success, char const *error_msg )
{
	RequestReply(
		request->getSock(),
		success,
		error_msg,
		request->getRequestID(),
		request->getTargetCCBID() );

	RemoveRequest( request );
}
예제 #7
0
void AddrInfoResolver::HandleLoop()
{
    if (!requests_.empty())
    {
        while (true)
        {
            auto resolved = resolved_.TryRecv();
            if (!resolved)
                break;

            auto request = *resolved;
            HandleResolve(*request);
            RemoveRequest(request);
        }
    }
}
예제 #8
0
NS_IMETHODIMP
nsGeolocationRequest::Notify(nsITimer* aTimer)
{
  // If we haven't gotten an answer from the geolocation
  // provider yet, cancel the request.  Same logic as
  // ::Cancel, just a different error
  
  if (!mHasSentData) {
    NotifyError(nsIDOMGeoPositionError::TIMEOUT);
    // remove ourselves from the locator's callback lists.
    mLocator->RemoveRequest(this);
  }

  mTimeoutTimer = nsnull;
  return NS_OK;
}
CommunicationID CreateRequest(HTTPRequestHeader* pRequest, bool bReceivedOverSocket)
{
    // protect the maps from being changed by other threads using the mutex
    ScopeLock lock(s_mutex);

    CommunicationID requestID = CommunicationID(pRequest->GetClientSocket());

    pRequest->SetReceivedOverSocket(bReceivedOverSocket);

    if (g_requestMap.find(requestID) != g_requestMap.end())
    {
        Log(logWARNING, "RequestID %u already exists from request: %s\n", requestID, pRequest->GetUrl());
        // Remove the pre-existing request (required to cleanup memory).
        RemoveRequest(requestID);
    }

    g_requestMap[requestID] = pRequest;

    return requestID;
}
void MediaSystemResourceService::ReleaseResource(
    media::MediaSystemResourceManagerParent* aParent, uint32_t aId,
    MediaSystemResourceType aResourceType) {
  MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
  MOZ_ASSERT(aParent);

  if (mDestroyed) {
    return;
  }

  MediaSystemResource* resource =
      mResources.Get(static_cast<uint32_t>(aResourceType));

  if (!resource || resource->mResourceCount == 0) {
    // Resource does not exit
    return;
  }
  RemoveRequest(aParent, aId, aResourceType);
  UpdateRequests(aResourceType);
}
//-----------------------------------------------------------------------------
bool MakeResponse(CommunicationID requestID, Response** ppResponse)
{
    // protect the maps from being changed by other threads using the mutex
    ScopeLock lock(s_mutex);

    PsAssert(ppResponse != NULL);

    // first see if we already have this ID as a streaming response
    ResponseMap::iterator iterResponse = g_streamingResponseMap.find(requestID);

    if (iterResponse != g_streamingResponseMap.end())
    {
        *ppResponse = iterResponse->second;
        return true;
    }

    // otherwise we need to create a new response based on the original request
    // so get the request
    RequestMap::iterator iterRequest = g_requestMap.find(requestID);

    if (iterRequest == g_requestMap.end())
    {
        // the original request couldn't be found, so return failure
        return false;
    }

    // need to create a new response
    if (PsNew(*ppResponse) == false)
    {
        return false;
    }

    HTTPRequestHeader* pRequest = iterRequest->second;
    PsAssert(pRequest != NULL);

    if (pRequest->GetReceivedOverSocket() == true)
    {
        (*ppResponse)->client_socket = pRequest->GetClientSocket();
    }
    else
    {
#if defined (_WIN32)
        (*ppResponse)->client_socket = NetSocket::CreateFromDuplicate(pRequest->GetProtoInfo());
#else
        // create a new socket and connect to the streamSocket on the server
        (*ppResponse)->client_socket = NetSocket::Create();

        if ((*ppResponse)->client_socket != NULL)
        {
            osPortAddress portAddress((unsigned short)pRequest->GetPort());
            (*ppResponse)->client_socket->Connect(portAddress);
        }

#endif
    }

    if ((*ppResponse)->client_socket == NULL)
    {
        int Err = NetSocket::LastError();
        Log(logERROR, "Could not create socket: NetSocket failed with error: %ld\n", Err);
        return false;
    }

    // see if this should be added as a streaming response
    gtASCIIString strUrl(pRequest->GetUrl());
    int32 iStream = strUrl.find(STR_STREAM_TOKEN);

    if (iStream >= 0)
    {
        const char* pBuf = strUrl.asCharArray();
        const char* pRate = &pBuf[ iStream + strlen(STR_STREAM_TOKEN)];
        unsigned int uRate = 0;

        // try to get the rate from the command;
        if (sscanf_s(pRate, "%u", &uRate) < 1)
        {
            // default to max rate
            uRate = COMM_MAX_STREAM_RATE;
        }

        // set the response as streaming with the specified rate
        (*ppResponse)->m_bStreamingEnabled = true;
        (*ppResponse)->m_dwMaxStreamsPerSecond = uRate;
        g_streamingResponseMap[ requestID ] = *ppResponse;
    }
    else
    {
        // streaming requests need to be kept around so that
        // additional responses can be directed to the right place,
        // HOWEVER, non-streaming requests only get a single response
        // and we just created the response for it, so it is safe
        // to remove the request from the requestMap. This will
        // help keep communication quick as the number of incoming
        // requests grows.
        RemoveRequest(requestID);
    }

    return true;
}
예제 #12
0
NS_IMETHODIMP
nsLoadGroup::Cancel(nsresult status)
{
    NS_ASSERTION(NS_FAILED(status), "shouldn't cancel with a success code");
    nsresult rv;
    PRUint32 count = mRequests.entryCount;

    nsAutoTArray<nsIRequest*, 8> requests;

    PL_DHashTableEnumerate(&mRequests, AppendRequestsToArray,
                           static_cast<nsTArray<nsIRequest*> *>(&requests));

    if (requests.Length() != count) {
        for (PRUint32 i = 0, len = requests.Length(); i < len; ++i) {
            NS_RELEASE(requests[i]);
        }

        return NS_ERROR_OUT_OF_MEMORY;
    }

    // set the load group status to our cancel status while we cancel 
    // all our requests...once the cancel is done, we'll reset it...
    //
    mStatus = status;

    // Set the flag indicating that the loadgroup is being canceled...  This
    // prevents any new channels from being added during the operation.
    //
    mIsCanceling = PR_TRUE;

    nsresult firstError = NS_OK;

    while (count > 0) {
        nsIRequest* request = requests.ElementAt(--count);

        NS_ASSERTION(request, "NULL request found in list.");

        RequestMapEntry *entry =
            static_cast<RequestMapEntry *>
                       (PL_DHashTableOperate(&mRequests, request,
                                                PL_DHASH_LOOKUP));

        if (PL_DHASH_ENTRY_IS_FREE(entry)) {
            // |request| was removed already

            NS_RELEASE(request);

            continue;
        }

#if defined(PR_LOGGING)
        nsCAutoString nameStr;
        request->GetName(nameStr);
        LOG(("LOADGROUP [%x]: Canceling request %x %s.\n",
             this, request, nameStr.get()));
#endif

        //
        // Remove the request from the load group...  This may cause
        // the OnStopRequest notification to fire...
        //
        // XXX: What should the context be?
        //
        (void)RemoveRequest(request, nsnull, status);

        // Cancel the request...
        rv = request->Cancel(status);

        // Remember the first failure and return it...
        if (NS_FAILED(rv) && NS_SUCCEEDED(firstError))
            firstError = rv;

        NS_RELEASE(request);
    }

#if defined(DEBUG)
    NS_ASSERTION(mRequests.entryCount == 0, "Request list is not empty.");
    NS_ASSERTION(mForegroundCount == 0, "Foreground URLs are active.");
#endif

    mStatus = NS_OK;
    mIsCanceling = PR_FALSE;

    return firstError;
}
예제 #13
0
void CServerBrowser::Update()
{
	int64 Timeout = time_freq();
	int64 Now = time_get();
	int Count;
	CServerEntry *pEntry, *pNext;

	// do server list requests
	if(m_NeedRefresh && !m_pMasterServer->IsRefreshing())
	{
		NETADDR Addr;
		CNetChunk Packet;
		int i;

		m_NeedRefresh = 0;

		mem_zero(&Packet, sizeof(Packet));
		Packet.m_ClientID = -1;
		Packet.m_Flags = NETSENDFLAG_CONNLESS;
		Packet.m_DataSize = sizeof(SERVERBROWSE_GETLIST);
		Packet.m_pData = SERVERBROWSE_GETLIST;

		for(i = 0; i < IMasterServer::MAX_MASTERSERVERS; i++)
		{
			Addr = m_pMasterServer->GetAddr(i);
			if(!Addr.ip[0] && !Addr.ip[1] && !Addr.ip[2] && !Addr.ip[3])
				continue;

			Packet.m_Address = Addr;
			m_pNetClient->Send(&Packet);
		}

		if(g_Config.m_Debug)
			dbg_msg("client", "requesting server list");
	}

	// do timeouts
	pEntry = m_pFirstReqServer;
	while(1)
	{
		if(!pEntry) // no more entries
			break;

		pNext = pEntry->m_pNextReq;

		if(pEntry->m_RequestTime && pEntry->m_RequestTime+Timeout < Now)
		{
			// timeout
			RemoveRequest(pEntry);
			m_NumRequests--;
		}

		pEntry = pNext;
	}

	// do timeouts
	pEntry = m_pFirstReqServer;
	Count = 0;
	while(1)
	{
		if(!pEntry) // no more entries
			break;

		// no more then 10 concurrent requests
		if(Count == g_Config.m_BrMaxRequests)
			break;

		if(pEntry->m_RequestTime == 0)
			RequestImpl(pEntry->m_Addr, pEntry);

		Count++;
		pEntry = pEntry->m_pNextReq;
	}

	// check if we need to resort
	// TODO: remove the str_comp
	if(m_Sorthash != SortHash() || str_comp(m_aFilterString, g_Config.m_BrFilterString) != 0 || str_comp(m_aFilterGametypeString, g_Config.m_BrFilterGametype) != 0)
		Sort();
}
예제 #14
0
void CServerBrowser::Update(bool ForceResort)
{
	int64 Timeout = time_freq();
	int64 Now = time_get();
	int Count;
	CServerEntry *pEntry, *pNext;

	// do server list requests
	if(m_NeedRefresh && !m_pMasterServer->IsRefreshing())
	{
		NETADDR Addr;
		CNetChunk Packet;
		int i;

		m_NeedRefresh = 0;

		mem_zero(&Packet, sizeof(Packet));
		Packet.m_ClientID = -1;
		Packet.m_Flags = NETSENDFLAG_CONNLESS;
		Packet.m_DataSize = sizeof(SERVERBROWSE_GETLIST);
		Packet.m_pData = SERVERBROWSE_GETLIST;

		for(i = 0; i < IMasterServer::MAX_MASTERSERVERS; i++)
		{
			if(!m_pMasterServer->IsValid(i))
				continue;

			Addr = m_pMasterServer->GetAddr(i);
			Packet.m_Address = Addr;
			m_pNetClient->Send(&Packet);
		}

		if(g_Config.m_Debug)
			m_pConsole->Print(IConsole::OUTPUT_LEVEL_DEBUG, "client_srvbrowse", "requesting server list");
	}

	// do timeouts
	pEntry = m_pFirstReqServer;
	while(1)
	{
		if(!pEntry) // no more entries
			break;

		pNext = pEntry->m_pNextReq;

		if(pEntry->m_RequestTime && pEntry->m_RequestTime+Timeout < Now)
		{
			// timeout
			RemoveRequest(pEntry);
		}

		pEntry = pNext;
	}

	// do timeouts
	pEntry = m_pFirstReqServer;
	Count = 0;
	while(1)
	{
		if(!pEntry) // no more entries
			break;

		// no more then 10 concurrent requests
		if(Count == g_Config.m_BrMaxRequests)
			break;

		if(pEntry->m_RequestTime == 0)
			RequestImpl(pEntry->m_Addr, pEntry);

		Count++;
		pEntry = pEntry->m_pNextReq;
	}

	// check if we need to resort
	if(m_Sorthash != SortHash() || ForceResort)
		Sort();
}
예제 #15
0
NS_IMETHODIMP
nsLoadGroup::Cancel(nsresult status)
{
    MOZ_ASSERT(NS_IsMainThread());

    NS_ASSERTION(NS_FAILED(status), "shouldn't cancel with a success code");
    nsresult rv;
    uint32_t count = mRequests.EntryCount();

    AutoTArray<nsIRequest*, 8> requests;

    if (!AppendRequestsToArray(&mRequests, &requests)) {
        return NS_ERROR_OUT_OF_MEMORY;
    }

    // set the load group status to our cancel status while we cancel 
    // all our requests...once the cancel is done, we'll reset it...
    //
    mStatus = status;

    // Set the flag indicating that the loadgroup is being canceled...  This
    // prevents any new channels from being added during the operation.
    //
    mIsCanceling = true;

    nsresult firstError = NS_OK;

    while (count > 0) {
        nsIRequest* request = requests.ElementAt(--count);

        NS_ASSERTION(request, "NULL request found in list.");

        if (!mRequests.Search(request)) {
            // |request| was removed already
            NS_RELEASE(request);
            continue;
        }

        if (MOZ_LOG_TEST(gLoadGroupLog, LogLevel::Debug)) {
            nsAutoCString nameStr;
            request->GetName(nameStr);
            LOG(("LOADGROUP [%x]: Canceling request %x %s.\n",
                 this, request, nameStr.get()));
        }

        //
        // Remove the request from the load group...  This may cause
        // the OnStopRequest notification to fire...
        //
        // XXX: What should the context be?
        //
        (void)RemoveRequest(request, nullptr, status);

        // Cancel the request...
        rv = request->Cancel(status);

        // Remember the first failure and return it...
        if (NS_FAILED(rv) && NS_SUCCEEDED(firstError))
            firstError = rv;

        NS_RELEASE(request);
    }

#if defined(DEBUG)
    NS_ASSERTION(mRequests.EntryCount() == 0, "Request list is not empty.");
    NS_ASSERTION(mForegroundCount == 0, "Foreground URLs are active.");
#endif

    mStatus = NS_OK;
    mIsCanceling = false;

    return firstError;
}
예제 #16
0
파일: OSPGraph.cpp 프로젝트: list-man/osp
HRESULT COSPBackgroundRequest::ProcessRequest(COSPGraph* pGraph)
{
	COMMAND_ID cmd = RemoveRequest();
	switch (cmd)
	{
	case RID_GRAPHCREATION:
		pGraph->CreateFilterGraph(&m_spGraphBuilder);
		break;
	case RID_GRAPHDESTRUCTION:
		break;
	case RID_ASYNCOPEN:
		{
			pGraph->DoNotifyGraphStateChange(sgsOpening);
			m_requestResult = pGraph->DoRender(m_spGraphBuilder, m_url.c_str());
			if (SUCCEEDED(m_requestResult))
			{
				pGraph->DoNotifyGraphStateChange(sgsOpen);
			}
		}
		break;
	case RID_CLOSE:
		{
			pGraph->DoNotifyGraphStateChange(sgsClosing);
			m_requestResult = m_requestResult = pGraph->InternelClose();
			if (SUCCEEDED(m_requestResult))
			{
				pGraph->DoNotifyGraphStateChange(sgsClose);
			}
		}
		break;
	case RID_PLAY:
		{
			pGraph->DoNotifyGraphStateChange(sgsRunning);
			m_requestResult = pGraph->InternelPlay();
			if (SUCCEEDED(m_requestResult))
			{
				pGraph->DoNotifyGraphStateChange(sgsRun);
			}
		}
		break;
	case RID_PAUSE:
		{
			pGraph->DoNotifyGraphStateChange(sgsPausing);
			m_requestResult = pGraph->InternelPause();
			if (SUCCEEDED(m_requestResult))
			{
				pGraph->DoNotifyGraphStateChange(sgsPause);
			}
		}
		break;
	case RID_STOP:
		{
			pGraph->DoNotifyGraphStateChange(sgsStopping);
			m_requestResult = pGraph->InternelStop();
			if (SUCCEEDED(m_requestResult))
			{
				pGraph->DoNotifyGraphStateChange(sgsStop);
			}
		}
		break;
	default:
		break;
	}

	return S_OK;
}
예제 #17
0
void CServerBrowser::Update(bool ForceResort)
{
	int64 Timeout = time_freq();
	int64 Now = time_get();
	int Count;
	CServerEntry *pEntry, *pNext;

	// do server list requests
	if(m_NeedRefresh && !m_pMasterServer->IsRefreshing())
	{
		CNetChunk Packet;

		m_NeedRefresh = 0;

		mem_zero(&Packet, sizeof(Packet));
		Packet.m_ClientID = -1;
		Packet.m_Flags = NETSENDFLAG_CONNLESS;
		Packet.m_DataSize = sizeof(SERVERBROWSE_GETLIST);
		Packet.m_pData = SERVERBROWSE_GETLIST;

		for(int i = 0; i < IMasterServer::MAX_MASTERSERVERS; i++)
		{
			if(!m_pMasterServer->IsValid(i))
				continue;

			Packet.m_Address = m_pMasterServer->GetAddr(i);
			m_pNetClient->Send(&Packet);
		}

		if(g_Config.m_Debug)
			m_pConsole->Print(IConsole::OUTPUT_LEVEL_DEBUG, "client_srvbrowse", "requesting server list");
	}

	// do timeouts
	pEntry = m_pFirstReqServer;
	while(1)
	{
		if(!pEntry) // no more entries
			break;

		pNext = pEntry->m_pNextReq;

		if(pEntry->m_RequestTime && pEntry->m_RequestTime+Timeout < Now)
		{
			// timeout
			RemoveRequest(pEntry);
		}

		pEntry = pNext;
	}

	// do timeouts
	pEntry = m_pFirstReqServer;
	Count = 0;
	while(1)
	{
		if(!pEntry) // no more entries
			break;

		// no more then 10 concurrent requests
		if(Count == g_Config.m_BrMaxRequests)
			break;

		if(pEntry->m_RequestTime == 0)
			RequestImpl(pEntry->m_Addr, pEntry);

		Count++;
		pEntry = pEntry->m_pNextReq;
	}

	// update favorite
	const NETADDR *pFavAddr = m_ServerBrowserFavorites.UpdateFavorites();
	if(pFavAddr)
	{
		for(int i = 0; i < NUM_TYPES; ++i)
		{
			CServerEntry *pEntry = Find(i, *pFavAddr);
			if(pEntry)
				pEntry->m_Info.m_Favorite = 1;

			if(i == m_ActServerlistType)
				ForceResort = true;
		}
	}

	m_ServerBrowserFilter.Sort(m_aServerlist[m_ActServerlistType].m_ppServerlist, m_aServerlist[m_ActServerlistType].m_NumServers, ForceResort ? CServerBrowserFilter::RESORT_FLAG_FORCE : 0);
}
예제 #18
0
void
CCBServer::HandleRequestResultsMsg( CCBTarget *target )
{
		// Reply from target daemon about whether it succeeded in
		// connecting to the requested client.

	Sock *sock = target->getSock();

	ClassAd msg;
	sock->decode();
	if( !msg.initFromStream( *sock ) || !sock->end_of_message() ) {
			// disconnect
		dprintf(D_FULLDEBUG,
				"CCB: received disconnect from target daemon %s "
				"with ccbid %lu.\n",
				sock->peer_description(), target->getCCBID() );
		RemoveTarget( target );
		return;
	}

	int command = 0;
	if( msg.LookupInteger( ATTR_COMMAND, command ) && command == ALIVE ) {
		SendHeartbeatResponse( target );
		return;
	}

	target->decPendingRequestResults();

	bool success = false;
	MyString error_msg;
	MyString reqid_str;
	CCBID reqid;
	MyString connect_id;
	msg.LookupBool( ATTR_RESULT, success );
	msg.LookupString( ATTR_ERROR_STRING, error_msg );
	msg.LookupString( ATTR_REQUEST_ID, reqid_str );
	msg.LookupString( ATTR_CLAIM_ID, connect_id );

	if( !CCBIDFromString( reqid, reqid_str.Value() ) ) {
		MyString msg_str;
		msg.sPrint(msg_str);
		dprintf(D_ALWAYS,
				"CCB: received reply from target daemon %s with ccbid %lu "
				"without a valid request id: %s\n",
				sock->peer_description(),
				target->getCCBID(),
				msg_str.Value());
		RemoveTarget( target );
		return;
	}

	CCBServerRequest *request = GetRequest( reqid );
	if( request && request->getSock()->readReady() ) {
		// Request socket must have just closed.  To avoid noise in
		// logs when we fail to write to it, delete the request now.
		RemoveRequest( request );
		request = NULL;
	}

	char const *request_desc = "(client which has gone away)";
	if( request ) {
		request_desc = request->getSock()->peer_description();
	}

	if( success ) {
		dprintf(D_FULLDEBUG,"CCB: received 'success' from target daemon %s "
				"with ccbid %lu for "
				"request %s from %s.\n",
				sock->peer_description(),
				target->getCCBID(),
				reqid_str.Value(),
				request_desc);
	}
	else {
		dprintf(D_FULLDEBUG,"CCB: received error from target daemon %s "
				"with ccbid %lu for "
				"request %s from %s: %s\n",
				sock->peer_description(),
				target->getCCBID(),
				reqid_str.Value(),
				request_desc,
				error_msg.Value());
	}

	if( !request ) {
		if( success ) {
				// expected: the client has gone away; it got what it wanted
			return;
		}
		dprintf( D_FULLDEBUG,
				 "CCB: client for request %s to target daemon %s with ccbid "
				 "%lu disappeared before receiving error details.\n",
				 reqid_str.Value(),
				 sock->peer_description(),
				 target->getCCBID());
		return;
	}
	if( connect_id != request->getConnectID() ) {
		MyString msg_str;
		msg.sPrint(msg_str);
		dprintf( D_FULLDEBUG,
				 "CCB: received wrong connect id (%s) from target daemon %s "
				 "with ccbid %lu for "
				 "request %s\n",
				 connect_id.Value(),
				 sock->peer_description(),
				 target->getCCBID(),
				 reqid_str.Value());
		RemoveTarget( target );
		return;
	}

	RequestFinished( request, success, error_msg.Value() );
}
예제 #19
0
void CServerBrowser::Set(const NETADDR &Addr, int SetType, int Token, const CServerInfo *pInfo)
{
	CServerEntry *pEntry = 0;
	switch(SetType)
	{
	case SET_MASTER_ADD:
		{
			if(!(m_RefreshFlags&IServerBrowser::REFRESHFLAG_INTERNET))
				return;

			if(!Find(IServerBrowser::TYPE_INTERNET, Addr))
			{
				pEntry = Add(IServerBrowser::TYPE_INTERNET, Addr);
				QueueRequest(pEntry);
			}
		}
		break;
	case SET_FAV_ADD:
		{
			if(!(m_RefreshFlags&IServerBrowser::REFRESHFLAG_INTERNET))
				return;

			if(!Find(IServerBrowser::TYPE_INTERNET, Addr))
			{
				pEntry = Add(IServerBrowser::TYPE_INTERNET, Addr);
				QueueRequest(pEntry);
			}
		}
		break;
	case SET_TOKEN:
		{
			int Type;

			// internet entry
			if(m_RefreshFlags&IServerBrowser::REFRESHFLAG_INTERNET)
			{
				Type = IServerBrowser::TYPE_INTERNET;
				pEntry = Find(Type, Addr);
				if(pEntry && (pEntry->m_InfoState != CServerEntry::STATE_PENDING || Token != pEntry->m_CurrentToken))
					pEntry = 0;
			}

			// lan entry
			if(!pEntry && (m_RefreshFlags&IServerBrowser::REFRESHFLAG_LAN) && m_BroadcastTime+time_freq() >= time_get())
			{
				Type = IServerBrowser::TYPE_LAN;
				pEntry = Add(Type, Addr);
			}

			// set info
			if(pEntry)
			{
				SetInfo(Type, pEntry, *pInfo);
				if(Type == IServerBrowser::TYPE_LAN)
					pEntry->m_Info.m_Latency = min(static_cast<int>((time_get()-m_BroadcastTime)*1000/time_freq()), 999);
				else
					pEntry->m_Info.m_Latency = min(static_cast<int>((time_get()-pEntry->m_RequestTime)*1000/time_freq()), 999);
				RemoveRequest(pEntry);
			}
		}
	}

	if(pEntry)
		m_ServerBrowserFilter.Sort(m_aServerlist[m_ActServerlistType].m_ppServerlist, m_aServerlist[m_ActServerlistType].m_NumServers, CServerBrowserFilter::RESORT_FLAG_FORCE);
}
예제 #20
0
void CServerBrowser::Update(bool ForceResort)
{
	if(m_ServerdataLocked)
		return;
	int64 Timeout = time_freq();
	int64 Now = time_get();
	int Count;
	CServerEntry *pEntry, *pNext;

	// do server list requests
	if(m_NeedRefresh && !m_pMasterServer->IsRefreshing())
	{
		NETADDR Addr;
		CNetChunk Packet;
		int i = 0;

		m_NeedRefresh = 0;
		m_MasterServerCount = -1;
		mem_zero(&Packet, sizeof(Packet));
		Packet.m_ClientID = -1;
		Packet.m_Flags = NETSENDFLAG_CONNLESS;
		Packet.m_DataSize = sizeof(SERVERBROWSE_GETCOUNT);
		Packet.m_pData = SERVERBROWSE_GETCOUNT;

		for(i = 0; i < IMasterServer::MAX_MASTERSERVERS; i++)
		{
			if(!m_pMasterServer->IsValid(i))
				continue;

			Addr = m_pMasterServer->GetAddr(i);
			m_pMasterServer->SetCount(i, -1);
			Packet.m_Address = Addr;
			m_pNetClient->Send(&Packet);
			if(g_Config.m_Debug)
			{
				dbg_msg("client_srvbrowse", "count-request sent to %d", i);
			}
		}
	}

	// check if all server counts arrived
	if(m_MasterServerCount == -1)
	{
		m_MasterServerCount = 0;
		for(int i = 0; i < IMasterServer::MAX_MASTERSERVERS; i++)
		{
			if(!m_pMasterServer->IsValid(i))
				continue;
			int Count = m_pMasterServer->GetCount(i);
			if(Count == -1)
			{
			/* ignore Server
				m_MasterServerCount = -1;
				return;
				// we don't have the required server information
				*/
			}
			else
				m_MasterServerCount += Count;
		}

		// request serverlist
		NETADDR Addr;
		CNetChunk Packet;
		mem_zero(&Packet, sizeof(Packet));
		Packet.m_ClientID = -1;
		Packet.m_Flags = NETSENDFLAG_CONNLESS;
		Packet.m_DataSize = sizeof(SERVERBROWSE_GETLIST);
		Packet.m_pData = SERVERBROWSE_GETLIST;

		for(int i = 0; i < IMasterServer::MAX_MASTERSERVERS; i++)
		{
			if(!m_pMasterServer->IsValid(i))
				continue;

			Addr = m_pMasterServer->GetAddr(i);
			Packet.m_Address = Addr;
			m_pNetClient->Send(&Packet);
		}
		if(g_Config.m_Debug)
		{
			dbg_msg("client_srvbrowse", "servercount: %d, requesting server list", m_MasterServerCount);
		}
		m_LastPacketTick = 0;
	}
	else if(m_MasterServerCount > -1)
	{
		m_MasterServerCount = 0;
		for(int i = 0; i < IMasterServer::MAX_MASTERSERVERS; i++)
			{
				if(!m_pMasterServer->IsValid(i))
					continue;
				int Count = m_pMasterServer->GetCount(i);
				if(Count == -1)
				{
				/* ignore Server
					m_MasterServerCount = -1;
					return;
					// we don't have the required server information
					*/
				}
				else
					m_MasterServerCount += Count;
			}
			//if(g_Config.m_Debug)
			//{
			//	dbg_msg("client_srvbrowse", "ServerCount2: %d", m_MasterServerCount);
			//}
	}
	if(m_MasterServerCount > m_NumRequests + m_LastPacketTick)
	{
		++m_LastPacketTick;
		return; // wait for more packets
	}
	pEntry = m_pFirstReqServer;
	Count = 0;
	while(1)
	{
		if(!pEntry) // no more entries
			break;

		if(pEntry->m_RequestTime && pEntry->m_RequestTime+Timeout < Now)
		{
			pEntry = pEntry->m_pNextReq;
			continue;
		}

		// no more than 10 concurrent requests
		if(Count >= m_CurrentMaxRequests)
			break;

		if(pEntry->m_RequestTime == 0)
		{
			if (pEntry->m_Is64)
				RequestImpl64(pEntry->m_Addr, pEntry);
			else
				RequestImpl(pEntry->m_Addr, pEntry);
		}

		Count++;
		pEntry = pEntry->m_pNextReq;
	}

	// no more current server requests
	if(m_pFirstReqServer && Count == 0 && m_CurrentMaxRequests > 1)
	{
		// reset old ones
		pEntry = m_pFirstReqServer;
		while(1)
		{
			if(!pEntry) // no more entries
				break;

			pEntry->m_RequestTime = 0;
			pEntry = pEntry->m_pNextReq;
		}

		// update max-requests
		m_CurrentMaxRequests /= 2;
		if(m_CurrentMaxRequests <= 3)
		{
			m_CurrentMaxRequests = 1;
			m_NeedRefresh = false;
		}
	}
	else if(Count == 0 && m_CurrentMaxRequests == 1) // we reached the limit, just release all left requests. If a server sends us a packet, a new request will be added automatically, so we can delete all
	{
		pEntry = m_pFirstReqServer;
		while(1)
		{
			if(!pEntry) // no more entries
				break;
			pNext = pEntry->m_pNextReq;
			RemoveRequest(pEntry); // release request
			pEntry = pNext;
		}
	}

	// check if we need to resort
	if(m_Sorthash != SortHash() || ForceResort)
		Sort();
}
예제 #21
0
// Async Read callback
// TODO: Should we add a 'hint' here to let the reader know that we are waiting for
// a certain number of additional bytes? (to prevent unecessary loops)...
void CDSISession::OnReceive(CTCPPacketReader& reader)
{
  DSIHeader hdr;  
  // Technically, we should probably be locking more in here, but we know that there is only one read thread, so 
  // there will never be concurrent calls into this method...
  
  // Ongoing Reply...
  /////////////////////////////////////////////////////
  // TODO: Should we time out after some period...?
  if (m_pOngoingReply) // Do we have a previously-incomplete reply block?
  {
    int err = kNoError;
    // Continue working on the incomplete read...
    int bytesRead = m_pOngoingReply->AppendResponse(reader);    
    if (bytesRead > 0) // All OK
    {
      if (m_pOngoingReply->GetBytesRemaining()) // Not quite done yet...
        return; // Wait some more
    }
    else if(!bytesRead)
    {
      XAFP_LOG(XAFP_LOG_FLAG_ERROR, "DSI Protocol: TCPPacketReader returned zero bytes (expected: %d)", reader.GetBytesLeft());
    }
    else
    {
      XAFP_LOG(XAFP_LOG_FLAG_ERROR, "DSI Protocol: Unable to read response - Error: %d", bytesRead);
      err = kTCPReceiveError;
    }
    
    // We either completed the reply block, or an error occurred. Signal waiting caller
    XAFP_LOG(XAFP_LOG_FLAG_DSI_PROTO, "DSI Protocol: Finished receiving multi-PDU read response (expected: %d, read: %d, pieces: %d)",m_pOngoingReply->GetTotalBytes(), m_pOngoingReply->GetTotalBytes() - m_pOngoingReply->GetBytesRemaining(), m_pOngoingReply->GetPieces());
    m_pOngoingReply->Complete(err); 
    m_pOngoingReply = NULL;
    return;
  }
  
  // 'Standard' Message Block(s) or beginning of a multi-PDU reply
  /////////////////////////////////////////////////////
  while (reader.GetBytesLeft())
  {
    // Read the message header
    int err = reader.Read(&hdr, sizeof(DSIHeader));
    if (err < 0)
    {
      XAFP_LOG(XAFP_LOG_FLAG_ERROR, "DSI Protocol: Unable to read response header - Error: %d", err);
      // TODO: Nothing after this is going to work...figure that out
      return;
    }
    
    translate_header(hdr); // Change from network to host representation
    
    if (!hdr.flags) // This is a server-initiated request (as opposed to a reply to one of our requests)
    {
      switch (hdr.command)
      {
        case DSITickle: // Used by server for 'heartbeat' monitoring
          // TODO: Track time since last notice to detect timeouts
          XAFP_LOG_0(XAFP_LOG_FLAG_DSI_PROTO, "DSI Protocol: Received Server 'Tickle'. Sending reply...");
          SendMessage(DSITickle, GetNewRequestId()); // Send keep-alive reply to server
          break;
        case DSIAttention: // Used by server to notify clients of events
          uint16_t attData;
          // TODO: Implement reconnect handler and heed delay specified by server in AFPUserBytes
          // TODO: Skip unexpected bytes, if present
          // TODO: Retrieve quantum size during login
          if (hdr.totalDataLength > 2)
            XAFP_LOG(XAFP_LOG_FLAG_ERROR,"DSI Protocol: ****Unexpected Size for Attention Data**** (%d bytes)", hdr.totalDataLength);
          reader.Read(&attData, sizeof(uint16_t)); // TODO: Where should we handle read() failures
          attData = ntohs(attData); // Handle byte-ordering
          XAFP_LOG(XAFP_LOG_FLAG_INFO, "DSI Protocol: Received Server Attention. Flags - Shutdown:%s, ServerCrash:%s, Message:%s, NoReconnect:%s",
                   (kShutDownNotifyMask & attData) ? "yes" : "no",
                   (kAllowReconnectMask & attData) ? "yes" : "no",
                   (kMsgNotifyMask & attData) ? "yes" : "no",
                   (kDisconnectNotifyMask & attData) ? "yes" : "no"
                   );
          // TODO: Retrieve the server message when there is one
          OnAttention(attData);
          break;
        case DSICloseSession: // Notification from server that the session will be closed. 
          // Signal all waiting callers and tell them something happened
          XAFP_LOG_0(XAFP_LOG_FLAG_INFO, "DSI Protocol: Server Closed Session. Canceling all pending requests");
          SignalAll(kDSISessionClosed);
          // TODO: Clean-up session (and possibly re-open?)
          break;  
        default:
          XAFP_LOG(XAFP_LOG_FLAG_ERROR,"DSI Protocol: Received unknown request - command: %d", hdr.command);
      }
    }
    else // This is a reply to a previously-sent message
    {
      CDSIRequest* pRequest = NULL;
      
      switch (hdr.command)
      {
        case DSICloseSession: // This should not happen, but handle it anyway...
          XAFP_LOG_0(XAFP_LOG_FLAG_ERROR, "DSI Protocol: Unexpected reply message - CloseSession");        
          // Signal all waiting callers and tell them something happened
          SignalAll(kDSISessionClosed);
          // TODO: Clean-up session (should already be done...)
          break;
        case DSIOpenSession:
        case DSICommand:
        case DSIWrite:
        case DSIGetStatus:
          XAFP_LOG(XAFP_LOG_FLAG_DSI_PROTO, "DSI Protocol: Received Reply - Message:%s, RequestId:%d, result:%d", DSIProtoCommandToString(hdr.command), hdr.requestID, hdr.errorCode);
          // Find the request in our request map
          pRequest = RemoveRequest(hdr.requestID);
          if (pRequest)
          {
            // Tranfer data into caller-supplied buffer, if one was provided
            // If not, they did not expect any data back, just a result code
            // TODO: Make sure all data in the message is read/skipped before moving on, to prevent 
            // clogging-up the pipe...
            pRequest->SaveResponse(reader, hdr.totalDataLength);
            if (pRequest->IsOngoing())
            {
              m_pOngoingReply = pRequest; 
              return; // Wait for more data before signaling requestor...
            }
            // Signal waiting requestor
            // NOTE: This object may self-destruct (or go out of scope) immediately. Do not use the reference again after calling 'Complete'
            pRequest->Complete(hdr.errorCode);
          }
          else
          {
            XAFP_LOG(XAFP_LOG_FLAG_ERROR, "DSI Protocol: Unexpected reply - RequestId: %d", hdr.requestID);
            // TODO: Need a better flush/skip/seek method
            void* p = malloc(hdr.totalDataLength);
            reader.Read(p, hdr.totalDataLength);
            free(p);
          }
          break;
        default:
          // TODO: Skip payload data and try to recover
          XAFP_LOG(XAFP_LOG_FLAG_ERROR, "DSI Protocol: Received unknown reply - command: %d, payload: %d", hdr.command, hdr.totalDataLength);
      }
    }
  }
}