| // Copyright 2012 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef NET_SERVER_HTTP_SERVER_H_ |
| #define NET_SERVER_HTTP_SERVER_H_ |
| |
| #include <stddef.h> |
| #include <stdint.h> |
| |
| #include <map> |
| #include <memory> |
| #include <string> |
| |
| #include "base/memory/raw_ptr.h" |
| #include "base/memory/weak_ptr.h" |
| #include "base/strings/string_piece.h" |
| #include "net/http/http_status_code.h" |
| #include "net/traffic_annotation/network_traffic_annotation.h" |
| |
| namespace net { |
| |
| class HttpConnection; |
| class HttpServerRequestInfo; |
| class HttpServerResponseInfo; |
| class IPEndPoint; |
| class ServerSocket; |
| class StreamSocket; |
| |
| class HttpServer { |
| public: |
| // Delegate to handle http/websocket events. Beware that it is not safe to |
| // destroy the HttpServer in any of these callbacks. |
| class Delegate { |
| public: |
| virtual ~Delegate() = default; |
| |
| virtual void OnConnect(int connection_id) = 0; |
| virtual void OnHttpRequest(int connection_id, |
| const HttpServerRequestInfo& info) = 0; |
| virtual void OnWebSocketRequest(int connection_id, |
| const HttpServerRequestInfo& info) = 0; |
| virtual void OnWebSocketMessage(int connection_id, std::string data) = 0; |
| virtual void OnClose(int connection_id) = 0; |
| }; |
| |
| // Instantiates a http server with |server_socket| which already started |
| // listening, but not accepting. This constructor schedules accepting |
| // connections asynchronously in case when |delegate| is not ready to get |
| // callbacks yet. |
| HttpServer(std::unique_ptr<ServerSocket> server_socket, |
| HttpServer::Delegate* delegate); |
| |
| HttpServer(const HttpServer&) = delete; |
| HttpServer& operator=(const HttpServer&) = delete; |
| |
| ~HttpServer(); |
| |
| void AcceptWebSocket(int connection_id, |
| const HttpServerRequestInfo& request, |
| NetworkTrafficAnnotationTag traffic_annotation); |
| void SendOverWebSocket(int connection_id, |
| base::StringPiece data, |
| NetworkTrafficAnnotationTag traffic_annotation); |
| // Sends the provided data directly to the given connection. No validation is |
| // performed that data constitutes a valid HTTP response. A valid HTTP |
| // response may be split across multiple calls to SendRaw. |
| void SendRaw(int connection_id, |
| const std::string& data, |
| NetworkTrafficAnnotationTag traffic_annotation); |
| // TODO(byungchul): Consider replacing function name with SendResponseInfo |
| void SendResponse(int connection_id, |
| const HttpServerResponseInfo& response, |
| NetworkTrafficAnnotationTag traffic_annotation); |
| void Send(int connection_id, |
| HttpStatusCode status_code, |
| const std::string& data, |
| const std::string& mime_type, |
| NetworkTrafficAnnotationTag traffic_annotation); |
| void Send200(int connection_id, |
| const std::string& data, |
| const std::string& mime_type, |
| NetworkTrafficAnnotationTag traffic_annotation); |
| void Send404(int connection_id, |
| NetworkTrafficAnnotationTag traffic_annotation); |
| void Send500(int connection_id, |
| const std::string& message, |
| NetworkTrafficAnnotationTag traffic_annotation); |
| |
| void Close(int connection_id); |
| |
| void SetReceiveBufferSize(int connection_id, int32_t size); |
| void SetSendBufferSize(int connection_id, int32_t size); |
| |
| // Copies the local address to |address|. Returns a network error code. |
| int GetLocalAddress(IPEndPoint* address); |
| |
| #if defined(STARBOARD) |
| // Like GetLocalAddress(), but if listening to IPADDR_ANY returns the local |
| // address of an arbitrary interface (choosing IPv4 address over IPv6). |
| int GetLocalInterfaceAddress(IPEndPoint* address); |
| |
| bool static ParseHeaders(const std::string& request, |
| HttpServerRequestInfo* info) { |
| size_t pos = 0; |
| return ParseHeaders(request.c_str(), request.length(), info, &pos); |
| } |
| #endif |
| |
| private: |
| friend class HttpServerTest; |
| |
| void DoAcceptLoop(); |
| void OnAcceptCompleted(int rv); |
| int HandleAcceptResult(int rv); |
| |
| void DoReadLoop(HttpConnection* connection); |
| void OnReadCompleted(int connection_id, int rv); |
| int HandleReadResult(HttpConnection* connection, int rv); |
| |
| void DoWriteLoop(HttpConnection* connection, |
| NetworkTrafficAnnotationTag traffic_annotation); |
| void OnWriteCompleted(int connection_id, |
| NetworkTrafficAnnotationTag traffic_annotation, |
| int rv); |
| int HandleWriteResult(HttpConnection* connection, int rv); |
| |
| // Expects the raw data to be stored in recv_data_. If parsing is successful, |
| // will remove the data parsed from recv_data_, leaving only the unused |
| // recv data. If all data has been consumed successfully, but the headers are |
| // not fully parsed, *pos will be set to zero. Returns false if an error is |
| // encountered while parsing, true otherwise. |
| #if defined(STARBOARD) |
| // Cobalt at least needs it to be static in dial_udp_server.cc. |
| static bool ParseHeaders(const char* data, |
| #else |
| bool ParseHeaders(const char* data, |
| #endif |
| size_t data_len, |
| HttpServerRequestInfo* info, |
| size_t* pos); |
| |
| HttpConnection* FindConnection(int connection_id); |
| |
| // Whether or not Close() has been called during delegate callback processing. |
| bool HasClosedConnection(HttpConnection* connection); |
| |
| const std::unique_ptr<ServerSocket> server_socket_; |
| std::unique_ptr<StreamSocket> accepted_socket_; |
| const raw_ptr<HttpServer::Delegate> delegate_; |
| |
| int last_id_ = 0; |
| std::map<int, std::unique_ptr<HttpConnection>> id_to_connection_; |
| |
| base::WeakPtrFactory<HttpServer> weak_ptr_factory_{this}; |
| }; |
| |
| } // namespace net |
| |
| #endif // NET_SERVER_HTTP_SERVER_H_ |