main.cpp 5.8 KB

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