1e509ee18Sopenharmony_ci/* 2e509ee18Sopenharmony_ci * Copyright (c) 2022 Huawei Device Co., Ltd. 3e509ee18Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 4e509ee18Sopenharmony_ci * you may not use this file except in compliance with the License. 5e509ee18Sopenharmony_ci * You may obtain a copy of the License at 6e509ee18Sopenharmony_ci * 7e509ee18Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 8e509ee18Sopenharmony_ci * 9e509ee18Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 10e509ee18Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 11e509ee18Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12e509ee18Sopenharmony_ci * See the License for the specific language governing permissions and 13e509ee18Sopenharmony_ci * limitations under the License. 14e509ee18Sopenharmony_ci */ 15e509ee18Sopenharmony_ci 16e509ee18Sopenharmony_ci#include "frame_builder.h" 17e509ee18Sopenharmony_ci 18e509ee18Sopenharmony_cinamespace OHOS::ArkCompiler::Toolchain { 19e509ee18Sopenharmony_ciServerFrameBuilder& ServerFrameBuilder::SetFinal(bool fin) 20e509ee18Sopenharmony_ci{ 21e509ee18Sopenharmony_ci fin_ = fin; 22e509ee18Sopenharmony_ci return *this; 23e509ee18Sopenharmony_ci} 24e509ee18Sopenharmony_ci 25e509ee18Sopenharmony_ciServerFrameBuilder& ServerFrameBuilder::SetOpcode(FrameType opcode) 26e509ee18Sopenharmony_ci{ 27e509ee18Sopenharmony_ci opcode_ = opcode; 28e509ee18Sopenharmony_ci return *this; 29e509ee18Sopenharmony_ci} 30e509ee18Sopenharmony_ci 31e509ee18Sopenharmony_ciServerFrameBuilder& ServerFrameBuilder::SetPayload(const std::string& payload) 32e509ee18Sopenharmony_ci{ 33e509ee18Sopenharmony_ci payload_ = payload; 34e509ee18Sopenharmony_ci return *this; 35e509ee18Sopenharmony_ci} 36e509ee18Sopenharmony_ci 37e509ee18Sopenharmony_ciServerFrameBuilder& ServerFrameBuilder::SetPayload(std::string&& payload) 38e509ee18Sopenharmony_ci{ 39e509ee18Sopenharmony_ci payload_ = std::move(payload); 40e509ee18Sopenharmony_ci return *this; 41e509ee18Sopenharmony_ci} 42e509ee18Sopenharmony_ci 43e509ee18Sopenharmony_ciServerFrameBuilder& ServerFrameBuilder::AppendPayload(const std::string& payload) 44e509ee18Sopenharmony_ci{ 45e509ee18Sopenharmony_ci payload_.append(payload); 46e509ee18Sopenharmony_ci return *this; 47e509ee18Sopenharmony_ci} 48e509ee18Sopenharmony_ci 49e509ee18Sopenharmony_cistd::string ServerFrameBuilder::Build() const 50e509ee18Sopenharmony_ci{ 51e509ee18Sopenharmony_ci std::string message; 52e509ee18Sopenharmony_ci PushFullHeader(message, 0); 53e509ee18Sopenharmony_ci PushPayload(message); 54e509ee18Sopenharmony_ci return message; 55e509ee18Sopenharmony_ci} 56e509ee18Sopenharmony_ci 57e509ee18Sopenharmony_civoid ServerFrameBuilder::PushFullHeader(std::string& message, size_t additionalReservedMem) const 58e509ee18Sopenharmony_ci{ 59e509ee18Sopenharmony_ci auto headerBytes = WebSocketFrame::HEADER_LEN; 60e509ee18Sopenharmony_ci auto payloadBytes = payload_.size(); 61e509ee18Sopenharmony_ci uint8_t payloadLenField = 0; 62e509ee18Sopenharmony_ci 63e509ee18Sopenharmony_ci if (payloadBytes <= WebSocketFrame::ONE_BYTE_LENTH_ENC_LIMIT) { 64e509ee18Sopenharmony_ci payloadLenField = static_cast<uint8_t>(payloadBytes); 65e509ee18Sopenharmony_ci } else if (payloadBytes < WebSocketFrame::TWO_BYTES_LENGTH_LIMIT) { 66e509ee18Sopenharmony_ci payloadLenField = WebSocketFrame::TWO_BYTES_LENTH_ENC; 67e509ee18Sopenharmony_ci headerBytes += WebSocketFrame::TWO_BYTES_LENTH; 68e509ee18Sopenharmony_ci } else { 69e509ee18Sopenharmony_ci payloadLenField = WebSocketFrame::EIGHT_BYTES_LENTH_ENC; 70e509ee18Sopenharmony_ci headerBytes += WebSocketFrame::EIGHT_BYTES_LENTH; 71e509ee18Sopenharmony_ci } 72e509ee18Sopenharmony_ci 73e509ee18Sopenharmony_ci message.reserve(headerBytes + payloadBytes + additionalReservedMem); 74e509ee18Sopenharmony_ci PushHeader(message, payloadLenField); 75e509ee18Sopenharmony_ci PushPayloadLength(message, payloadLenField); 76e509ee18Sopenharmony_ci} 77e509ee18Sopenharmony_ci 78e509ee18Sopenharmony_civoid ServerFrameBuilder::PushHeader(std::string& message, uint8_t payloadLenField) const 79e509ee18Sopenharmony_ci{ 80e509ee18Sopenharmony_ci uint8_t byte = EnumToNumber(opcode_); 81e509ee18Sopenharmony_ci if (fin_) { 82e509ee18Sopenharmony_ci byte |= 0x80; 83e509ee18Sopenharmony_ci } 84e509ee18Sopenharmony_ci message.push_back(byte); 85e509ee18Sopenharmony_ci 86e509ee18Sopenharmony_ci // A server MUST NOT mask any frames that it sends to the client, 87e509ee18Sopenharmony_ci // hence mask bit must be set to zero (see https://www.rfc-editor.org/rfc/rfc6455#section-5.1) 88e509ee18Sopenharmony_ci byte = payloadLenField & 0x7f; 89e509ee18Sopenharmony_ci message.push_back(byte); 90e509ee18Sopenharmony_ci} 91e509ee18Sopenharmony_ci 92e509ee18Sopenharmony_civoid ServerFrameBuilder::PushPayloadLength(std::string& message, uint8_t payloadLenField) const 93e509ee18Sopenharmony_ci{ 94e509ee18Sopenharmony_ci uint64_t payloadLen = payload_.size(); 95e509ee18Sopenharmony_ci if (payloadLenField == WebSocketFrame::TWO_BYTES_LENTH_ENC) { 96e509ee18Sopenharmony_ci PushNumberPerByte(message, static_cast<uint16_t>(payloadLen)); 97e509ee18Sopenharmony_ci } else if (payloadLenField == WebSocketFrame::EIGHT_BYTES_LENTH_ENC) { 98e509ee18Sopenharmony_ci PushNumberPerByte(message, payloadLen); 99e509ee18Sopenharmony_ci } 100e509ee18Sopenharmony_ci} 101e509ee18Sopenharmony_ci 102e509ee18Sopenharmony_civoid ServerFrameBuilder::PushPayload(std::string& message) const 103e509ee18Sopenharmony_ci{ 104e509ee18Sopenharmony_ci message.append(payload_); 105e509ee18Sopenharmony_ci} 106e509ee18Sopenharmony_ci 107e509ee18Sopenharmony_ciClientFrameBuilder::ClientFrameBuilder(bool final, FrameType opcode, const uint8_t maskingKey[WebSocketFrame::MASK_LEN]) 108e509ee18Sopenharmony_ci : ServerFrameBuilder(final, opcode) 109e509ee18Sopenharmony_ci{ 110e509ee18Sopenharmony_ci SetMask(maskingKey); 111e509ee18Sopenharmony_ci} 112e509ee18Sopenharmony_ci 113e509ee18Sopenharmony_ciClientFrameBuilder& ClientFrameBuilder::SetMask(const uint8_t maskingKey[WebSocketFrame::MASK_LEN]) 114e509ee18Sopenharmony_ci{ 115e509ee18Sopenharmony_ci for (size_t i = 0; i < WebSocketFrame::MASK_LEN; ++i) { 116e509ee18Sopenharmony_ci maskingKey_[i] = maskingKey[i]; 117e509ee18Sopenharmony_ci } 118e509ee18Sopenharmony_ci return *this; 119e509ee18Sopenharmony_ci} 120e509ee18Sopenharmony_ci 121e509ee18Sopenharmony_civoid ClientFrameBuilder::PushFullHeader(std::string& message, size_t additionalReservedMem) const 122e509ee18Sopenharmony_ci{ 123e509ee18Sopenharmony_ci // reserve additional 4 bytes for mask 124e509ee18Sopenharmony_ci ServerFrameBuilder::PushFullHeader(message, additionalReservedMem + WebSocketFrame::MASK_LEN); 125e509ee18Sopenharmony_ci // If the data is being sent by the client, the frame(s) MUST be masked 126e509ee18Sopenharmony_ci // (see https://www.rfc-editor.org/rfc/rfc6455#section-6.1) 127e509ee18Sopenharmony_ci message[1] |= 0x80; 128e509ee18Sopenharmony_ci PushMask(message); 129e509ee18Sopenharmony_ci} 130e509ee18Sopenharmony_ci 131e509ee18Sopenharmony_civoid ClientFrameBuilder::PushPayload(std::string& message) const 132e509ee18Sopenharmony_ci{ 133e509ee18Sopenharmony_ci // push masked payload 134e509ee18Sopenharmony_ci for (size_t i = 0, end = payload_.size(); i < end; ++i) { 135e509ee18Sopenharmony_ci char c = payload_[i] ^ maskingKey_[i % WebSocketFrame::MASK_LEN]; 136e509ee18Sopenharmony_ci message.push_back(c); 137e509ee18Sopenharmony_ci } 138e509ee18Sopenharmony_ci} 139e509ee18Sopenharmony_ci 140e509ee18Sopenharmony_civoid ClientFrameBuilder::PushMask(std::string& message) const 141e509ee18Sopenharmony_ci{ 142e509ee18Sopenharmony_ci for (size_t i = 0; i < WebSocketFrame::MASK_LEN; ++i) { 143e509ee18Sopenharmony_ci message.push_back(static_cast<char>(maskingKey_[i])); 144e509ee18Sopenharmony_ci } 145e509ee18Sopenharmony_ci} 146e509ee18Sopenharmony_ci} // OHOS::ArkCompiler::Toolchain 147