Example #1
0
bool StopNovad()
{
	bool retSuccess;
	//Keep the scope of the following Ticket out of the call to Disconnect
	{
		Ticket ticket = MessageManager::Instance().StartConversation(IPCSocketFD);

		ControlMessage killRequest(CONTROL_EXIT_REQUEST);
		if(!MessageManager::Instance().WriteMessage(ticket, &killRequest))
		{
			LOG(ERROR, "Error sending command to NOVAD (CONTROL_EXIT_REQUEST)", "");
			return false;
		}

		Message *reply = MessageManager::Instance().ReadMessage(ticket);
		if(reply->m_messageType == ERROR_MESSAGE && ((ErrorMessage*)reply)->m_errorType == ERROR_TIMEOUT)
		{
			LOG(ERROR, "Timeout error when waiting for message reply", "");
			delete ((ErrorMessage*)reply);
			return false;
		}
		if(reply->m_messageType != CONTROL_MESSAGE )
		{
			LOG(ERROR, "Received the wrong kind of reply message", "");
			reply->DeleteContents();
			delete reply;
			return false;
		}

		ControlMessage *killReply = (ControlMessage*)reply;
		if( killReply->m_controlType != CONTROL_EXIT_REPLY )
		{
			LOG(ERROR, "Received the wrong kind of control message", "");
			reply->DeleteContents();
			delete reply;
			return false;
		}
		retSuccess = killReply->m_success;
		delete killReply;

		LOG(DEBUG, "Call to StopNovad complete", "");
	}
	DisconnectFromNovad();

	return retSuccess;
}
Example #2
0
void *EventDispatcherThread(void *arg)
{
	int ret = event_base_dispatch(libeventBase);
	if(ret != 0)
	{
		stringstream ss;
		ss << ret;
		//LOG(DEBUG, "Message loop ended. Error code: " + ss.str(), "");
	}
	else
	{
		LOG(DEBUG, "Message loop ended cleanly.", "");
	}

	DisconnectFromNovad();
	return NULL;
}
Example #3
0
bool IsNovadUp(bool tryToConnect)
{
	bool isUp = true;
	if(tryToConnect)
	{
		//If we couldn't connect, then it's definitely not up
		if(!ConnectToNovad())
		{
			return false;
		}
	}

	//Funny syntax just so I can break; out of the context
	do
	{
		Ticket ticket = MessageManager::Instance().StartConversation(IPCSocketFD);

		RequestMessage ping(REQUEST_PING);
		if(!MessageManager::Instance().WriteMessage(ticket, &ping))
		{
			//There was an error in sending the message
			isUp = false;
			break;
		}

		Message *reply = MessageManager::Instance().ReadMessage(ticket);
		if(reply->m_messageType == ERROR_MESSAGE && ((ErrorMessage*)reply)->m_errorType == ERROR_TIMEOUT)
		{
			LOG(WARNING, "Timeout error when waiting for message reply", "");
			reply->DeleteContents();
			delete reply;
			isUp = false;
			break;
		}

		if(reply->m_messageType == ERROR_MESSAGE )
		{
			ErrorMessage *error = (ErrorMessage*)reply;
			if(error->m_errorType == ERROR_SOCKET_CLOSED)
			{
				// This was breaking things during the mess of isNovadUp calls
				// when the QT GUi starts and connects to novad. If there was some
				// important reason for it being here that I don't know about, we
				// might need to put it back and track down why exactly it was
				// causing problems.
				//CloseNovadConnection();
			}
			delete error;
			isUp = false;
			break;
		}
		if(reply->m_messageType != REQUEST_MESSAGE )
		{
			//Received the wrong kind of message
			reply->DeleteContents();
			delete reply;
			isUp = false;
			break;
		}

		RequestMessage *pong = (RequestMessage*)reply;
		if(pong->m_requestType != REQUEST_PONG)
		{
			//Received the wrong kind of control message
			pong->DeleteContents();
			isUp = false;
		}
		delete pong;
	}while(0);

	if(isUp == false)
	{
		DisconnectFromNovad();
	}
	return isUp;
}
Example #4
0
bool ConnectToNovad()
{
	if(IsNovadUp(false))
	{
		return true;
	}

	DisconnectFromNovad();

	//Create new base
	if(libeventBase == NULL)
	{
		evthread_use_pthreads();
		libeventBase = event_base_new();
		pthread_mutex_init(&bufferevent_mutex, NULL);
	}

	//Builds the key path
	string key = Config::Inst()->GetPathHome();
	key += "/config/keys";
	key += NOVAD_LISTEN_FILENAME;

	//Builds the address
	struct sockaddr_un novadAddress;
	novadAddress.sun_family = AF_UNIX;
	memset(novadAddress.sun_path, '\0', sizeof(novadAddress.sun_path));
	strncpy(novadAddress.sun_path, key.c_str(), sizeof(novadAddress.sun_path));

	{
		Lock buffereventLock(&bufferevent_mutex);
		bufferevent = bufferevent_socket_new(libeventBase, -1,
				BEV_OPT_CLOSE_ON_FREE | BEV_OPT_THREADSAFE |  BEV_OPT_UNLOCK_CALLBACKS | BEV_OPT_DEFER_CALLBACKS );
		if(bufferevent == NULL)
		{
			LOG(ERROR, "Unable to create a socket to Nova", "");
			DisconnectFromNovad();
			return false;
		}

		bufferevent_setcb(bufferevent, MessageManager::MessageDispatcher, NULL, MessageManager::ErrorDispatcher, NULL);

		if(bufferevent_enable(bufferevent, EV_READ) == -1)
		{
			LOG(ERROR, "Unable to enable socket events", "");
			return false;
		}

		if(bufferevent_socket_connect(bufferevent, (struct sockaddr *)&novadAddress, sizeof(novadAddress)) == -1)
		{
			bufferevent = NULL;
			LOG(DEBUG, "Unable to connect to NOVAD: "+string(strerror(errno))+".", "");
			return false;
		}

		IPCSocketFD = bufferevent_getfd(bufferevent);
		if(IPCSocketFD == -1)
		{
			LOG(DEBUG, "Unable to connect to Novad: "+string(strerror(errno))+".", "");
			bufferevent_free(bufferevent);
			bufferevent = NULL;
			return false;
		}

		if(evutil_make_socket_nonblocking(IPCSocketFD) == -1)
		{
			LOG(DEBUG, "Unable to connect to Novad", "Could not set socket to non-blocking mode");
			bufferevent_free(bufferevent);
			bufferevent = NULL;
			return false;
		}

		MessageManager::Instance().DeleteEndpoint(IPCSocketFD);
		MessageManager::Instance().StartSocket(IPCSocketFD, bufferevent);
	}
	pthread_create(&eventDispatchThread, NULL, EventDispatcherThread, NULL);

	//Test if the connection is up
	Ticket ticket = MessageManager::Instance().StartConversation(IPCSocketFD);

	RequestMessage connectRequest(REQUEST_PING);
	if(!MessageManager::Instance().WriteMessage(ticket, &connectRequest))
	{
		return false;
	}

	Message *reply = MessageManager::Instance().ReadMessage(ticket);
	if(reply->m_messageType == ERROR_MESSAGE && ((ErrorMessage*)reply)->m_errorType == ERROR_TIMEOUT)
	{
		LOG(DEBUG, "Timeout error when waiting for message reply", "");
		delete reply;
		return false;
	}

	if(reply->m_messageType != REQUEST_MESSAGE)
	{
		stringstream s;
		s << "Expected message type of REQUEST_MESSAGE but got " << reply->m_messageType;
		LOG(DEBUG, s.str(), "");

		reply->DeleteContents();
		delete reply;
		return false;
	}
	RequestMessage *connectionReply = (RequestMessage*)reply;
	if(connectionReply->m_contents.m_requesttype() != REQUEST_PONG)
	{
		stringstream s;
		s << "Expected control type of CONTROL_CONNECT_REPLY but got " <<connectionReply->m_contents.m_requesttype();
		LOG(DEBUG, s.str(), "");

		reply->DeleteContents();
		delete reply;
		return false;
	}
	delete connectionReply;

	return true;
}