PageRenderTime 33ms CodeModel.GetById 13ms RepoModel.GetById 1ms app.codeStats 0ms

/mordor/streams/namedpipe.cpp

http://github.com/mozy/mordor
C++ | 139 lines | 124 code | 13 blank | 2 comment | 36 complexity | 2561454902be8bd28f3b9e7bdad6cba0 MD5 | raw file
Possible License(s): BSD-3-Clause
  1. // Copyright (c) 2009 - Mozy, Inc.
  2. #include "namedpipe.h"
  3. #include "mordor/assert.h"
  4. #include "mordor/exception.h"
  5. #include "mordor/log.h"
  6. #include "mordor/runtime_linking.h"
  7. #include "mordor/string.h"
  8. namespace Mordor {
  9. static Logger::ptr g_log = Log::lookup("mordor:streams::namedpipe");
  10. NamedPipeStream::NamedPipeStream(const std::string &name, Flags flags, IOManager *ioManager, Scheduler *scheduler, DWORD pipeModeFlags)
  11. {
  12. init(toUtf16(name), flags, pipeModeFlags,ioManager, scheduler);
  13. }
  14. NamedPipeStream::NamedPipeStream(const std::wstring &name, Flags flags, IOManager *ioManager, Scheduler *scheduler, DWORD pipeModeFlags)
  15. {
  16. init(name, flags, pipeModeFlags, ioManager, scheduler);
  17. }
  18. void NamedPipeStream::init(const std::wstring &name, Flags flags, DWORD pipeModeFlags, IOManager *ioManager, Scheduler *scheduler)
  19. {
  20. if (pipeModeFlags == (DWORD)-1) {
  21. pipeModeFlags = PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT;
  22. }
  23. HANDLE hPipe = CreateNamedPipeW(name.c_str(),
  24. (DWORD)flags | (ioManager ? FILE_FLAG_OVERLAPPED : 0),
  25. pipeModeFlags,
  26. PIPE_UNLIMITED_INSTANCES,
  27. 0, 0, 0, NULL);
  28. error_t error = lastError();
  29. MORDOR_LOG_LEVEL(g_log, hPipe == INVALID_HANDLE_VALUE ? Log::ERROR : Log::VERBOSE)
  30. << this << " CreateNamedPipeW(" << toUtf8(name) << ", " << flags
  31. << "): " << hPipe << " (" << error << ")";
  32. if (hPipe == INVALID_HANDLE_VALUE)
  33. MORDOR_THROW_EXCEPTION_FROM_ERROR_API(error, "CreateNamedPipeW");
  34. HandleStream::init(hPipe, ioManager, scheduler);
  35. m_supportsRead = !!(flags & READ);
  36. m_supportsWrite = !!(flags & WRITE);
  37. }
  38. void
  39. NamedPipeStream::close(CloseType type)
  40. {
  41. if (m_hFile != INVALID_HANDLE_VALUE) {
  42. SchedulerSwitcher switcher(m_scheduler);
  43. BOOL ret = DisconnectNamedPipe(m_hFile);
  44. error_t error = lastError();
  45. MORDOR_LOG_VERBOSE(g_log) << this << " DisconnectNamedPipe(" << m_hFile
  46. << "): " << ret << " (" << error << ")";
  47. if (!ret)
  48. MORDOR_THROW_EXCEPTION_FROM_ERROR_API(error, "DisconnectNamedPipe");
  49. }
  50. HandleStream::close(type);
  51. }
  52. void
  53. NamedPipeStream::accept()
  54. {
  55. if (m_cancelRead)
  56. MORDOR_THROW_EXCEPTION(OperationAbortedException());
  57. SchedulerSwitcher switcher(m_ioManager ? NULL : m_scheduler);
  58. OVERLAPPED *overlapped = NULL;
  59. if (m_ioManager) {
  60. MORDOR_ASSERT(Scheduler::getThis());
  61. m_ioManager->registerEvent(&m_readEvent);
  62. overlapped = &m_readEvent.overlapped;
  63. }
  64. BOOL ret = ConnectNamedPipe(m_hFile, overlapped);
  65. Log::Level level = Log::DEBUG;
  66. if (!ret) {
  67. if (lastError() == ERROR_PIPE_CONNECTED) {
  68. } else if (m_ioManager) {
  69. if (lastError() == ERROR_IO_PENDING)
  70. level = Log::TRACE;
  71. else
  72. level = Log::ERROR;
  73. } else {
  74. level = Log::ERROR;
  75. }
  76. }
  77. error_t error = lastError();
  78. MORDOR_LOG_LEVEL(g_log, level) << this
  79. << " ConnectNamedPipe(" << m_hFile << "): " << ret << " ("
  80. << error << ")";
  81. if (m_ioManager) {
  82. if (!ret && error == ERROR_PIPE_CONNECTED) {
  83. m_ioManager->unregisterEvent(&m_readEvent);
  84. return;
  85. }
  86. if (!ret && error != ERROR_IO_PENDING) {
  87. m_ioManager->unregisterEvent(&m_readEvent);
  88. MORDOR_THROW_EXCEPTION_FROM_LAST_ERROR_API("ConnectNamedPipe");
  89. }
  90. if (ret && m_skipCompletionPortOnSuccess)
  91. m_ioManager->unregisterEvent(&m_readEvent);
  92. else
  93. Scheduler::yieldTo();
  94. error_t error = pRtlNtStatusToDosError((NTSTATUS)m_readEvent.overlapped.Internal);
  95. MORDOR_LOG_LEVEL(g_log, error ? Log::ERROR : Log::DEBUG) << this
  96. << " ConnectNamedPipe(" << m_hFile << "): (" << error
  97. << ")";
  98. if (error)
  99. MORDOR_THROW_EXCEPTION_FROM_ERROR_API(error, "ConnectNamedPipe");
  100. } else {
  101. if (!ret && error == ERROR_PIPE_CONNECTED)
  102. return;
  103. if (!ret)
  104. MORDOR_THROW_EXCEPTION_FROM_ERROR_API(error, "ConnectNamedPipe");
  105. }
  106. }
  107. void
  108. NamedPipeStream::cancelAccept()
  109. {
  110. m_cancelRead = true;
  111. if (m_ioManager) {
  112. m_ioManager->cancelEvent(m_hFile, &m_readEvent);
  113. } else {
  114. MORDOR_ASSERT(supportsCancel());
  115. if (!pCancelIoEx(m_hFile, NULL))
  116. MORDOR_THROW_EXCEPTION_FROM_LAST_ERROR_API("CancelIoEx");
  117. }
  118. }
  119. void
  120. NamedPipeStream::disconnectClient()
  121. {
  122. // Prepare for reuse of the named pipe handle
  123. FlushFileBuffers(m_hFile);
  124. DisconnectNamedPipe(m_hFile);
  125. }
  126. }