// Copyright 2017 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#ifndef COBALT_WEBSOCKET_WEB_SOCKET_IMPL_H_
#define COBALT_WEBSOCKET_WEB_SOCKET_IMPL_H_

#include <string>
#include <vector>

#include "base/compiler_specific.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_vector.h"
#include "base/optional.h"
#include "base/single_thread_task_runner.h"
#include "base/threading/thread_checker.h"
#include "cobalt/network/network_module.h"
#include "cobalt/websocket/buffered_amount_tracker.h"
#include "cobalt/websocket/web_socket_event_interface.h"
#include "cobalt/websocket/web_socket_frame_container.h"
#include "cobalt/websocket/web_socket_handshake_helper.h"
#include "cobalt/websocket/web_socket_message_container.h"
#include "googleurl/src/gurl.h"
#include "net/url_request/url_request_context_getter.h"
#include "net/websockets/websocket_frame_parser.h"
#include "net/websockets/websocket_job.h"

namespace cobalt {
namespace websocket {

typedef uint16 SerializedCloseStatusCodeType;

// According to https://tools.ietf.org/html/rfc6455#section-5.5.2
// All control frames MUST have a payload length of 125 bytes or less
// and MUST NOT be fragmented.
static const std::size_t kMaxControlPayloadSizeInBytes = 125;
const int kMaxCloseReasonSize =
    kMaxControlPayloadSizeInBytes - sizeof(SerializedCloseStatusCodeType);

class WebSocketImpl : public net::SocketStream::Delegate,
                      public base::RefCountedThreadSafe<WebSocketImpl> {
 public:
  typedef ScopedVector<net::WebSocketFrameChunk> WebSocketFrameChunkVector;

  explicit WebSocketImpl(cobalt::network::NetworkModule* network_module,
                         WebsocketEventInterface* delegate);

  void SetWebSocketEventDelegate(WebsocketEventInterface* delegate);

  // These functions are meant to be called from the Web Module thread.
  void Connect(const std::string& origin, const GURL& url,
               const std::vector<std::string>& sub_protocols);

  // Following functions return false if something went wrong.
  bool SendText(const char* data, std::size_t length, int32* buffered_amount,
                std::string* error_message);
  bool SendBinary(const char* data, std::size_t length, int32* buffered_amount,
                  std::string* error_message);

  void Close(const net::WebSocketError code, const std::string& reason);

  // Following functions are from net::SocketStream::Delegate, and are called on
  // the IO thread.

  void OnConnected(net::SocketStream* socket,
                   int max_pending_send_allowed) OVERRIDE;
  // Called when |amount_sent| bytes of data are sent.
  void OnSentData(net::SocketStream* socket, int amount_sent) OVERRIDE;
  // Called when |len| bytes of |data| are received.
  void OnReceivedData(net::SocketStream* socket, const char* data,
                      int len) OVERRIDE;
  // Called when the socket stream has been closed.
  void OnClose(net::SocketStream* socket) OVERRIDE;

  void OnError(const net::SocketStream* socket, int error) OVERRIDE;

 private:
  struct CloseInfo {
    CloseInfo(const net::WebSocketError code, const std::string& reason)
        : code(code), reason(reason) {}
    explicit CloseInfo(const net::WebSocketError code) : code(code) {}

    net::WebSocketError code;
    std::string reason;
  };

  void DoDetach(base::WaitableEvent* waitable_event);
  void DoClose(const CloseInfo& close_info);
  void DoPong(const scoped_refptr<net::IOBufferWithSize> payload);
  void DoConnect(
      scoped_refptr<cobalt::network::URLRequestContextGetter> context,
      const GURL& url, base::WaitableEvent* job_created_event);
  void SendFrame(const scoped_array<char> data, const int length,
                 const int overhead_bytes);
  void OnHandshakeComplete(const std::string& selected_subprotocol);

  void ProcessCompleteMessage(
      const WebSocketMessageContainer& message_container);
  void ProcessControlMessage(
      const WebSocketMessageContainer& message_container);

  bool ProcessCompleteFrame(WebSocketFrameContainer* frame);

  void HandleClose(const net::WebSocketFrameHeader& header,
                   const scoped_refptr<net::IOBufferWithSize>& close_data);
  void HandlePing(const net::WebSocketFrameHeader& header,
                  const scoped_refptr<net::IOBufferWithSize>& ping_data);
  void HandlePong(const net::WebSocketFrameHeader& header,
                  const scoped_refptr<net::IOBufferWithSize>& pong_data);

  bool SendClose(const net::WebSocketError status_code,
                 const std::string& reason, std::string* error_message);
  bool SendPong(const base::StringPiece payload, std::string* error_message);
  // Note that |payload_length| in |header| will define the payload length.
  bool SendHelper(const net::WebSocketFrameHeader& header, const char* data,
                  std::string* error_message);

  // Returns true if the handshake has been fully processed.
  bool ProcessHandshake(std::size_t* payload_offset);

  void TrampolineClose(const CloseInfo& close_info);

  void OnWebSocketConnected(const std::string& selected_subprotocol);
  void OnWebSocketDisconnected(bool was_clean, uint16 code,
                               const std::string& reason);
  void OnWebSocketSentData(int amount_sent);
  void OnWebSocketReceivedData(bool is_text_frame,
                               scoped_refptr<net::IOBufferWithSize> data);
  void OnWebSocketError();

  base::ThreadChecker thread_checker_;
  net::WebSocketJob::State GetCurrentState() const;

  std::vector<std::string> desired_sub_protocols_;
  network::NetworkModule* network_module_;
  scoped_refptr<net::WebSocketJob> job_;
  WebsocketEventInterface* delegate_;
  std::string origin_;
  GURL connect_url_;
  WebSocketHandshakeHelper handshake_helper_;
  bool handshake_completed_;
  net::WebSocketFrameParser frame_parser_;
  WebSocketFrameContainer current_frame_container_;
  WebSocketMessageContainer current_message_container_;

  base::optional<CloseInfo> peer_close_info_;
  BufferedAmountTracker buffered_amount_tracker_;

  scoped_refptr<base::SingleThreadTaskRunner> delegate_task_runner_;
  scoped_refptr<base::SingleThreadTaskRunner> owner_task_runner_;

  virtual ~WebSocketImpl();
  friend class base::RefCountedThreadSafe<WebSocketImpl>;

  DISALLOW_COPY_AND_ASSIGN(WebSocketImpl);
};

}  // namespace websocket
}  // namespace cobalt

#endif  // COBALT_WEBSOCKET_WEB_SOCKET_IMPL_H_
