Пример #1
0
//
// status check event handler
// to reconcile the status 
//
// to be connected status, broadcast packet
// should be received within MAX_ALLOWED_HEARTBEAT_INTERVAL
// 
// returns TRUE to detach from the monitor
// FALSE otherwise.
//
BOOL
CNdasDevice::OnStatusCheck()
{
	ximeta::CAutoLock autolock(this);

	//
	// Only when the device is connected!
	//
	if (NDAS_DEVICE_STATUS_CONNECTED != m_status) {
//		_ASSERTE(FALSE && "OnStatusCheck should be called when connected!");
		DBGPRT_WARN(_FT("OnStatusCheck is called on connected. Detaching.\n"));
		// Detach from the monitor
		return TRUE;
	}

	DWORD dwCurrentTick = ::GetTickCount();
	DWORD dwElapsed = dwCurrentTick - m_dwLastHeartbeatTick;

	if (dwElapsed > MAX_ALLOWED_HEARTBEAT_INTERVAL) {

		//
		// When just a single unit device is mounted,
		// status will not be changed to DISCONNECTED!
		//

		if (IsAnyUnitDevicesMounted()) {
			return FALSE;
		}

		//
		// Do not disconnect the device when the debugger is attached
		//
		if (!NdasServiceConfig::Get(nscDisconnectOnDebug) &&
			::IsDebuggerPresent()) 
		{
			return FALSE;
		}

		BOOL fSuccess = DestroyAllUnitDevices();
		if (!fSuccess) {
			return FALSE;
		}

		ChangeStatus(NDAS_DEVICE_STATUS_DISCONNECTED);
		return TRUE;
	}

	return FALSE;
}
Пример #2
0
VOID
CNdasLogicalDevice::OnDeviceStatusFailure()
{
	ximeta::CAutoLock autolock(this);

	DBGPRT_WARN(_FT("Logical device %s instance does not exist anymore.\n"), ToString());

	SetStatus(NDAS_LOGICALDEVICE_STATUS_UNMOUNTED);

	//
	// Detach from the event monitor
	//
	CNdasEventMonitor* pEventMon = pGetNdasEventMonitor();
	pEventMon->Detach(this);
}
Пример #3
0
BOOL
CNdasLogicalDeviceManager::UnregisterNdasScsiLocation(
	CONST NDAS_SCSI_LOCATION& location)
{
	ximeta::CAutoLock autolock(this);

	LocationMap::size_type nErased = m_NdasScsiLocationMap.erase(location);
	if (1 != nErased) {
		DBGPRT_WARN(
			_FT("NdasScsiLocation not registered at %s"), 
			CNdasScsiLocation(location).ToString());
	}
	_ASSERTE(1 == nErased);

	return (1 == nErased);
}
Пример #4
0
BOOL
CNdasDevice::CreateUnitDevice(DWORD dwUnitNo)
{
	_ASSERTE(dwUnitNo < MAX_NDAS_UNITDEVICE_COUNT);
	if (dwUnitNo >= MAX_NDAS_UNITDEVICE_COUNT) 
	{
		return FALSE;
	}

	_ASSERTE(NULL == m_pUnitDevices[dwUnitNo]);

	if (!m_fUnitDevicePresent[dwUnitNo])
	{
		DBGPRT_WARN(_FT("HWINFO does not contain unit %d.\n"), dwUnitNo);
		return FALSE;
	}

	DWORD dwMaxFailure = NdasServiceConfig::Get(nscUnitDeviceIdentifyRetryMax);
	DWORD dwInterval = NdasServiceConfig::Get(nscUnitDeviceIdentifyRetryGap);

	for (DWORD i = 0; i < dwMaxFailure; ++i)
	{
		CNdasUnitDeviceCreator udCreator(*this, dwUnitNo);
		CNdasUnitDevice* pUnitDevice = udCreator.CreateUnitDevice();
		// CreateUnitDevice already called AddRef

		if (NULL != pUnitDevice) 
		{
			m_pUnitDevices[dwUnitNo] = pUnitDevice;
			pUnitDevice->RegisterToLDM();
			return TRUE;
		}

		::Sleep(dwInterval);

		DBGPRT_ERR_EX(_FT("Creating a unit device instance failed (%d out of %d): "),
			i, dwMaxFailure);
	}

	return FALSE;
}
Пример #5
0
DWORD
CNdasEventPublisher::OnTaskStart()
{
	_ASSERTE(NULL != m_hSemQueue && "Don't forget to call initialize().");

	// Queue Semaphore, Terminating Thread, Pipe Instances(MAX...)
	HANDLE hWaitHandles[2 + MAX_NDAS_EVENT_PIPE_INSTANCES];
	hWaitHandles[0] = m_hTaskTerminateEvent;
	hWaitHandles[1] = m_hSemQueue;

	//
	// initial pipe instance
	//
	m_PipeData.clear();
	BOOL fSuccess = AcceptNewConnection();
	if (!fSuccess) {
		DBGPRT_ERR_EX(_T("Creating a first pipe instance failed: "));
		return -1;
	}

	BOOL bTerminate(FALSE);

	while (FALSE == bTerminate) {

		DWORD dwWaitHandles = 2 + m_PipeData.size();
		for (DWORD i = 0; i < m_PipeData.size(); ++i) {
			hWaitHandles[i + 2] = m_PipeData[i]->overlapped.hEvent;
		}

		DWORD dwWaitResult = ::WaitForMultipleObjects(
			dwWaitHandles,
			hWaitHandles,
			FALSE,
			m_dwPeriod);


		if (dwWaitResult == WAIT_OBJECT_0) 
		{
			//
			// Terminate Thread
			//
			bTerminate = TRUE;
		} 
		else if (dwWaitResult == WAIT_OBJECT_0 + 1) 
		{
			//
			// Event Message is queued
			//
			while (TRUE) {
				m_queueLock.Lock();
				bool bEmpty = m_EventMessageQueue.empty();
				if (bEmpty) {
					m_queueLock.Unlock();
					break;
				}
				NDAS_EVENT_MESSAGE message = m_EventMessageQueue.front();
				m_EventMessageQueue.pop();
				m_queueLock.Unlock();
				Publish(&message);
			}

		} 
		else if (dwWaitResult >= WAIT_OBJECT_0 + 2 && 
			dwWaitResult < WAIT_OBJECT_0 + 2 + m_PipeData.size())
		{
			DWORD dwPipe = dwWaitResult - WAIT_OBJECT_0 - 2;

			DBGPRT_INFO(_FT("Event Client %d\n"), dwPipe);

			CLIENT_DATA* pCurClientData = m_PipeData[dwPipe];

			DBGPRT_INFO(_FT("Connected: %d\n"), pCurClientData->bConnected);

			fSuccess = ::ResetEvent(pCurClientData->overlapped.hEvent);
			_ASSERT(fSuccess);

			if (!pCurClientData->bConnected) {
				
				//
				// create another instance
				//
				fSuccess = AcceptNewConnection();
				if (!fSuccess) {
					DBGPRT_WARN_EX(_FT("Creating another pipe instance failed: "));
					DBGPRT_WARN(_FT("No more event subscribers can be accepted.\n"));
				}

				// AcceptNewConnection will invalidate pCurClientData;

				pCurClientData = m_PipeData.at(dwPipe);

				//
				// Accepting connection
				//
				pCurClientData->bConnected = TRUE;
				fSuccess = ::ResetEvent(pCurClientData->overlapped.hEvent);
				_ASSERT(fSuccess);
				
				//
				// Send a version event for connected client
				//
				fSuccess = SendVersionInfo(
					pCurClientData->hPipe, 
					&pCurClientData->overlapped);

				//
				// Any failure will disconnect the client
				//
				if (!fSuccess && ERROR_IO_PENDING != ::GetLastError()) {
					ClientDataVector::iterator itr = m_PipeData.begin();
					CleanupConnection(pCurClientData);
					while (itr != m_PipeData.end()) {
						if ((CLIENT_DATA*)*itr == pCurClientData) {
							m_PipeData.erase(itr);
							break;
						}
						++itr;
					}
					DBGPRT_INFO(_FT("Accepted removed event subscriber.\n"));
				} else {
					DBGPRT_INFO(_FT("Accepted new event subscriber.\n"));
				}

			} else {
			}
			// ignore other status
		} else if (WAIT_TIMEOUT == dwWaitResult) {
			NDAS_EVENT_MESSAGE msg = {0};
			msg.EventType = NDAS_EVENT_TYPE_PERIODIC;
			Publish(&msg);
		} else 
		{
			//
			// Error
			//
		}

	}

	//
	// TODO: Add cleanup
	//
	DWORD nPipeData = m_PipeData.size();
	ClientDataVector::iterator itr = m_PipeData.begin();
	while (itr != m_PipeData.end()) {
		CleanupConnection(*itr);
		++itr;
	}
	m_PipeData.clear();

	_tprintf(TEXT("Terminating Publisher Thread...\n"));
	return 0;
}
Пример #6
0
void 
CNdasEventPublisher::Publish(const PNDAS_EVENT_MESSAGE pMessage)
{
	DBGPRT_INFO(_FT("Publishing Event: %s\n"), 
		NdasEventTypeString(pMessage->EventType));

	//
	// sent the message to the connected pipes
	//
	for (ClientDataVector::iterator itr = m_PipeData.begin(); 
		itr != m_PipeData.end();) 
		//
		// do not forward the iterator here when erasing some 
		// elements 
		// itr2 = v.erase(itr); 
		// itr2 has a forwarded iterator from itr
		//
	{
		CLIENT_DATA* pClientData = *itr;
		if (pClientData->bConnected) {

			DWORD cbWritten;

			BOOL fSuccess = ::WriteFile(
				pClientData->hPipe,
				pMessage,
				sizeof(NDAS_EVENT_MESSAGE),
				&cbWritten,
				&pClientData->overlapped);

			if (!fSuccess && ERROR_IO_PENDING != ::GetLastError()) {
				
				DBGPRT_ERR_EX(_FT("Writing to a pipe failed: "));
				DBGPRT_INFO(_FT("Detaching an event subscriber.\n"));
				
				CleanupConnection(pClientData);
				//
				// erasing an element will automatically
				// forward the vector 
				// (actually, itr remains the same, but the itr is
				// a next elemen)
				itr = m_PipeData.erase(itr);

				//
				// create another instance
				//
				fSuccess = AcceptNewConnection();
				if (!fSuccess) {
					DBGPRT_WARN_EX(_FT("Creating another pipe instance failed: "));
					DBGPRT_WARN(_FT("No more event subscribers can be accepted.\n"));
				}

			} else {
				//
				// forward the iterator if we did erase
				//
				DBGPRT_INFO(_FT("Event written to a pipe %p.\n"), (*itr)->hPipe);
				++itr;
			}
		} else {
			//
			// forward the iterator if not connected
			//
			++itr;
		}
	}	
}
Пример #7
0
BOOL
CNdasDevice::CreateUnitDevice(DWORD dwUnitNo)
{
	_ASSERTE(dwUnitNo < MAX_NDAS_UNITDEVICE_COUNT);
	if (dwUnitNo >= MAX_NDAS_UNITDEVICE_COUNT) 
	{
		return FALSE;
	}

	_ASSERTE(NULL == m_pUnitDevices[dwUnitNo]);

	if (!m_fUnitDevicePresent[dwUnitNo])
	{
		DBGPRT_WARN(_FT("HWINFO does not contain unit %d.\n"), dwUnitNo);
		return FALSE;
	}

	static const DWORD UNITDEVICE_IDENTIFY_FAILURE_RETRY_DEFAULT = 4;
	static const DWORD UNITDEVICE_IDENTIFY_INTERVAL_DEFAULT = 2500;

	DWORD dwMaxFailure = UNITDEVICE_IDENTIFY_FAILURE_RETRY_DEFAULT;
	BOOL fSuccess = _NdasSystemCfg.GetValueEx(
		_T("ndassvc"),
		_T("MaxUnitDeviceIdentifyFailure"),
		&dwMaxFailure);
	if (!fSuccess || 0 == dwMaxFailure)
	{
		dwMaxFailure = UNITDEVICE_IDENTIFY_FAILURE_RETRY_DEFAULT;
	}

	DWORD dwInterval = UNITDEVICE_IDENTIFY_INTERVAL_DEFAULT;
	fSuccess = _NdasSystemCfg.GetValueEx(
		_T("ndassvc"),
		_T("UnitDeviceIdentifyFailureRetryInterval"),
		&dwInterval);
	if (!fSuccess || dwInterval > 300000)
	{
		dwInterval = UNITDEVICE_IDENTIFY_INTERVAL_DEFAULT;
	}

	for (DWORD i = 0; i < dwMaxFailure; ++i)
	{
		CNdasUnitDeviceCreator udCreator(*this, dwUnitNo);
		CNdasUnitDevice* pUnitDevice = udCreator.CreateUnitDevice();
		// CreateUnitDevice already called AddRef

		if (NULL != pUnitDevice) 
		{
			m_pUnitDevices[dwUnitNo] = pUnitDevice;
			pUnitDevice->RegisterToLDM();
			return TRUE;
		}

		::Sleep(dwInterval);

		DBGPRT_ERR_EX(_FT("Creating a unit device instance failed (%d out of %d): "),
			i, dwMaxFailure);
	}

	return FALSE;
}
Пример #8
0
VOID
CNdasIXServer::OnReceive(CLpxDatagramSocket& sock)
{
	SOCKADDR_LPX remoteAddr;
	DWORD cbReceived;
	BYTE* pPacket = NULL;
	DWORD dwRecvFlags;

	BOOL fSuccess = sock.GetRecvFromResult(
		&remoteAddr,
		&cbReceived,
		(BYTE**)&pPacket,
		&dwRecvFlags);

	//
	// Sanity Check
	//
	CONST LSINFOX_HEADER* pHeader = 
		reinterpret_cast<CONST LSINFOX_HEADER*>(pPacket);
	
	UCHAR ProtocolName[4] = INFOX_DATAGRAM_PROTOCOL;

	if (pHeader->Protocol[0] != ProtocolName[0] ||
		pHeader->Protocol[1] != ProtocolName[1] ||
		pHeader->Protocol[2] != ProtocolName[2] ||
		pHeader->Protocol[3] != ProtocolName[3])
	{
		DBGPRT_WARN(_FT("Invalid INFOX packet: protocol %c%c%c%c\n"),
			pHeader->Protocol[0],
			pHeader->Protocol[1],
			pHeader->Protocol[2],
			pHeader->Protocol[3]);
		return;
	}

	if (pHeader->MessageSize != cbReceived) {
		DBGPRT_WARN(
			_FT("Invalid packet size: Received %d bytes, Claimed %d bytes\n"),
			cbReceived,
			pHeader->MessageSize);
		return;
	}

	CONST LSINFOX_DATA* pData = 
		reinterpret_cast<CONST LSINFOX_DATA*>(pPacket + sizeof(LSINFOX_HEADER));

	switch (LSINFOX_TYPE_MAJTYPE & pHeader->Type) {
	case LSINFOX_PRIMARY_UPDATE_MESSAGE:
		{
			CONST LSINFOX_PRIMARY_UPDATE* pPrimaryUpdateData = 
				reinterpret_cast<const LSINFOX_PRIMARY_UPDATE*>(pData);

			OnIXPrimaryUpdate(sock,&remoteAddr,pPrimaryUpdateData);

			return;
		}
	case LSINFOX_PRIMARY_USAGE_MESSAGE:
		{
			CONST LSINFOX_NDASDEV_USAGE_REQUEST* pUsageRequest = 
				reinterpret_cast<const LSINFOX_NDASDEV_USAGE_REQUEST*>(pData);

			OnIXUsageRequest(sock,&remoteAddr,pUsageRequest);
			return;
		}

	default:
		
		return;
	}
}
Пример #9
0
VOID
CNdasIXBcast::ResetBind()
{
	BOOL fSuccess = FALSE;

	if (NULL != m_lpSocketAddressList) {
		::LocalFree(m_lpSocketAddressList);
		m_lpSocketAddressList = NULL;
	}

	while (NULL == m_lpSocketAddressList) {
		m_lpSocketAddressList = pCreateLocalLpxAddressList();
			if (NULL == m_lpSocketAddressList) {
			DBGPRT_WARN_EX(_FT("Getting local lpx address list failed. Retry in 5 sec: "));
			// try to get address list again in 5 sec
			// we should terminate this routine at a task terminate event
			DWORD dwWaitResult = ::WaitForSingleObject(m_hTaskTerminateEvent, 5000);
			if (WAIT_OBJECT_0 == dwWaitResult) {
				return;
			}
		}
	}
	
	fSuccess = m_sockAddrChangeNotifier.Reset();
	// _ASSERTE(fSuccess);
	if (!fSuccess) {
		DBGPRT_WARN(_FT("Resetting sockAddrChangeNotifier failed: "));
	}

	DWORD nLocalAddrs =
		min((DWORD)m_lpSocketAddressList->iAddressCount, m_nSenders);

	for (DWORD i = 0; i < m_nSenders; ++i) {
		if (INVALID_SOCKET != (SOCKET)m_senders[i]) {
			m_senders[i].Close();
		}
	}

	for (DWORD i = 0; i < nLocalAddrs && i < m_nSenders; ++i) {

		PSOCKADDR_LPX pSockAddr = (PSOCKADDR_LPX)
			m_lpSocketAddressList->Address[i].lpSockaddr;
		pSockAddr->LpxAddress.Port = 0;

		fSuccess = m_senders[i].Create();
		if (!fSuccess) {
			DBGPRT_ERR_EX(_FT("Creating a socket failed: "));
			continue;
		}

		//
		// This is a broadcast socket
		//
		BOOL bBroadcast = TRUE;
		fSuccess = m_senders[i].SetSockOpt(
			SO_BROADCAST, 
			(CONST BYTE*)&bBroadcast, 
			sizeof(BOOL));

		if (!fSuccess) {
			DBGPRT_ERR_EX(_FT("Setting a sock option to broadcast failed: "));
			(VOID) m_senders[i].Close();
			continue;
		}

		fSuccess = m_senders[i].Bind(pSockAddr);
		if (!fSuccess) {
			DBGPRT_ERR_EX(_FT("Binding a sock %d to %s failed: "),
				i, CSockLpxAddr(pSockAddr).ToString());
			(VOID) m_senders[i].Close();
			continue;
		}
	}

}
Пример #10
0
void
CNdasDeviceHeartbeatListener::OnReceive(CLpxDatagramSocket& sock)
{
	SOCKADDR_LPX remoteAddr;
	DWORD cbReceived;

	PNDAS_DEVICE_HEARTBEAT pData = NULL;

	DWORD dwRecvFlags;
	BOOL fSuccess = sock.GetRecvFromResult(
		&remoteAddr, 
		&cbReceived, 
		(BYTE**)&pData,
		&dwRecvFlags);

	if (!fSuccess) 
	{
		DBGPRT_ERR_EX(_FT("Heartbeat Packet Receive failed: "));
		return;
	}

	DBGPRT_NOISE(_FT("Received Heartbeat Packet (%d bytes) ")
		_T("from %s at %s: ")
		_T("Receive Flag %08X\n"),
		cbReceived, 
		CSockLpxAddr(remoteAddr).ToString(),
		CSockLpxAddr(sock.GetBoundAddr()).ToString(),
		dwRecvFlags);


	fSuccess = IsValidHeartbeat(cbReceived, (LPCVOID) pData);

	if (!fSuccess) 
	{
		DBGPRT_WARN(_FT("Invalid packet received!\n"));
		return;
	}

	const NDAS_DEVICE_HEARTBEAT* pHeartbeat = 
		reinterpret_cast<const NDAS_DEVICE_HEARTBEAT*>(pData);

	NDAS_DEVICE_HEARTBEAT_INFO eventData = {0};
	
	::CopyMemory(
		eventData.DeviceAddress.Node,
		remoteAddr.LpxAddress.Node,
		sizeof(remoteAddr.LpxAddress.Node));

	C_ASSERT(
		sizeof(eventData.DeviceAddress.Node) ==
		sizeof(remoteAddr.LpxAddress.Node));

	::CopyMemory(
		eventData.LocalAddress.Node,
		sock.GetBoundAddr()->LpxAddress.Node,
		sizeof(remoteAddr.LpxAddress.Node));

	C_ASSERT(
		sizeof(eventData.LocalAddress.Node) ==
		sizeof(remoteAddr.LpxAddress.Node));

	eventData.Timestamp = ::GetTickCount();
	eventData.Type = pHeartbeat->Type;
	eventData.Version = pHeartbeat->Version;

	__raise this->OnHeartbeat(eventData);
}