/**
 * 	This method should be called to handle requests on the socket.
 */
bool WatcherNub::receiveRequest()
{
	if (!isInitialised_)
	{
		// TODO: Allow calls to this when not initialised before the client
		// currently does this. Should really fix the client so that this is
		// only called once initialised.
		return false;
	}

	sockaddr_in		senderAddr;
	int				len;

	if (wrh_ == NULL)
	{
		ERROR_MSG( "WatcherNub::receiveRequest: Can't call me before\n"
			"\tcalling setRequestHandler(WatcherRequestHandler*)\n" );
		return false;
	}

	if (insideReceiveRequest_)
	{
		ERROR_MSG( "WatcherNub::receiveRequest: BAD THING NOTICED:\n"
			"\tAttempted re-entrant call to receiveRequest\n" );
		return false;
	}

	insideReceiveRequest_ = true;

	// try to recv
	len = socket_.recvfrom( requestPacket_, WN_PACKET_SIZE, senderAddr );

	if (len == -1)
	{
		// EAGAIN = no packets waiting, ECONNREFUSED = rejected outgoing packet

#ifdef _WIN32
		int err = WSAGetLastError();
		if (err != WSAEWOULDBLOCK && err != WSAECONNREFUSED && err != WSAECONNRESET)
#else
		int err = errno;
		if (err != EAGAIN && err != ECONNREFUSED)
#endif
		{
			ERROR_MSG( "WatcherNub::receiveRequest: recvfrom failed\n" );
		}

		insideReceiveRequest_ = false;
		return false;
	}

	// make sure we haven't picked up a weird packet (from when broadcast
	// was on, say ... hey, it could happen!)
	WatcherDataMsg * wdm = (WatcherDataMsg*)requestPacket_;

	if (len < (int)sizeof(WatcherDataMsg))
	{
		ERROR_MSG( "WatcherNub::receiveRequest: Packet is too short\n" );
		insideReceiveRequest_ = false;
		return false;
	}

	if (! (wdm->message == WATCHER_MSG_GET ||
		   wdm->message == WATCHER_MSG_GET_WITH_DESC ||
		   wdm->message == WATCHER_MSG_SET ||
		   wdm->message == WATCHER_MSG_GET2 ||
		   wdm->message == WATCHER_MSG_SET2
		) )
	{
		wrh_->processExtensionMessage( wdm->message,
								requestPacket_ + sizeof( wdm->message ),
								len - sizeof( wdm->message ),
								Mercury::Address( senderAddr.sin_addr.s_addr,
									senderAddr.sin_port ) );
		insideReceiveRequest_ = false;
		return true;
	}


	// Our reply handler for the current request.
	WatcherPacketHandler *packetHandler = NULL;

	// and call back to the program
	switch (wdm->message)
	{
		case WATCHER_MSG_GET:
		case WATCHER_MSG_GET_WITH_DESC:
		{
			// Create the packet reply handler for the current incoming request
			packetHandler = new WatcherPacketHandler( socket_, senderAddr,
					wdm->count, WatcherPacketHandler::WP_VERSION_1, false );

			char	*astr = wdm->string;
			for(int i=0;i<wdm->count;i++)
			{
				wrh_->processWatcherGetRequest( *packetHandler, astr,
					   	(wdm->message == WATCHER_MSG_GET_WITH_DESC) );
				astr += strlen(astr)+1;
			}
		}
		break;

		case WATCHER_MSG_GET2:
		{
			// Create the packet reply handler for the current incoming request
			packetHandler = new WatcherPacketHandler( socket_, senderAddr,
					wdm->count, WatcherPacketHandler::WP_VERSION_2, false );

			char	*astr = wdm->string;
			for(int i=0;i<wdm->count;i++)
			{
				unsigned int & seqNum = (unsigned int &)*astr;
				astr += sizeof(unsigned int);
				wrh_->processWatcherGet2Request( *packetHandler, astr, seqNum );
				astr += strlen(astr)+1;
			}
		}
		break;


		case WATCHER_MSG_SET:
		{
			// Create the packet reply handler for the current incoming request
			packetHandler = new WatcherPacketHandler( socket_, senderAddr,
					wdm->count, WatcherPacketHandler::WP_VERSION_1, true );

			char	*astr = wdm->string;
			for(int i=0;i<wdm->count;i++)
			{
				char	*bstr = astr + strlen(astr)+1;
				wrh_->processWatcherSetRequest( *packetHandler, astr,bstr );
				astr = bstr + strlen(bstr)+1;
			}
		}
		break;


		case WATCHER_MSG_SET2:
		{
			// Create the packet reply handler for the current incoming request
			packetHandler = new WatcherPacketHandler( socket_, senderAddr,
					wdm->count, WatcherPacketHandler::WP_VERSION_2, true );

			char	*astr = wdm->string;
			for(int i=0;i<wdm->count;i++)
			{
				wrh_->processWatcherSet2Request( *packetHandler, astr );
			}
		}
		break;

		default:
		{
			Mercury::Address srcAddr( senderAddr.sin_addr.s_addr,
									senderAddr.sin_port );
			WARNING_MSG( "WatcherNub::receiveRequest: "
						"Unknown message %d from %s\n",
					wdm->message, srcAddr.c_str() );
		}
		break;
	}

	// Start running the packet handler now, it will delete itself when
	// complete.
	if (packetHandler)
	{
		packetHandler->run();
		packetHandler = NULL;
	}

	// and we're done!
	insideReceiveRequest_ = false;

	return true;
}
bool FvNetWatcherNub::ReceiveRequest()
{
	if (!m_bIsInitialised)
	{
		return false;
	}

	sockaddr_in		senderAddr;
	int				len;

	if (m_pkWRHandler == NULL)
	{
		FV_ERROR_MSG( "FvNetWatcherNub::ReceiveRequest: Can't call me before\n"
			"\tcalling setRequestHandler(WatcherRequestHandler*)\n" );
		return false;
	}

	if (m_bInsideReceiveRequest)
	{
		FV_ERROR_MSG( "FvNetWatcherNub::ReceiveRequest: BAD THING NOTICED:\n"
			"\tAttempted re-entrant call to receiveRequest\n" );
		return false;
	}

	m_bInsideReceiveRequest = true;

	len = m_kSocket.RecvFrom( m_pcRequestPacket, FV_NET_WN_PACKET_SIZE, senderAddr );

	if (len == -1)
	{
		// EAGAIN = no packets waiting, ECONNREFUSED = rejected outgoing packet

#ifdef _WIN32
		int err = WSAGetLastError();
		if (err != WSAEWOULDBLOCK && err != WSAECONNREFUSED && err != WSAECONNRESET)
#else
		int err = errno;
		if (err != EAGAIN && err != ECONNREFUSED)
#endif
		{
			FV_ERROR_MSG( "FvNetWatcherNub::ReceiveRequest: recvfrom failed\n" );
		}

		m_bInsideReceiveRequest = false;
		return false;
	}

	FvNetWatcherDataMsg * wdm = (FvNetWatcherDataMsg*)m_pcRequestPacket;

	if (len < (int)sizeof(FvNetWatcherDataMsg))
	{
		FV_ERROR_MSG( "FvNetWatcherNub::ReceiveRequest: Packet is too short\n" );
		m_bInsideReceiveRequest = false;
		return false;
	}

	if (! (wdm->m_iMessage == FV_NET_WATCHER_MSG_GET ||
		   wdm->m_iMessage == FV_NET_WATCHER_MSG_GET_WITH_DESC ||
		   wdm->m_iMessage == FV_NET_WATCHER_MSG_SET ||
		   wdm->m_iMessage == FV_NET_WATCHER_MSG_GET2 ||
		   wdm->m_iMessage == FV_NET_WATCHER_MSG_SET2
		) )
	{
		m_pkWRHandler->ProcessExtensionMessage( wdm->m_iMessage,
								m_pcRequestPacket + sizeof( wdm->m_iMessage ),
								len - sizeof( wdm->m_iMessage ),
								FvNetAddress( senderAddr.sin_addr.s_addr,
									senderAddr.sin_port ) );
		m_bInsideReceiveRequest = false;
		return true;
	}

	FvNetWatcherPacketHandler *packetHandler = NULL;

	switch (wdm->m_iMessage)
	{
		case FV_NET_WATCHER_MSG_GET:
		case FV_NET_WATCHER_MSG_GET_WITH_DESC:
		{
			packetHandler = new FvNetWatcherPacketHandler( m_kSocket, senderAddr,
					wdm->m_iCount, FvNetWatcherPacketHandler::WP_VERSION_1, false );

			char	*astr = wdm->m_acString;
			for(int i=0;i<wdm->m_iCount;i++)
			{
				m_pkWRHandler->ProcessWatcherGetRequest( *packetHandler, astr,
					   	(wdm->m_iMessage == FV_NET_WATCHER_MSG_GET_WITH_DESC) );
				astr += strlen(astr)+1;
			}
		}
		break;

		case FV_NET_WATCHER_MSG_GET2:
		{
			packetHandler = new FvNetWatcherPacketHandler( m_kSocket, senderAddr,
					wdm->m_iCount, FvNetWatcherPacketHandler::WP_VERSION_2, false );

			char	*astr = wdm->m_acString;
			for(int i=0;i<wdm->m_iCount;i++)
			{
				unsigned int & seqNum = (unsigned int &)*astr;
				astr += sizeof(unsigned int);
				m_pkWRHandler->ProcessWatcherGet2Request( *packetHandler, astr, seqNum );
				astr += strlen(astr)+1;
			}
		}
		break;


		case FV_NET_WATCHER_MSG_SET:
		{
			packetHandler = new FvNetWatcherPacketHandler( m_kSocket, senderAddr,
					wdm->m_iCount, FvNetWatcherPacketHandler::WP_VERSION_1, true );

			char	*astr = wdm->m_acString;
			for(int i=0;i<wdm->m_iCount;i++)
			{
				char	*bstr = astr + strlen(astr)+1;
				m_pkWRHandler->ProcessWatcherSetRequest( *packetHandler, astr,bstr );
				astr = bstr + strlen(bstr)+1;
			}
		}
		break;


		case FV_NET_WATCHER_MSG_SET2:
		{
			packetHandler = new FvNetWatcherPacketHandler( m_kSocket, senderAddr,
					wdm->m_iCount, FvNetWatcherPacketHandler::WP_VERSION_2, true );

			char	*astr = wdm->m_acString;
			for(int i=0;i<wdm->m_iCount;i++)
			{
				m_pkWRHandler->ProcessWatcherSet2Request( *packetHandler, astr );
			}
		}
		break;

		default:
		{
			FvNetAddress srcAddr( senderAddr.sin_addr.s_addr,
									senderAddr.sin_port );
			FV_WARNING_MSG( "FvNetWatcherNub::ReceiveRequest: "
						"Unknown message %d from %s\n",
					wdm->m_iMessage, srcAddr.c_str() );
		}
		break;
	}

	if (packetHandler)
	{
		packetHandler->Run();
		packetHandler = NULL;
	}

	m_bInsideReceiveRequest = false;

	return true;
}