123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165 |
- #include <iostream>
- #include <fstream>
- #include <sstream>
- #include <vector>
- #include <thread>
- #include <tuple>
- #include <grpc++/grpc++.h>
- #include <simplechat.pb.h>
- #include <simplechat.grpc.pb.h>
- using namespace ::qtprotobuf::examples;
- class MessageListHandler;
- class UserListHandler;
- class SimpleChatService final : public SimpleChat::WithAsyncMethod_messageList<SimpleChat::WithAsyncMethod_usersOnline<SimpleChat::Service>> {
- public:
- Users m_usersOnline;
- Users m_usersDatabase;
- ChatMessages m_messages;
- SimpleChatService() {
- User *newUser = m_usersDatabase.add_users();
- newUser->set_name("user1");
- newUser->set_password("d8578edf8458ce06fbc5bb76a58c5ca4");
- newUser = m_usersDatabase.add_users();
- newUser->set_name("user2");
- newUser->set_password("d8578edf8458ce06fbc5bb76a58c5ca4");
- newUser = m_usersDatabase.add_users();
- newUser->set_name("user3");
- newUser->set_password("d8578edf8458ce06fbc5bb76a58c5ca4");
- newUser = m_usersDatabase.add_users();
- newUser->set_name("user4");
- newUser->set_password("d8578edf8458ce06fbc5bb76a58c5ca4");
- newUser = m_usersDatabase.add_users();
- newUser->set_name("user5");
- newUser->set_password("d8578edf8458ce06fbc5bb76a58c5ca4");
- }
- void loginUser(MessageListHandler *userHandler);
- void updateActiveUsers() {
- for(unsigned int i = 0; i < (m_activeUserListClients.size() - 1); i++) {
- m_activeUserListClients[i]->Write(m_usersOnline, nullptr);
- }
- }
- void updateMessages() {
- for(unsigned int i = 0; i < (m_activeClients.size() - 1); i++) {
- m_activeClients[i]->Write(m_messages, nullptr);
- }
- }
- bool checkUserCredentials(const std::string &name, const std::string &password) {
- for(int i = 0; i < m_usersDatabase.users_size(); i++) {
- if (m_usersDatabase.users(i).name() == name && m_usersDatabase.users(i).password() == password) {
- return true;
- }
- }
- return false;
- }
- std::tuple<std::string, std::string> extractCredentials(grpc::ServerContext *context) {
- std::string name{};
- std::string password{};
- for (auto it = context->client_metadata().begin(); it != context->client_metadata().end(); ++it) {
- if ((*it).first == std::string("user-name")) {
- name = std::string((*it).second.data());
- }
- if ((*it).first == std::string("user-password")) {
- password = std::string((*it).second.data());
- }
- }
- return std::make_tuple(name, password);
- }
- ::grpc::Status sendMessage(grpc::ServerContext *context, const ChatMessage *request, None *) override
- {
- std::string name{};
- std::string password{};
- std::tie(name, password) = extractCredentials(context);
- if (!checkUserCredentials(name, password)) {
- return ::grpc::Status(::grpc::StatusCode::UNAUTHENTICATED, "User or login are invalid");
- }
- ChatMessage *msg = m_messages.add_messages();
- *msg = *request;
- msg->set_from(name);
- updateMessages();
- return ::grpc::Status();
- }
- std::vector<::grpc::ServerAsyncWriter<ChatMessages> *> m_activeClients;
- std::vector<::grpc::ServerAsyncWriter<Users> *> m_activeUserListClients;
- };
- class MessageListHandler {
- public:
- MessageListHandler(SimpleChatService *service, ::grpc::ServerCompletionQueue *cq) : tag_(0xdeadbeef)
- , writer_(&ctx_)
- , cq_(cq)
- {
- service->RequestmessageList(&ctx_, &request_, &writer_, cq_, cq_, &tag_);
- service->loginUser(this);
- }
- int tag_;
- grpc::ServerContext ctx_;
- None request_;
- ::grpc::ServerAsyncWriter< ::qtprotobuf::examples::ChatMessages> writer_;
- ::grpc::ServerCompletionQueue *cq_;
- };
- void SimpleChatService::loginUser(MessageListHandler *handler) {
- m_activeClients.push_back(&(handler->writer_));
- //TODO: update online if required here
- }
- int main(int argc, char *argv[])
- {
- std::string server_address("localhost:65002");
- SimpleChatService service;
- std::ifstream tfile("cert.pem");
- std::stringstream cert;
- cert << tfile.rdbuf();
- tfile.close();
- tfile.open("key.pem");
- std::stringstream key;
- key << tfile.rdbuf();
- tfile.close();
- grpc::ServerBuilder builder;
- grpc::SslServerCredentialsOptions opts(GRPC_SSL_DONT_REQUEST_CLIENT_CERTIFICATE);
- opts.pem_key_cert_pairs.push_back({key.str(), cert.str()});
- builder.AddListeningPort(server_address, grpc::SslServerCredentials(opts));
- builder.RegisterService(&service);
- std::unique_ptr<grpc::ServerCompletionQueue> cq = builder.AddCompletionQueue();
- std::unique_ptr<grpc::Server> server(builder.BuildAndStart());
- std::cout << "Server listening on " << server_address << std::endl;
- MessageListHandler *last = new MessageListHandler(&service, cq.get());
- while (true) {
- unsigned int *tag;
- bool ok;
- cq->Next((void**)&tag, &ok);
- if (tag == nullptr) {
- continue;
- }
- if ((*tag) == 0xdeadbeef) {
- std::string name{};
- std::string password{};
- std::tie(name, password) = service.extractCredentials(&(last->ctx_));
- if (!service.checkUserCredentials(name, password)) {
- std::cout << "Authentication failed" << std::endl;
- last->writer_.Finish(::grpc::Status(::grpc::StatusCode::UNAUTHENTICATED, "User or login are invalid"), nullptr);
- last = new MessageListHandler(&service, cq.get());
- continue;
- }
- std::cout << "Authentication ok update user chat" << std::endl;
- last->writer_.Write(service.m_messages, nullptr);
- last = new MessageListHandler(&service, cq.get());
- }
- }
- }
|