CommunicationSocket.cpp 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. /**
  2. * Copyright (c) 2000-2013 Liferay, Inc. All rights reserved.
  3. *
  4. * This library is free software; you can redistribute it and/or modify it under
  5. * the terms of the GNU Lesser General Public License as published by the Free
  6. * Software Foundation; either version 2.1 of the License, or (at your option)
  7. * any later version.
  8. *
  9. * This library is distributed in the hope that it will be useful, but WITHOUT
  10. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  11. * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
  12. * details.
  13. */
  14. #include "CommunicationSocket.h"
  15. #include "StringUtil.h"
  16. #include "WinShellExtConstants.h"
  17. #include <iostream>
  18. #include <vector>
  19. #include <array>
  20. #include <fstream>
  21. #define DEFAULT_BUFLEN 4096
  22. using namespace std;
  23. namespace {
  24. std::wstring getUserName() {
  25. DWORD len = DEFAULT_BUFLEN;
  26. TCHAR buf[DEFAULT_BUFLEN];
  27. if (GetUserName(buf, &len)) {
  28. return std::wstring(&buf[0], len);
  29. } else {
  30. return std::wstring();
  31. }
  32. }
  33. }
  34. std::wstring CommunicationSocket::DefaultPipePath()
  35. {
  36. auto pipename = std::wstring(LR"(\\.\pipe\)");
  37. pipename += std::wstring(UTIL_PIPE_APP_NAME);
  38. pipename += L"-";
  39. pipename += getUserName();
  40. return pipename;
  41. }
  42. CommunicationSocket::CommunicationSocket()
  43. : _pipe(INVALID_HANDLE_VALUE)
  44. {
  45. }
  46. CommunicationSocket::~CommunicationSocket()
  47. {
  48. Close();
  49. }
  50. bool CommunicationSocket::Close()
  51. {
  52. if (_pipe == INVALID_HANDLE_VALUE) {
  53. return false;
  54. }
  55. CloseHandle(_pipe);
  56. _pipe = INVALID_HANDLE_VALUE;
  57. return true;
  58. }
  59. bool CommunicationSocket::Connect(const std::wstring &pipename)
  60. {
  61. _pipe = CreateFile(pipename.data(), GENERIC_READ | GENERIC_WRITE, 0, nullptr, OPEN_EXISTING, 0, nullptr);
  62. if (_pipe == INVALID_HANDLE_VALUE) {
  63. return false;
  64. }
  65. return true;
  66. }
  67. bool CommunicationSocket::SendMsg(const wchar_t* message) const
  68. {
  69. auto utf8_msg = StringUtil::toUtf8(message);
  70. DWORD numBytesWritten = 0;
  71. auto result = WriteFile( _pipe, utf8_msg.c_str(), DWORD(utf8_msg.size()), &numBytesWritten, nullptr);
  72. if (result) {
  73. return true;
  74. } else {
  75. const_cast<CommunicationSocket*>(this)->Close();
  76. return false;
  77. }
  78. }
  79. bool CommunicationSocket::ReadLine(wstring* response)
  80. {
  81. if (!response) {
  82. return false;
  83. }
  84. response->clear();
  85. if (_pipe == INVALID_HANDLE_VALUE) {
  86. return false;
  87. }
  88. while (true) {
  89. int lbPos = 0;
  90. auto it = std::find(_buffer.begin() + lbPos, _buffer.end(), '\n');
  91. if (it != _buffer.end()) {
  92. *response = StringUtil::toUtf16(_buffer.data(), DWORD(it - _buffer.begin()));
  93. _buffer.erase(_buffer.begin(), it + 1);
  94. return true;
  95. }
  96. std::array<char, 128> resp_utf8 = {};
  97. DWORD numBytesRead = 0;
  98. DWORD totalBytesAvailable = 0;
  99. if (!PeekNamedPipe(_pipe, nullptr, 0, nullptr, &totalBytesAvailable, nullptr)) {
  100. Close();
  101. return false;
  102. }
  103. if (totalBytesAvailable == 0) {
  104. return false;
  105. }
  106. if (!ReadFile(_pipe, resp_utf8.data(), DWORD(resp_utf8.size()), &numBytesRead, nullptr)) {
  107. Close();
  108. return false;
  109. }
  110. if (numBytesRead <= 0) {
  111. return false;
  112. }
  113. _buffer.insert(_buffer.end(), resp_utf8.begin(), resp_utf8.begin()+numBytesRead);
  114. continue;
  115. }
  116. }