main.cpp 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. #include <iostream>
  2. #include <fstream>
  3. #include <sstream>
  4. #include <vector>
  5. #include <thread>
  6. #include <tuple>
  7. #include <grpc++/grpc++.h>
  8. #include <simplechat.pb.h>
  9. #include <simplechat.grpc.pb.h>
  10. using namespace ::qtprotobuf::examples;
  11. class MessageListHandler;
  12. class UserListHandler;
  13. class SimpleChatService final : public SimpleChat::WithAsyncMethod_messageList<SimpleChat::WithAsyncMethod_usersOnline<SimpleChat::Service>> {
  14. public:
  15. Users m_usersOnline;
  16. Users m_usersDatabase;
  17. ChatMessages m_messages;
  18. SimpleChatService() {
  19. User *newUser = m_usersDatabase.add_users();
  20. newUser->set_name("user1");
  21. newUser->set_password("d8578edf8458ce06fbc5bb76a58c5ca4");
  22. newUser = m_usersDatabase.add_users();
  23. newUser->set_name("user2");
  24. newUser->set_password("d8578edf8458ce06fbc5bb76a58c5ca4");
  25. newUser = m_usersDatabase.add_users();
  26. newUser->set_name("user3");
  27. newUser->set_password("d8578edf8458ce06fbc5bb76a58c5ca4");
  28. newUser = m_usersDatabase.add_users();
  29. newUser->set_name("user4");
  30. newUser->set_password("d8578edf8458ce06fbc5bb76a58c5ca4");
  31. newUser = m_usersDatabase.add_users();
  32. newUser->set_name("user5");
  33. newUser->set_password("d8578edf8458ce06fbc5bb76a58c5ca4");
  34. }
  35. void loginUser(MessageListHandler *userHandler);
  36. void updateActiveUsers() {
  37. for(unsigned int i = 0; i < (m_activeUserListClients.size() - 1); i++) {
  38. m_activeUserListClients[i]->Write(m_usersOnline, nullptr);
  39. }
  40. }
  41. void updateMessages() {
  42. for(unsigned int i = 0; i < (m_activeClients.size() - 1); i++) {
  43. m_activeClients[i]->Write(m_messages, nullptr);
  44. }
  45. }
  46. bool checkUserCredentials(const std::string &name, const std::string &password) {
  47. for(int i = 0; i < m_usersDatabase.users_size(); i++) {
  48. if (m_usersDatabase.users(i).name() == name && m_usersDatabase.users(i).password() == password) {
  49. return true;
  50. }
  51. }
  52. return false;
  53. }
  54. std::tuple<std::string, std::string> extractCredentials(grpc::ServerContext *context) {
  55. std::string name{};
  56. std::string password{};
  57. for (auto it = context->client_metadata().begin(); it != context->client_metadata().end(); ++it) {
  58. if ((*it).first == std::string("user-name")) {
  59. name = std::string((*it).second.data());
  60. }
  61. if ((*it).first == std::string("user-password")) {
  62. password = std::string((*it).second.data());
  63. }
  64. }
  65. return std::make_tuple(name, password);
  66. }
  67. ::grpc::Status sendMessage(grpc::ServerContext *context, const ChatMessage *request, None *) override
  68. {
  69. std::string name{};
  70. std::string password{};
  71. std::tie(name, password) = extractCredentials(context);
  72. if (!checkUserCredentials(name, password)) {
  73. return ::grpc::Status(::grpc::StatusCode::UNAUTHENTICATED, "User or login are invalid");
  74. }
  75. ChatMessage *msg = m_messages.add_messages();
  76. *msg = *request;
  77. msg->set_from(name);
  78. updateMessages();
  79. return ::grpc::Status();
  80. }
  81. std::vector<::grpc::ServerAsyncWriter<ChatMessages> *> m_activeClients;
  82. std::vector<::grpc::ServerAsyncWriter<Users> *> m_activeUserListClients;
  83. };
  84. class MessageListHandler {
  85. public:
  86. MessageListHandler(SimpleChatService* service, ::grpc::ServerCompletionQueue* cq) : tag_(0xdeadbeef)
  87. , writer_(&ctx_)
  88. , cq_(cq)
  89. {
  90. service->RequestmessageList(&ctx_, &request_, &writer_, cq_, cq_, &tag_);
  91. service->loginUser(this);
  92. }
  93. int tag_;
  94. grpc::ServerContext ctx_;
  95. None request_;
  96. ::grpc::ServerAsyncWriter< ::qtprotobuf::examples::ChatMessages> writer_;
  97. ::grpc::ServerCompletionQueue* cq_;
  98. };
  99. void SimpleChatService::loginUser(MessageListHandler *handler) {
  100. m_activeClients.push_back(&(handler->writer_));
  101. //TODO: update online if required here
  102. }
  103. int main(int argc, char *argv[])
  104. {
  105. std::string server_address("localhost:65002");
  106. SimpleChatService service;
  107. std::ifstream tfile("cert.pem");
  108. std::stringstream cert;
  109. cert << tfile.rdbuf();
  110. tfile.close();
  111. tfile.open("key.pem");
  112. std::stringstream key;
  113. key << tfile.rdbuf();
  114. tfile.close();
  115. grpc::ServerBuilder builder;
  116. grpc::SslServerCredentialsOptions opts(GRPC_SSL_DONT_REQUEST_CLIENT_CERTIFICATE);
  117. opts.pem_key_cert_pairs.push_back({key.str(), cert.str()});
  118. builder.AddListeningPort(server_address, grpc::SslServerCredentials(opts));
  119. builder.RegisterService(&service);
  120. std::unique_ptr<grpc::ServerCompletionQueue> cq = builder.AddCompletionQueue();
  121. std::unique_ptr<grpc::Server> server(builder.BuildAndStart());
  122. std::cout << "Server listening on " << server_address << std::endl;
  123. MessageListHandler *last = new MessageListHandler(&service, cq.get());
  124. while (true) {
  125. unsigned int *tag;
  126. bool ok;
  127. cq->Next((void**)&tag, &ok);
  128. if (tag == nullptr) {
  129. continue;
  130. }
  131. if ((*tag) == 0xdeadbeef) {
  132. std::string name{};
  133. std::string password{};
  134. std::tie(name, password) = service.extractCredentials(&(last->ctx_));
  135. if (!service.checkUserCredentials(name, password)) {
  136. std::cout << "Authentication failed" << std::endl;
  137. last->writer_.Finish(::grpc::Status(::grpc::StatusCode::UNAUTHENTICATED, "User or login are invalid"), nullptr);
  138. last = new MessageListHandler(&service, cq.get());
  139. continue;
  140. }
  141. std::cout << "Authentication ok update user chat" << std::endl;
  142. last->writer_.Write(service.m_messages, nullptr);
  143. last = new MessageListHandler(&service, cq.get());
  144. }
  145. }
  146. }