PageRenderTime 52ms CodeModel.GetById 26ms RepoModel.GetById 1ms app.codeStats 0ms

/src/websocketpp_02/src/messages/control.hpp

https://gitlab.com/vectorci/rippled
C++ Header | 182 lines | 112 code | 35 blank | 35 comment | 21 complexity | a7eb7b1bce4f71fa13c0ad994ba52c2c MD5 | raw file
  1. /*
  2. * Copyright (c) 2011, Peter Thorson. All rights reserved.
  3. *
  4. * Redistribution and use in source and binary forms, with or without
  5. * modification, are permitted provided that the following conditions are met:
  6. * * Redistributions of source code must retain the above copyright
  7. * notice, this list of conditions and the following disclaimer.
  8. * * Redistributions in binary form must reproduce the above copyright
  9. * notice, this list of conditions and the following disclaimer in the
  10. * documentation and/or other materials provided with the distribution.
  11. * * Neither the name of the WebSocket++ Project nor the
  12. * names of its contributors may be used to endorse or promote products
  13. * derived from this software without specific prior written permission.
  14. *
  15. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  16. * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  17. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  18. * ARE DISCLAIMED. IN NO EVENT SHALL PETER THORSON BE LIABLE FOR ANY
  19. * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  20. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  21. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  22. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  23. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  24. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  25. *
  26. */
  27. #ifndef WEBSOCKET_CONTROL_MESSAGE_HPP
  28. #define WEBSOCKET_CONTROL_MESSAGE_HPP
  29. #include <iostream>
  30. #include <boost/shared_ptr.hpp>
  31. #include "../processors/processor.hpp"
  32. #include "../websocket_frame.hpp"
  33. #include "../utf8_validator/utf8_validator.hpp"
  34. #include "../processors/hybi_util.hpp"
  35. using websocketpp_02::processor::hybi_util::circshift_prepared_key;
  36. namespace websocketpp_02 {
  37. namespace message {
  38. class control {
  39. public:
  40. control() {
  41. m_payload.reserve(PAYLOAD_SIZE_INIT);
  42. }
  43. frame::opcode::value get_opcode() const {
  44. return m_opcode;
  45. };
  46. const std::string& get_payload() const {
  47. return m_payload;
  48. }
  49. void process_payload(char *input,uint64_t size) {
  50. const size_t new_size = static_cast<size_t>(m_payload.size() + size);
  51. if (new_size > PAYLOAD_SIZE_MAX) {
  52. throw processor::exception("Message payload was too large.",processor::error::MESSAGE_TOO_BIG);
  53. }
  54. if (m_masked) {
  55. // this retrieves ceiling of size / word size
  56. size_t n = static_cast<size_t>((size + sizeof(size_t) - 1) / sizeof(size_t));
  57. // reinterpret the input as an array of word sized integers
  58. size_t* data = reinterpret_cast<size_t*>(input);
  59. // unmask working buffer
  60. for (size_t i = 0; i < n; i++) {
  61. data[i] ^= m_prepared_key;
  62. }
  63. // circshift working key
  64. m_prepared_key = circshift_prepared_key(m_prepared_key, size%4);
  65. }
  66. // copy working buffer into
  67. m_payload.append(input, static_cast<size_t>(size));
  68. }
  69. void complete() {
  70. if (m_opcode == frame::opcode::CLOSE) {
  71. if (m_payload.size() == 1) {
  72. throw processor::exception("Single byte close code",processor::error::PROTOCOL_VIOLATION);
  73. } else if (m_payload.size() >= 2) {
  74. close::status::value code = close::status::value(get_raw_close_code());
  75. if (close::status::invalid(code)) {
  76. throw processor::exception("Close code is not allowed on the wire.",processor::error::PROTOCOL_VIOLATION);
  77. } else if (close::status::reserved(code)) {
  78. throw processor::exception("Close code is reserved.",processor::error::PROTOCOL_VIOLATION);
  79. }
  80. }
  81. if (m_payload.size() > 2) {
  82. if (!m_validator.decode(m_payload.begin()+2,m_payload.end())) {
  83. throw processor::exception("Invalid UTF8",processor::error::PAYLOAD_VIOLATION);
  84. }
  85. if (!m_validator.complete()) {
  86. throw processor::exception("Invalid UTF8",processor::error::PAYLOAD_VIOLATION);
  87. }
  88. }
  89. }
  90. }
  91. void reset(frame::opcode::value opcode, uint32_t masking_key) {
  92. m_opcode = opcode;
  93. set_masking_key(masking_key);
  94. m_payload.resize(0);
  95. m_validator.reset();
  96. }
  97. close::status::value get_close_code() const {
  98. if (m_payload.size() == 0) {
  99. return close::status::NO_STATUS;
  100. } else {
  101. return close::status::value(get_raw_close_code());
  102. }
  103. }
  104. std::string get_close_reason() const {
  105. if (m_payload.size() > 2) {
  106. return m_payload.substr(2);
  107. } else {
  108. return std::string();
  109. }
  110. }
  111. void set_masking_key(int32_t key) {
  112. m_masking_key.i = key;
  113. m_prepared_key = processor::hybi_util::prepare_masking_key(m_masking_key);
  114. m_masked = true;
  115. }
  116. private:
  117. uint16_t get_raw_close_code() const {
  118. if (m_payload.size() <= 1) {
  119. throw processor::exception("get_raw_close_code called with invalid size",processor::error::FATAL_ERROR);
  120. }
  121. union {uint16_t i;char c[2];} val;
  122. val.c[0] = m_payload[0];
  123. val.c[1] = m_payload[1];
  124. return ntohs(val.i);
  125. }
  126. static const uint64_t PAYLOAD_SIZE_INIT = 128; // 128B
  127. static const uint64_t PAYLOAD_SIZE_MAX = 128; // 128B
  128. typedef websocketpp_02::processor::hybi_util::masking_key_type masking_key_type;
  129. union masking_key {
  130. int32_t i;
  131. char c[4];
  132. };
  133. // Message state
  134. frame::opcode::value m_opcode;
  135. // UTF8 validation state
  136. utf8_validator::validator m_validator;
  137. // Masking state
  138. masking_key_type m_masking_key;
  139. bool m_masked;
  140. size_t m_prepared_key;
  141. // Message payload
  142. std::string m_payload;
  143. };
  144. typedef boost::shared_ptr<control> control_ptr;
  145. } // namespace message
  146. } // namespace websocketpp_02
  147. #endif // WEBSOCKET_CONTROL_MESSAGE_HPP