main.cpp 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  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. name.resize(5);
  61. }
  62. if ((*it).first == std::string("user-password")) {
  63. password = std::string((*it).second.data());
  64. password.resize(32);
  65. }
  66. }
  67. return std::make_tuple(name, password);
  68. }
  69. ::grpc::Status sendMessage(grpc::ServerContext *context, const ChatMessage *request, None *) override
  70. {
  71. std::string name{""};
  72. std::string password{""};
  73. std::tie(name, password) = extractCredentials(context);
  74. if (!checkUserCredentials(name, password)) {
  75. return ::grpc::Status(::grpc::StatusCode::UNAUTHENTICATED, "User or login are invalid");
  76. }
  77. ChatMessage *msg = m_messages.add_messages();
  78. *msg = *request;
  79. msg->set_from(name);
  80. updateMessages();
  81. return ::grpc::Status();
  82. }
  83. std::vector<::grpc::ServerAsyncWriter<ChatMessages> *> m_activeClients;
  84. std::vector<::grpc::ServerAsyncWriter<Users> *> m_activeUserListClients;
  85. };
  86. class MessageListHandler {
  87. public:
  88. MessageListHandler(SimpleChatService *service, ::grpc::ServerCompletionQueue *cq) : tag_(0xdeadbeef)
  89. , writer_(&ctx_)
  90. , cq_(cq)
  91. {
  92. service->RequestmessageList(&ctx_, &request_, &writer_, cq_, cq_, &tag_);
  93. service->loginUser(this);
  94. }
  95. unsigned int tag_;
  96. grpc::ServerContext ctx_;
  97. None request_;
  98. ::grpc::ServerAsyncWriter< ::qtprotobuf::examples::ChatMessages> writer_;
  99. ::grpc::ServerCompletionQueue *cq_;
  100. };
  101. void SimpleChatService::loginUser(MessageListHandler *handler) {
  102. m_activeClients.push_back(&(handler->writer_));
  103. //TODO: update online if required here
  104. }
  105. int main(int, char *[])
  106. {
  107. std::string server_address("localhost:65002");
  108. SimpleChatService service;
  109. std::ifstream tfile("cert.pem");
  110. std::stringstream cert;
  111. cert << tfile.rdbuf();
  112. tfile.close();
  113. tfile.open("key.pem");
  114. std::stringstream key;
  115. key << tfile.rdbuf();
  116. tfile.close();
  117. grpc::ServerBuilder builder;
  118. grpc::SslServerCredentialsOptions opts(GRPC_SSL_DONT_REQUEST_CLIENT_CERTIFICATE);
  119. opts.pem_key_cert_pairs.push_back({key.str(), cert.str()});
  120. builder.AddListeningPort(server_address, grpc::SslServerCredentials(opts));
  121. builder.RegisterService(&service);
  122. std::unique_ptr<grpc::ServerCompletionQueue> cq = builder.AddCompletionQueue();
  123. std::unique_ptr<grpc::Server> server(builder.BuildAndStart());
  124. std::cout << "Server listening on " << server_address << std::endl;
  125. MessageListHandler *last = new MessageListHandler(&service, cq.get());
  126. while (true) {
  127. unsigned int *tag;
  128. bool ok;
  129. cq->Next(reinterpret_cast<void**>(&tag), &ok);
  130. if (tag == nullptr) {
  131. continue;
  132. }
  133. if (!ok) {
  134. std::cout << "0xdeadbeef done";
  135. }
  136. if ((*tag) == 0xdeadbeef) {
  137. std::string name{""};
  138. std::string password{""};
  139. std::tie(name, password) = service.extractCredentials(&(last->ctx_));
  140. if (!service.checkUserCredentials(name, password)) {
  141. std::cout << "Authentication failed" << std::endl;
  142. last->writer_.Finish(::grpc::Status(::grpc::StatusCode::UNAUTHENTICATED, "User or login are invalid"), nullptr);
  143. last = new MessageListHandler(&service, cq.get());
  144. continue;
  145. }
  146. std::cout << "Authentication ok update user chat" << std::endl;
  147. last->writer_.Write(service.m_messages, nullptr);
  148. last = new MessageListHandler(&service, cq.get());
  149. } else {
  150. std::cout << "0xdeadbeef done";
  151. }
  152. }
  153. }