oatpp / oatpp-websocket

oatpp-websocket submodule.

Home Page:https://oatpp.io/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

unable to get the websocket instance of a websocket::connectionHandler object

Saadharta opened this issue · comments

commented

Hello there :)

I feel like i stumbled upon an edgy use case:

My server is primarily used for a REST API; however i also need to use the websocket mechanism so that my server has the ability to send to its clients that something happened, prompting the clients to interrogate the REST API for more details.

I don't need to send a lot; a high level access to WebSocket::Listener::onPing() might do the trick.

Apart rewriting my own sauce of the ConnectionProvider class (more specifically the Task subclass), is there any server-side ways to
access opened websocket connections?

( It is more-or-less an issue related to #37 )

Kind regards,

Saadharta

commented

Update: i followed loosely the AsyncRoomsServer example; i added a getter on the current instance of Lobby and added a getter on it's m_rooms map;

I also modified Lobby a little bit to make full use of the m_room map:

std::shared_ptr<Room> Lobby::getOrCreateRoom(const oatpp::String& roomName) {
  std::lock_guard<std::mutex> lock(m_roomsMutex);
  std::shared_ptr<Room>& room = m_rooms[roomName]; // may not be needed?
  if(!room) {
    room = std::make_shared<Room>(roomName);
    m_rooms[roomName] = room; // make sense to fill the Lobby's room map if there is a new room
  }
  return room;
}

void Lobby::onAfterCreate_NonBlocking(const std::shared_ptr<AsyncWebSocket>& socket, const std::shared_ptr<const ParameterMap>& params) {

  auto roomName = params->find("roomName")->second;
  auto nickname = params->find("nickname")->second;
  auto room = getOrCreateRoom(roomName);

  auto peer = std::make_shared<Peer>(socket, room, nickname, obtainNewUserId());
  socket->setListener(peer);

  m_room[roomName]->addPeer(peer); // using the map instead of the room instance
  m_room[roomName]->sendMessage(nickname + " joined " + roomName); //using the map instead of the room instance
}

after some tweakings, in my main mathod (i am not using the Server class for practical purposes)

// Run """server"""
std::shared_ptr<const std::unordered_map<oatpp::String, oatpp::String>> params;
oatpp::provider::ResourceHandle<oatpp::network::ConnectionHandler::IOStream> cH;

while (true) {
	cH = connectionProvider->get();
	if (cH.object) 
	{
		serverConnectionHandler->handleConnection(cH, params /* null params? */);
// give a bit of time for the request to be processed
		std::this_thread::sleep_for(std::chrono::milliseconds(200));
// who is my client?
		std::cout
			<< "Incoming connection from "
			<< cH.object->getInputStreamContext().getProperties().get("peer_address")->c_str()
			<< ":"
			<< cH.object->getInputStreamContext().getProperties().get("peer_port")->c_str();
// who are my connections?
		for (auto wsR : Lobby::getLobbyInstance()->getRooms()) 
		{
			std::cout 
				<< " on endpoint " 
				<< wsR.first->c_str()
 				<< std::endl;
			wsR.second->sendMessage("I SEE YOU LITTLE CLIENT ON " + wsR.first->c_str() );
		}
	}
}

It is not perfect but it shows that it is possible for the server to send a message by itself to clients.

Saadharta