Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Closed
Saadharta opened this issue May 25, 2023 · 1 comment

Comments

@Saadharta
Copy link

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

@Saadharta Saadharta changed the title unable to get a websocket instance from websocket::connectionHnalder unable to get the websocket instance of a websocket::connectionHandler object May 25, 2023
@Saadharta
Copy link
Author

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant