コード例 #1
0
//============================================================================
static void NotifyConnSocketConnectFailed (CliFileConn * conn) {
    s_critsect.Enter();
    {
        conn->cancelId = 0;
        s_conns.Unlink(conn);

        if (conn == s_active)
            s_active = nil;
    }
    s_critsect.Leave();
    
    // Cancel all transactions in progress on this connection.
    NetTransCancelByConnId(conn->seq, kNetErrTimeout);
    
#ifndef SERVER
    // Client apps fail if unable to connect for a time
    if (++conn->numFailedConnects >= kMaxFailedConnects) {
        ReportNetError(kNetProtocolCli2File, kNetErrConnectFailed);
    }
    else
#endif // ndef SERVER
    {
        // start reconnect, if we are doing that
        if (s_running && conn->AutoReconnectEnabled())
            conn->StartAutoReconnect();
        else
            conn->UnRef("Lifetime"); // if we are not reconnecting, this socket is done, so remove the lifetime ref
    }
    conn->UnRef("Connecting");
}
コード例 #2
0
//============================================================================
static void AsyncLookupCallback (
    void *              param,
    const char          name[],
    unsigned            addrCount,
    const plNetAddress  addrs[]
) {
    if (!addrCount) {
        ReportNetError(kNetProtocolCli2File, kNetErrNameLookupFailed);
        return;
    }

    for (unsigned i = 0; i < addrCount; ++i) {
        Connect(name, addrs[i]);
    }
}
コード例 #3
0
//============================================================================
static void NotifyConnSocketDisconnect (CliFileConn * conn) {
    conn->StopAutoPing();
    s_critsect.Enter();
    {
        conn->cancelId = 0;
        s_conns.Unlink(conn);
            
        if (conn == s_active)
            s_active = nil;
    }
    s_critsect.Leave();

    // Cancel all transactions in progress on this connection.
    NetTransCancelByConnId(conn->seq, kNetErrTimeout);


    bool notify = false;

#ifdef SERVER
    {
        if (hsTimer::GetMilliSeconds<uint32_t>() - conn->connectStartMs > kMinValidConnectionMs)
            conn->reconnectStartMs = 0;
        else
            conn->reconnectStartMs = GetNonZeroTimeMs() + kMaxReconnectIntervalMs;
    }
#else
    {
    #ifndef LOAD_BALANCER_HARDWARE
        // If the connection to the remote server was open for longer than
        // kMinValidConnectionMs then assume that the connection was to
        // a valid server and try to perform reconnection immediately. If
        // less time elapsed then the connection was likely to a server
        // with an open port but with no notification procedure registered
        // for this type of communication channel.
        if (hsTimer::GetMilliSeconds<uint32_t>() - conn->connectStartMs > kMinValidConnectionMs) {
            conn->reconnectStartMs = 0;
        }
        else {
            if (++conn->numImmediateDisconnects < kMaxImmediateDisconnects)
                conn->reconnectStartMs = GetNonZeroTimeMs() + kMaxReconnectIntervalMs;
            else
                notify = true;
        }
    #else
        // File server is running behind a load-balancer, so the next connection may
        // send us to a new server, therefore attempt a reconnection to the same
        // address even if the disconnect was immediate.  This is safe because the
        // file server is stateless with respect to clients.
        if (hsTimer::GetMilliSeconds<uint32_t>() - conn->connectStartMs <= kMinValidConnectionMs) {
            if (++conn->numImmediateDisconnects < kMaxImmediateDisconnects)
                conn->reconnectStartMs = GetNonZeroTimeMs() + kMaxReconnectIntervalMs;
            else
                notify = true;
        }
        else {
            // disconnect was not immediate. attempt a reconnect unless we're shutting down
            conn->numImmediateDisconnects = 0;
            conn->reconnectStartMs = 0;
        }
    #endif  // LOAD_BALANCER
    }
#endif // ndef SERVER

    if (notify) {
        ReportNetError(kNetProtocolCli2File, kNetErrDisconnected);
    }
    else {  
        // clean up the socket and start reconnect, if we are doing that
        conn->Destroy();
        if (conn->AutoReconnectEnabled())
            conn->StartAutoReconnect();
        else
            conn->UnRef("Lifetime"); // if we are not reconnecting, this socket is done, so remove the lifetime ref
    }

    conn->UnRef("Connected");
}
コード例 #4
0
BOOL COXNetBrowseTree::CreateChildren(HTREEITEM hParentItem, NETRESOURCE* pParentNetResources)
// --- In  : hParentItem : Node of which the children nodes have to be created
//			 pParentNetResources : Net resource of this parent node
// --- Out : 
// --- Returns :
// --- Effect : Computes the netresources of the children and creates the child nodes
{
	HANDLE hEnum = NULL;
	DWORD dwScope = pParentNetResources == NULL ? m_nResourceScope : pParentNetResources->dwScope;
	DWORD nResult = WNetOpenEnum(
		dwScope,				// scope of enumeration 
		RESOURCETYPE_ANY,		// resource types to list 
		0,						// resource usage to list 
		pParentNetResources,	// pointer to resource structure 
		&hEnum);				// pointer to enumeration handle buffer 
	if (nResult != NO_ERROR)
	{
		TRACE2("COXNetBrowseTree::CreateChildren : WNetOpenEnum failed with error code %i == 0x%X\n",
			nResult, nResult);
		ReportNetError(nResult, pParentNetResources == NULL ? NULL : pParentNetResources->lpRemoteName);
		return FALSE;
	}

	DWORD nCurrentCount(0);
	DWORD nCurrentSkipCount(0);
	/* =============================================================================== */	

	// The problem with the WNetEnumResoiurce fuction is that allthough you use 
	// 0xFFFFFFFF as requested resource count (this means everything) the function
	// does NOT return ERROR_MORE_DATA if the buffer is too small.  It only returns
	// this value if the buffer supplied is too small even for one value, in this
	// case the space needed to hold the first resource found in the enumeration
	// Normally the size of this resource should be sizeof(NETRESOURCE) which is 
	// 32 bytes but experience learned that this fluctuates between 32 bytes and 
	// more than 1000 bytes.  This is probably due to the fact that WNetEnumResource
	// also needs allocated memory for the strings inside the NETRESOURCE struct.
	// This leads to the conclusion that we cannot calculate with certainty the size
	// of the buffer we need for a certain number of resources.  The most robust
	// solution to this problem is to request a absolute number of resources, make
	// an serious and realistic estimation of the maximum amount of memory needed
	// to hold ALL requested resources and then test to see whether you have retrieved
	// all requested resources.  If this is TRUE then again enumerate the resources
	// to determine whether there aren't any left and so on until the returned
	// number of resources is smaller than the requested number.  This last remark
	// explains why we need to be sure that the requested number of resources 
	// allways fit in the amount of memory we allocated for the buffer.  We could 
	// alocated a very big buffer but we prefer the loop.

	// Also note that we don't use NETRESOURCE* pRes = new NETRESOURCE[Count]
	// because the array allocated will be an array of structs of size sizeof(NETRESOURCE)
	// and that's just not correct to  hold one netresource. That's why we use
	// GlobalAlloc.

	// USERS WHO WANT TO TUNE THE PERFORMANCE OF THIS FUNCTION CAN PLAY WITH THE 
	// NUMBER OF NETRESOURCES VIA THE nCOUNT VARIABLE AND WITH THE SIZE OF THE 
	// ALLOCATED BUFFER VIA THE nBUFFERSIZE VARIABLE BUT KEEP THE REMARKS ABOVE
	// IN MIND.
	/* =============================================================================== */
	// Start with a reasonable buffer size
	DWORD nCount = 5;
	DWORD nBufferSize = 5000;
	LPNETRESOURCE rgpNetResources = (LPNETRESOURCE)GlobalAlloc(GPTR, nBufferSize);

	while (TRUE)
	{
		DWORD nTempCount = nCount;
		DWORD nTempBufferSize = nBufferSize;
		memset(rgpNetResources, 0, nBufferSize);
		DWORD nResult2 = WNetEnumResource(
			hEnum,					// handle to enumeration 
			&nTempCount,				// pointer to entries to list 
			(LPVOID)rgpNetResources, // pointer to buffer for results 
			&nTempBufferSize);			// pointer to buffer size variable 
		TRACE2("COXNetBrowseTree::WNetEnumResource : Number of Netresources (%i), in buffersize (0x%X)\n", nTempCount, nTempBufferSize);

		if ((nResult2 != NO_ERROR) && (nResult2 != ERROR_NO_MORE_ITEMS) &&
			(nResult2 != ERROR_MORE_DATA))
		{
			TRACE2("COXNetBrowseTree::CreateChildren : WNetEnumResource failed with error code %i == 0x%X\n",
				nResult2, nResult2);
			ReportNetError(nResult2, pParentNetResources == NULL ? NULL : pParentNetResources->lpRemoteName);
			// ... Cleanup the handle and memeory allocated
			VERIFY(WNetCloseEnum(hEnum) == NO_ERROR);
			GlobalFree((HGLOBAL)rgpNetResources);
			return FALSE;
		}

		if (nResult2 == ERROR_NO_MORE_ITEMS)
			nTempCount = 0;

		// Loop the requested number of NetResources and make tree item nodes
		{
			HTREEITEM hNewItem;
			NETRESOURCE* pSourceNetResource = NULL;
			NETRESOURCE* pCopyNetResource = NULL;
			DWORD nIndex;
			DWORD nSkipCount = 0;
			for (nIndex = 0; nIndex < nTempCount; nIndex++)
			{
				pSourceNetResource  = &rgpNetResources[nIndex];

				// Check special case for disks and printers
				if ((pSourceNetResource->dwType == RESOURCETYPE_DISK) && !m_bShowDisks)
				{
					// Skip this item
					nSkipCount++;
					continue;
				}
				if ((pSourceNetResource->dwType == RESOURCETYPE_PRINT) && !m_bShowPrinters)
				{
					// Skip this item
					nSkipCount++;
					continue;
				}

				// ... Create a new item
				hNewItem = InsertResourceItem(pSourceNetResource, hParentItem);
				if (hNewItem  == NULL)
				{
					TRACE0("COXNetBrowseTree::InsertResourceItem returned NULL\n");
					// Skip this item
					nSkipCount++;
					continue;
				}

				// Add a copy to the map
				// ... Should not yet be in map
#ifdef _DEBUG
				NETRESOURCE* pCheckNetResource = NULL;
				ASSERT(!m_resourceMap.Lookup(hNewItem, pCheckNetResource));
#endif // _DEBUG
				pCopyNetResource = new NETRESOURCE;
				// ... Copy the struct itself
				memcpy(pCopyNetResource, pSourceNetResource, sizeof(NETRESOURCE));
				// ... Make a copy of all the string members
				if (pSourceNetResource->lpLocalName != NULL)
				{
					size_t len = _tcslen(pSourceNetResource->lpLocalName) + 1;
					pCopyNetResource->lpLocalName = new TCHAR[len];
					UTBStr::tcscpy(pCopyNetResource->lpLocalName, len, pSourceNetResource->lpLocalName);
				}
				else
				{
					pCopyNetResource->lpLocalName = new TCHAR[1];
					*pCopyNetResource->lpLocalName = _T('\0');
				}

				if (pSourceNetResource->lpRemoteName != NULL)
				{
					size_t len = _tcslen(pSourceNetResource->lpRemoteName) + 1;
					pCopyNetResource->lpRemoteName = new TCHAR[len];
					UTBStr::tcscpy(pCopyNetResource->lpRemoteName, len, pSourceNetResource->lpRemoteName);
				}
				else
				{
					pCopyNetResource->lpRemoteName = new TCHAR[1];
					*pCopyNetResource->lpRemoteName = _T('\0');
				}

				if (pSourceNetResource->lpComment != NULL)
				{
					size_t len = _tcslen(pSourceNetResource->lpComment) + 1;
					pCopyNetResource->lpComment = new TCHAR[len];
					UTBStr::tcscpy(pCopyNetResource->lpComment, len, pSourceNetResource->lpComment);
				}
				else
				{
					pCopyNetResource->lpComment = new TCHAR[1];
					*pCopyNetResource->lpComment = _T('\0');
				}

				if (pSourceNetResource->lpProvider != NULL)
				{
					size_t len = _tcslen(pSourceNetResource->lpProvider) + 1;
					pCopyNetResource->lpProvider = new TCHAR[len];
					UTBStr::tcscpy(pCopyNetResource->lpProvider, len, pSourceNetResource->lpProvider);
				}
				else
				{
					pCopyNetResource->lpProvider = new TCHAR[1];
					*pCopyNetResource->lpProvider = _T('\0');
				}

				// ... Add to map
				m_resourceMap.SetAt(hNewItem, pCopyNetResource);
			}

			// we need to keep track of the real number of nodes because we 
			// need it to set the correct treeitem number for the parent node
			nCurrentCount += nTempCount;
			nCurrentSkipCount += nSkipCount;

			if (hParentItem != NULL)
			{
				// Mark the parent node as expanded at least once
				VERIFY(SetItemState(hParentItem, TVIS_EXPANDEDONCE, TVIS_EXPANDEDONCE));

				// Set the number of child items to the correct value
				TV_ITEM item;
				item.hItem = hParentItem;
				item.mask = TVIF_CHILDREN;
				ASSERT(nSkipCount <= nTempCount);
				item.cChildren = nCurrentCount - nCurrentSkipCount;
				VERIFY(SetItem(&item));
			}
		}

		if (nResult2 == ERROR_MORE_DATA  || nTempCount == nCount)
			// Possibly there is more data to retrieve
		{
			nTempCount = nCount;
			continue;
		}
		else
			// There was no error and there isn't anymore data to retrieve
			break;
	}

	// Cleanup the handle and allocated memory
	VERIFY(WNetCloseEnum(hEnum) == NO_ERROR);
	GlobalFree((HGLOBAL)rgpNetResources);
	return TRUE;
}