1/*
2 * Copyright (c) 2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#ifndef ARKCOMPILER_TOOLCHAIN_WEBSOCKET_FRAME_BUILDER_H
17#define ARKCOMPILER_TOOLCHAIN_WEBSOCKET_FRAME_BUILDER_H
18
19#include "web_socket_frame.h"
20
21#include <string>
22
23namespace OHOS::ArkCompiler::Toolchain {
24template <typename T, typename = std::enable_if_t<std::is_unsigned_v<T>>>
25inline void PushNumberPerByte(std::string& message, T number)
26{
27    constexpr size_t bytesCount = sizeof(T);
28    constexpr size_t bitsCount = 8;
29    size_t shiftCount = (bytesCount - 1) * bitsCount;
30    for (size_t i = 0; i < bytesCount; ++i, shiftCount -= bitsCount) {
31        message.push_back((number >> shiftCount) & 0xff);
32    }
33}
34
35class ServerFrameBuilder {
36public:
37    // force users to specify opcode and final bit
38    ServerFrameBuilder() = delete;
39    ServerFrameBuilder(bool final, FrameType opcode) : fin_(final), opcode_(opcode)
40    {
41    }
42    ~ServerFrameBuilder() noexcept = default;
43
44    ServerFrameBuilder& SetFinal(bool fin);
45    ServerFrameBuilder& SetOpcode(FrameType opcode);
46    ServerFrameBuilder& SetPayload(const std::string& payload);
47    ServerFrameBuilder& SetPayload(std::string&& payload);
48    ServerFrameBuilder& AppendPayload(const std::string& payload);
49
50    std::string Build() const;
51
52protected:
53    void PushHeader(std::string& message, uint8_t payloadLenField) const;
54    void PushPayloadLength(std::string& message, uint8_t payloadLenField) const;
55    virtual void PushFullHeader(std::string& message, size_t additionalReservedMem) const;
56    virtual void PushPayload(std::string& message) const;
57
58protected:
59    bool fin_;
60    FrameType opcode_;
61    std::string payload_;
62};
63
64class ClientFrameBuilder final : public ServerFrameBuilder {
65public:
66    ClientFrameBuilder(bool final, FrameType opcode, const uint8_t maskingKey[WebSocketFrame::MASK_LEN]);
67
68    ClientFrameBuilder& SetMask(const uint8_t maskingKey[WebSocketFrame::MASK_LEN]);
69
70private:
71    void PushMask(std::string& message) const;
72    void PushFullHeader(std::string& message, size_t additionalReservedMem) const override;
73    void PushPayload(std::string& message) const override;
74
75private:
76    uint8_t maskingKey_[WebSocketFrame::MASK_LEN] = {0};
77};
78} // namespace OHOS::ArkCompiler::Toolchain
79
80#endif // ARKCOMPILER_TOOLCHAIN_WEBSOCKET_FRAME_BUILDER_H
81