自己做的网站发布到网上,佛山自己网站建设,国金紫郡府淮北论坛,网站建设应列入啥费用一、WebSocket前端接口定义#xff1a;
WebSocket 对象提供了用于创建和管理 WebSocket 连接#xff0c;以及可以通过该连接发送和接收数据的 API。
使用 WebSocket() 构造函数来构造一个 WebSocket。
构造函数
WebSocket(url[, protocols])
返回一个 WebSocket 对象。 …一、WebSocket前端接口定义
WebSocket 对象提供了用于创建和管理 WebSocket 连接以及可以通过该连接发送和接收数据的 API。
使用 WebSocket() 构造函数来构造一个 WebSocket。
构造函数
WebSocket(url[, protocols])
返回一个 WebSocket 对象。
常量
ConstantValueWebSocket.CONNECTING0WebSocket.OPEN1WebSocket.CLOSING2WebSocket.CLOSED3
属性
WebSocket.binaryType
使用二进制的数据类型连接。
WebSocket.bufferedAmount 只读
未发送至服务器的字节数。
WebSocket.extensions 只读
服务器选择的扩展。
WebSocket.onclose
用于指定连接关闭后的回调函数。
WebSocket.onerror
用于指定连接失败后的回调函数。
WebSocket.onmessage
用于指定当从服务器接受到信息时的回调函数。
WebSocket.onopen
用于指定连接成功后的回调函数。
WebSocket.protocol 只读
服务器选择的下属协议。
WebSocket.readyState 只读
当前的链接状态。
WebSocket.url 只读
WebSocket 的绝对路径。
方法
WebSocket.close([code[, reason]])
关闭当前链接。
WebSocket.send(data)
对要传输的数据进行排队。
事件
使用 addEventListener() 或将一个事件监听器赋值给本接口的 oneventname 属性来监听下面的事件。
close
当一个 WebSocket 连接被关闭时触发。 也可以通过 onclose 属性来设置。
error
当一个 WebSocket 连接因错误而关闭时触发例如无法发送数据时。 也可以通过 onerror 属性来设置。
message
当通过 WebSocket 收到数据时触发。 也可以通过 onmessage 属性来设置。
open
当一个 WebSocket 连接成功时触发。 也可以通过 onopen 属性来设置。
更多参考WebSocket - Web API | MDN (mozilla.org)
二、websocket c接口实现和定义
1、websocket.idl接口定义
third_party\blink\renderer\modules\websockets\websocket.idl // https://html.spec.whatwg.org/C/#the-websocket-interfaceenum BinaryType { blob, arraybuffer };[ActiveScriptWrappable,Exposed(Window,Worker),ImplementedAsDOMWebSocket
] interface WebSocket : EventTarget {[CallWithExecutionContext, RaisesException] constructor(USVString url, optional (DOMString or sequenceDOMString) protocols);readonly attribute USVString url;// ready stateconst unsigned short CONNECTING 0;const unsigned short OPEN 1;const unsigned short CLOSING 2;const unsigned short CLOSED 3;readonly attribute unsigned short readyState;readonly attribute unsigned long long bufferedAmount;// networkingattribute EventHandler onopen;attribute EventHandler onerror;attribute EventHandler onclose;readonly attribute DOMString extensions;readonly attribute DOMString protocol;[RaisesException] void close(optional [Clamp] unsigned short code, optional USVString reason);// messagingattribute EventHandler onmessage;attribute BinaryType binaryType;[RaisesException] void send(USVString data);[RaisesException] void send(Blob data);[RaisesException] void send(ArrayBuffer data);[RaisesException] void send(ArrayBufferView data);
};2、websocket.idl接口实现blink
third_party\blink\renderer\modules\websockets\dom_websocket.h
third_party\blink\renderer\modules\websockets\dom_websocket.cc namespace blink {class Blob;
class DOMArrayBuffer;
class DOMArrayBufferView;
class ExceptionState;
class ExecutionContext;
class V8UnionStringOrStringSequence;class MODULES_EXPORT DOMWebSocket: public EventTarget,public ActiveScriptWrappableDOMWebSocket,public ExecutionContextLifecycleStateObserver,public WebSocketChannelClient {DEFINE_WRAPPERTYPEINFO();public:// These definitions are required by V8DOMWebSocket.static constexpr auto kConnecting WebSocketCommon::kConnecting;static constexpr auto kOpen WebSocketCommon::kOpen;static constexpr auto kClosing WebSocketCommon::kClosing;static constexpr auto kClosed WebSocketCommon::kClosed;// DOMWebSocket instances must be used with a wrapper since this classs// lifetime management is designed assuming the V8 holds a ref on it while// hasPendingActivity() returns true.static DOMWebSocket* Create(ExecutionContext*,const String url,ExceptionState);static DOMWebSocket* Create(ExecutionContext* execution_context,const String url,const V8UnionStringOrStringSequence* protocols,ExceptionState exception_state);explicit DOMWebSocket(ExecutionContext*);~DOMWebSocket() override;void Connect(const String url,const VectorString protocols,ExceptionState);void send(const String message, ExceptionState);void send(DOMArrayBuffer*, ExceptionState);void send(NotSharedDOMArrayBufferView, ExceptionState);void send(Blob*, ExceptionState);// To distinguish close method call with the code parameter from one// without, we have these three signatures. Use of// OptionalDefaultIsUndefined in the IDL file doesnt help for now since// its bound to a value of 0 which is indistinguishable from the case 0// is passed as code parameter.void close(uint16_t code, const String reason, ExceptionState);void close(ExceptionState);void close(uint16_t code, ExceptionState);const KURL url() const;WebSocketCommon::State readyState() const;uint64_t bufferedAmount() const;String protocol() const;String extensions() const;String binaryType() const;void setBinaryType(const String);DEFINE_ATTRIBUTE_EVENT_LISTENER(open, kOpen)DEFINE_ATTRIBUTE_EVENT_LISTENER(message, kMessage)DEFINE_ATTRIBUTE_EVENT_LISTENER(error, kError)DEFINE_ATTRIBUTE_EVENT_LISTENER(close, kClose)// EventTarget functions.const AtomicString InterfaceName() const override;ExecutionContext* GetExecutionContext() const override;// ExecutionContextLifecycleStateObserver functions.void ContextDestroyed() override;void ContextLifecycleStateChanged(mojom::FrameLifecycleState) override;// ScriptWrappable functions.// Prevent this instance from being collected while its not in CLOSED// state.bool HasPendingActivity() const final;// WebSocketChannelClient functions.void DidConnect(const String subprotocol, const String extensions) override;void DidReceiveTextMessage(const String message) override;void DidReceiveBinaryMessage(const Vectorbase::spanconst char data) override;void DidError() override;void DidConsumeBufferedAmount(uint64_t) override;void DidStartClosingHandshake() override;void DidClose(ClosingHandshakeCompletionStatus,uint16_t code,const String reason) override;void Trace(Visitor*) const override;private:// FIXME: This should inherit blink::EventQueue.class EventQueue final : public GarbageCollectedEventQueue {public:static EventQueue* Create(EventTarget* target) {return MakeGarbageCollectedEventQueue(target);}explicit EventQueue(EventTarget*);~EventQueue();// Dispatches the event if this queue is active.// Queues the event if this queue is suspended.// Does nothing otherwise.void Dispatch(Event* /* event */);bool IsEmpty() const;void Pause();void Unpause();void ContextDestroyed();bool IsPaused();void Trace(Visitor*) const;private:enum State {kActive,kPaused,kUnpausePosted,kStopped,};// Dispatches queued events if this queue is active.// Does nothing otherwise.void DispatchQueuedEvents();void UnpauseTask();State state_;MemberEventTarget target_;HeapDequeMemberEvent events_;};enum class WebSocketSendType {kString,kArrayBuffer,kArrayBufferView,kBlob,kMaxValue kBlob,};enum BinaryType { kBinaryTypeBlob, kBinaryTypeArrayBuffer };// This function is virtual for unittests.virtual WebSocketChannel* CreateChannel(ExecutionContext* context,WebSocketChannelClient* client) {return WebSocketChannelImpl::Create(context, client,CaptureSourceLocation(context));}// Adds a console message with JSMessageSource and ErrorMessageLevel.void LogError(const String message);// Handle the JavaScript close method call. close() methods on this class// are just for determining if the optional code argument is supplied or// not.void CloseInternal(int, const String, ExceptionState);// Updates |buffered_amount_after_close_| given the amount of data passed to// send() method after the state changed to CLOSING or CLOSED.void UpdateBufferedAmountAfterClose(uint64_t);// Causes |buffered_amount_| to be updated asynchronously after returning to// the event loop. Uses |buffered_amount_update_task_pending_| to avoid// posting multiple tasks simultaneously.void PostBufferedAmountUpdateTask();// Updates |buffered_amount_| and resets// |buffered_amount_update_task_pending_|.void BufferedAmountUpdateTask();// Updates |buffered_amount_| provided the object is not currently paused.void ReflectBufferedAmountConsumption();void ReleaseChannel();// Called on web socket message activity (sending or receiving a message) that// the execution context may want to handle, such as to extend its own// lifetime.void NotifyWebSocketActivity();MemberWebSocketChannel channel_;WebSocketCommon common_;String origin_string_;uint64_t buffered_amount_;// The consumed buffered amount that will be reflected to |buffered_amount_|// later. It will be cleared once reflected.uint64_t consumed_buffered_amount_;uint64_t buffered_amount_after_close_;BinaryType binary_type_;// The subprotocol the server selected.String subprotocol_;String extensions_;MemberEventQueue event_queue_;bool buffered_amount_update_task_pending_;
};} // namespace blink3、websocket.idl接口实现blink/v8
out\Debug\gen\third_party\blink\renderer\bindings\modules\v8\v8_websocket.h
out\Debug\gen\third_party\blink\renderer\bindings\modules\v8\v8_websocket.cc
截取部分 websocket.send更多参考v8_websocket.cc
void SendOperationOverload1(const v8::FunctionCallbackInfov8::Value info) {v8::Isolate* isolate info.GetIsolate();
const ExceptionContextType exception_context_type ExceptionContextType::kOperationInvoke;
const char* const class_like_name WebSocket;
const char* const property_name send;
ExceptionState exception_state(isolate, exception_context_type, class_like_name, property_name);
if (UNLIKELY(info.Length() 1)) {exception_state.ThrowTypeError(ExceptionMessages::NotEnoughArguments(1, info.Length()));
return;
}v8::Localv8::Object v8_receiver info.This();
DOMWebSocket* blink_receiver V8WebSocket::ToWrappableUnsafe(isolate, v8_receiver);
auto arg1_data NativeValueTraitsIDLUSVString::ArgumentValue(isolate, 0, info[0], exception_state);
if (UNLIKELY(exception_state.HadException())) {return;
}
blink_receiver-send(arg1_data, exception_state);
if (UNLIKELY(exception_state.HadException())) {return;
}}
三、websocket网络进程实现接口 1、websocket.mojom接口定义 services\network\public\mojom\websocket.mojom 作用用来与render进程window.socket前端接口通信收发数据等。
// Copyright 2016 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.module network.mojom;import url/mojom/url.mojom;
import services/network/public/mojom/network_param.mojom;
import services/network/public/mojom/ip_endpoint.mojom;enum WebSocketMessageType {CONTINUATION,TEXT,BINARY,LAST BINARY
};// TODO(darin): Move to a more general location.
struct HttpHeader {string name;string value;
};// TODO(darin): Remove redundancy b/w |headers| and |headers_text|.struct WebSocketHandshakeRequest {url.mojom.Url url;arrayHttpHeader headers;string headers_text;
};struct WebSocketHandshakeResponse {url.mojom.Url url;HttpVersion http_version;int32 status_code;string status_text;IPEndPoint remote_endpoint;arrayHttpHeader headers;string headers_text;// Sub-protocol the server selected, or empty if no sub-protocol was selected.string selected_protocol;// The list of extensions negotiated for the connection.string extensions;
};// This interface is for HTTP Authentication.
interface WebSocketAuthenticationHandler {// Returns null credentials when it wants to cancel authentication, and// returns a non-null credentials when it wants to use the credentials for// authentication.OnAuthRequired(AuthChallengeInfo info,HttpResponseHeaders headers,IPEndPoint remote_endpoint) (AuthCredentials? credentials);
};// This interface is for client-side WebSocket handshake. Used to initialize
// the WebSocket Connection.
interface WebSocketHandshakeClient {// Notify the renderer that the browser has started an opening handshake.OnOpeningHandshakeStarted(WebSocketHandshakeRequest request);// Called when the WebSocket connection has failed.// |message| may contain a human-readable explanation of the error, but may be// empty.// |net_error| contains a network error code, which will be |ERR_FAILED| for// WebSocket-level protocol errors that do not have their own error code.// |response_code| contains the HTTP status code that caused the failure, if// it was caused by an unexpected status code, or else is -1.OnFailure(string message, int32 net_error, int32 response_code);// Called when the connection is established.// |response| may contain cookie-related headers when the client has// an access to raw cookie information.// |readable| is readable datapipe to receive data from network service.// |writable| is writable datapipe used to transfer the actual content of the// message(data) to the network service. The network services later sends out// the actual message by framing each message from the meta-info given from// the renderer side with |SendMessage()|.OnConnectionEstablished(pending_remoteWebSocket socket,pending_receiverWebSocketClient client_receiver,WebSocketHandshakeResponse response,handledata_pipe_consumer readable,handledata_pipe_producer writable);
};// The interface for the client side of WebSocket. Implemented by renderer
// processes to receive messages from the network service.
interface WebSocketClient {// Receive a non-control frame from the remote server.// - |fin| indicates that this frame is the last in the current message.// - |type| is the type of the message. On the first frame of a message, it// must be set to either WebSocketMessageType.TEXT or// WebSocketMessageType.BINARY. On subsequent frames, it must be set to// WebSocketMessageType.CONTINUATION, and the type is the same as that of// the first message.// - |data_length| is the length of data and actual data is read via// |readable| on WebSocketHandshakeClient.OnConnectionEstablished.// If |type| is WebSocketMessageType.TEXT, then the concatenation of all// the frames in the message must be valid UTF-8.// If |fin| is not set, |data_length| must be non-zero.OnDataFrame(bool fin,WebSocketMessageType type,uint64 data_length);// Drop the channel.//// When sent by the renderer, this will cause a Close message will be sent and// the TCP/IP connection will be closed.//// When sent by the browser, this indicates that a Close has been received,// the connection was closed, or a network or protocol error occurred.//// - |code| is one of the reason codes specified in RFC6455.// - |reason|, if non-empty, is a UTF-8 encoded string which may be useful// for debugging but is not necessarily human-readable, as supplied by the// server in the Close message.// - If |was_clean| is false, then the WebSocket connection was not closed// cleanly.OnDropChannel(bool was_clean, uint16 code, string reason);// Notify the renderer that a closing handshake has been initiated by the// server, so that it can set the Javascript readyState to CLOSING.OnClosingHandshake();
};// The interface for the server side of WebSocket. Implemented by the network
// service. Used to send out data to the network service.
interface WebSocket {// Sends a message via mojo datapipe to the remote server.// - |type| is the type of the message. It must be set to either// WebSocketMessageType.TEXT or WebSocketMessageType.BINARY.// - |data_length| is the actual length of message. The message is written to// the datapipe named |writable| in the// WebSocketHandshakeClient.OnConnectionEstablished message.//// If |type| is WebSocketMessageType.TEXT, then the message must be// valid UTF-8.SendMessage(WebSocketMessageType type, uint64 data_length);// Let browser to start receiving WebSocket data frames from network stream.// TODO(yoichio): Remove this by move Connect() after checking throttle at// WebSocketChannelImpl::Connect so that OnAddChannelResponse is// actual signal to start receive data frame.StartReceiving();// Close the channel gracefully.//// When sent by the renderer, this will cause a Close message will be sent and// the TCP/IP connection will be closed.//// - |code| is one of the reason codes specified in RFC6455.// - |reason|, if non-empty, is a UTF-8 encoded string which may be useful for// debugging but is not necessarily human-readable, as supplied by the// server in the Close message.StartClosingHandshake(uint16 code, string reason);
};2、websocket.mojom接口实现
out\Debug\gen\services\network\public\mojom\websocket.mojom.cc
out\Debug\gen\services\network\public\mojom\websocket.mojom.h
2.1)、数据发送接口SendMessage 2.1.1)、数据发送接口发送端WebSocketProxy::SendMessage //message.set_method_name(SendMessage);c
void WebSocketProxy::SendMessage(WebSocketMessageType in_type, uint64_t in_data_length) {
#if BUILDFLAG(MOJO_TRACE_ENABLED)TRACE_EVENT1(mojom, Send network::mojom::WebSocket::SendMessage, input_parameters,[](perfetto::TracedValue context){auto dict std::move(context).WriteDictionary();perfetto::WriteIntoTracedValueWithFallback(dict.AddItem(type), in_type,value of type WebSocketMessageType);perfetto::WriteIntoTracedValueWithFallback(dict.AddItem(data_length), in_data_length,value of type uint64_t);});
#endifconst bool kExpectsResponse false;const bool kIsSync false;const bool kAllowInterrupt true;const bool is_urgent false;const uint32_t kFlags ((kExpectsResponse) ? mojo::Message::kFlagExpectsResponse : 0) |((kIsSync) ? mojo::Message::kFlagIsSync : 0) |((kAllowInterrupt) ? 0 : mojo::Message::kFlagNoInterrupt) |((is_urgent) ? mojo::Message::kFlagIsUrgent : 0);mojo::Message message(internal::kWebSocket_SendMessage_Name, kFlags, 0, 0, nullptr);mojo::internal::MessageFragment::network::mojom::internal::WebSocket_SendMessage_Params_Data params(message);params.Allocate();mojo::internal::Serialize::network::mojom::WebSocketMessageType(in_type, params-type);params-data_length in_data_length;#if defined(ENABLE_IPC_FUZZER)message.set_interface_name(WebSocket::Name_);message.set_method_name(SendMessage);
#endif// This return value may be ignored as false implies the Connector has// encountered an error, which will be visible through other means.::mojo::internal::SendMojoMessage(*receiver_, message);
} 2.1.2)、数据发送接口接收端实现 impl-SendMessage(std::move(p_type),std::move(p_data_length));
// static
bool WebSocketStubDispatch::Accept(WebSocket* impl,mojo::Message* message) {switch (message-header()-name) {case internal::kWebSocket_SendMessage_Name: {DCHECK(message-is_serialized());internal::WebSocket_SendMessage_Params_Data* params reinterpret_castinternal::WebSocket_SendMessage_Params_Data*(message-mutable_payload());bool success true;WebSocketMessageType p_type{};uint64_t p_data_length{};WebSocket_SendMessage_ParamsDataView input_data_view(params, message);if (success !input_data_view.ReadType(p_type))success false;if (success)p_data_length input_data_view.data_length();if (!success) {ReportValidationErrorForMessage(message,mojo::internal::VALIDATION_ERROR_DESERIALIZATION_FAILED,WebSocket::Name_, 0, false);return false;}// A null |impl| means no implementation was bound.DCHECK(impl);impl-SendMessage(
std::move(p_type),
std::move(p_data_length));return true;}.........................................
}
2.2)、数据接收接口OnDataFrame
2.2.1)、数据接收接口 发送端OnDataFrame
WebSocketClientProxy::OnDataFrame message.set_method_name(OnDataFrame);
void WebSocketClientProxy::OnDataFrame(bool in_fin, WebSocketMessageType in_type, uint64_t in_data_length) {
#if BUILDFLAG(MOJO_TRACE_ENABLED)TRACE_EVENT1(mojom, Send network::mojom::WebSocketClient::OnDataFrame, input_parameters,[](perfetto::TracedValue context){auto dict std::move(context).WriteDictionary();perfetto::WriteIntoTracedValueWithFallback(dict.AddItem(fin), in_fin,value of type bool);perfetto::WriteIntoTracedValueWithFallback(dict.AddItem(type), in_type,value of type WebSocketMessageType);perfetto::WriteIntoTracedValueWithFallback(dict.AddItem(data_length), in_data_length,value of type uint64_t);});
#endifconst bool kExpectsResponse false;const bool kIsSync false;const bool kAllowInterrupt true;const bool is_urgent false;const uint32_t kFlags ((kExpectsResponse) ? mojo::Message::kFlagExpectsResponse : 0) |((kIsSync) ? mojo::Message::kFlagIsSync : 0) |((kAllowInterrupt) ? 0 : mojo::Message::kFlagNoInterrupt) |((is_urgent) ? mojo::Message::kFlagIsUrgent : 0);mojo::Message message(internal::kWebSocketClient_OnDataFrame_Name, kFlags, 0, 0, nullptr);mojo::internal::MessageFragment::network::mojom::internal::WebSocketClient_OnDataFrame_Params_Data params(message);params.Allocate();params-fin in_fin;mojo::internal::Serialize::network::mojom::WebSocketMessageType(in_type, params-type);params-data_length in_data_length;#if defined(ENABLE_IPC_FUZZER)message.set_interface_name(WebSocketClient::Name_);message.set_method_name(OnDataFrame);
#endif// This return value may be ignored as false implies the Connector has// encountered an error, which will be visible through other means.::mojo::internal::SendMojoMessage(*receiver_, message);
}
2.2.2)、数据接收接口 接收端OnDataFrame impl-OnDataFrame(std::move(p_fin), std::move(p_type), std::move(p_data_length));
// static
bool WebSocketClientStubDispatch::Accept(WebSocketClient* impl,mojo::Message* message) {switch (message-header()-name) {case internal::kWebSocketClient_OnDataFrame_Name: {DCHECK(message-is_serialized());internal::WebSocketClient_OnDataFrame_Params_Data* params reinterpret_castinternal::WebSocketClient_OnDataFrame_Params_Data*(message-mutable_payload());bool success true;bool p_fin{};WebSocketMessageType p_type{};uint64_t p_data_length{};WebSocketClient_OnDataFrame_ParamsDataView input_data_view(params, message);if (success)p_fin input_data_view.fin();if (success !input_data_view.ReadType(p_type))success false;if (success)p_data_length input_data_view.data_length();if (!success) {ReportValidationErrorForMessage(message,mojo::internal::VALIDATION_ERROR_DESERIALIZATION_FAILED,WebSocketClient::Name_, 0, false);return false;}// A null |impl| means no implementation was bound.DCHECK(impl);impl-OnDataFrame(
std::move(p_fin),
std::move(p_type),
std::move(p_data_length));return true;}。。。。。。。。。。。。。。。。。。。。。。。。。。。
}
3、websocket.mojom接口 network实现[net进程]
services\network\websocket.h
services\network\websocket.cc
WebSocket::SendMessage和WebSocket::WebSocketEventHandler::OnDataFrame
与render进程的WebSocketProxy::SendMessage(和WebSocketClientStubDispatch::OnDataFrame相互对应。
class GURL;namespace base {
class Location;
} // namespace basenamespace net {
class IOBuffer;
class IsolationInfo;
class SSLInfo;
class SiteForCookies;
class WebSocketChannel;
} // namespace netnamespace network {class WebSocketFactory;// Host of net::WebSocketChannel.
class COMPONENT_EXPORT(NETWORK_SERVICE) WebSocket : public mojom::WebSocket {public:using HasRawHeadersAccess base::StrongAliasclass HasRawHeadersAccessTag, bool;WebSocket(WebSocketFactory* factory,const GURL url,const std::vectorstd::string requested_protocols,const net::SiteForCookies site_for_cookies,bool has_storage_access,const net::IsolationInfo isolation_info,std::vectormojom::HttpHeaderPtr additional_headers,const url::Origin origin,uint32_t options,net::NetworkTrafficAnnotationTag traffic_annotation,HasRawHeadersAccess has_raw_cookie_access,mojo::PendingRemotemojom::WebSocketHandshakeClient handshake_client,mojo::PendingRemotemojom::URLLoaderNetworkServiceObserverurl_loader_network_observer,mojo::PendingRemotemojom::WebSocketAuthenticationHandler auth_handler,mojo::PendingRemotemojom::TrustedHeaderClient header_client,absl::optionalWebSocketThrottler::PendingConnectionpending_connection_tracker,base::TimeDelta delay,const absl::optionalbase::UnguessableToken throttling_profile_id);WebSocket(const WebSocket) delete;WebSocket operator(const WebSocket) delete;~WebSocket() override;// mojom::WebSocket methods:void SendMessage(mojom::WebSocketMessageType type,uint64_t data_length) override;void StartReceiving() override;void StartClosingHandshake(uint16_t code, const std::string reason) override;// Whether to allow sending/setting cookies during WebSocket handshakes for// |url|. This decision is based on the |options_| and |origin_| this// WebSocket was created with.bool AllowCookies(const GURL url) const;// These methods are called by the network delegate to forward these events to// the |header_client_|.int OnBeforeStartTransaction(const net::HttpRequestHeaders headers,net::NetworkDelegate::OnBeforeStartTransactionCallback callback);int OnHeadersReceived(net::CompletionOnceCallback callback,const net::HttpResponseHeaders* original_response_headers,scoped_refptrnet::HttpResponseHeaders* override_response_headers,absl::optionalGURL* preserve_fragment_on_redirect_url);// Gets the WebSocket associated with this request.static WebSocket* ForRequest(const net::URLRequest request);static const void* const kUserDataKey;private:class WebSocketEventHandler;struct CloseInfo;// This class is used to set the WebSocket as user data on a URLRequest. This// is used instead of WebSocket directly because SetUserData requires a// std::unique_ptr. This is safe because WebSocket owns the URLRequest, so is// guaranteed to outlive it.class UnownedPointer : public base::SupportsUserData::Data {public:explicit UnownedPointer(WebSocket* pointer) : pointer_(pointer) {}UnownedPointer(const UnownedPointer) delete;UnownedPointer operator(const UnownedPointer) delete;WebSocket* get() const { return pointer_; }private:const raw_ptrWebSocket pointer_;};struct DataFrame final {DataFrame(mojom::WebSocketMessageType type,uint64_t data_length,bool do_not_fragment): type(type),data_length(data_length),do_not_fragment(do_not_fragment) {}mojom::WebSocketMessageType type;uint64_t data_length;const bool do_not_fragment;};void OnConnectionError(const base::Location set_from);void AddChannel(const GURL socket_url,const std::vectorstd::string requested_protocols,const net::SiteForCookies site_for_cookies,bool has_storage_access,const net::IsolationInfo isolation_info,std::vectormojom::HttpHeaderPtr additional_headers);void OnSSLCertificateErrorResponse(std::unique_ptrnet::WebSocketEventInterface::SSLErrorCallbackscallbacks,const net::SSLInfo ssl_info,int net_error);void OnAuthRequiredComplete(base::OnceCallbackvoid(const net::AuthCredentials*) callback,const absl::optionalnet::AuthCredentials credential);void OnBeforeSendHeadersComplete(net::NetworkDelegate::OnBeforeStartTransactionCallback callback,int result,const absl::optionalnet::HttpRequestHeaders headers);void OnHeadersReceivedComplete(net::CompletionOnceCallback callback,scoped_refptrnet::HttpResponseHeaders* out_headers,absl::optionalGURL* out_preserve_fragment_on_redirect_url,int result,const absl::optionalstd::string headers,const absl::optionalGURL preserve_fragment_on_redirect_url);void Reset();enum class InterruptionReason {// Not interrupted or not resuming after interruptions (but processing a// brand new frame)kNone,// Interrupted by empty Mojo pipe or resuming afterwardskMojoPipe,// Interrupted by the interceptor or resuming afterwardskInterceptor,};// Datapipe functions to receive.void OnWritable(MojoResult result, const mojo::HandleSignalsState state);void SendPendingDataFrames(InterruptionReason resume_reason);void SendDataFrame(base::spanconst char* data_span);// Datapipe functions to send.void OnReadable(MojoResult result, const mojo::HandleSignalsState state);void ReadAndSendFromDataPipe(InterruptionReason resume_reason);// This helper method only called from ReadAndSendFromDataPipe.// Note that it may indirectly delete |this|.// Returns true if the frame has been sent completely.bool ReadAndSendFrameFromDataPipe(DataFrame* data_frame);void ResumeDataPipeReading();// |factory_| owns |this|.const raw_ptrWebSocketFactory factory_;mojo::Receivermojom::WebSocket receiver_{this};mojo::Remotemojom::URLLoaderNetworkServiceObserverurl_loader_network_observer_;mojo::Remotemojom::WebSocketHandshakeClient handshake_client_;mojo::Remotemojom::WebSocketClient client_;mojo::Remotemojom::WebSocketAuthenticationHandler auth_handler_;mojo::Remotemojom::TrustedHeaderClient header_client_;absl::optionalWebSocketThrottler::PendingConnectionpending_connection_tracker_;// The channel we use to send events to the network.std::unique_ptrnet::WebSocketChannel channel_;// Delay used for per-renderer WebSocket throttling.const base::TimeDelta delay_;const uint32_t options_;const net::NetworkTrafficAnnotationTag traffic_annotation_;// The web origin to use for the WebSocket.const url::Origin origin_;// For 3rd-party cookie permission checking.net::SiteForCookies site_for_cookies_;bool handshake_succeeded_ false;const HasRawHeadersAccess has_raw_headers_access_;InterruptionReason incoming_frames_interrupted_ InterruptionReason::kNone;InterruptionReason outgoing_frames_interrupted_ InterruptionReason::kNone;// Datapipe fields to receive.mojo::ScopedDataPipeProducerHandle writable_;mojo::SimpleWatcher writable_watcher_;base::queuebase::spanconst char pending_data_frames_;// Datapipe fields to send.mojo::ScopedDataPipeConsumerHandle readable_;mojo::SimpleWatcher readable_watcher_;base::queueDataFrame pending_send_data_frames_;bool blocked_on_websocket_channel_ false;// True if we should preserve the old behaviour where 64KB messages were// never fragmented.// TODO(ricea): Remove the flag once we know whether we really need this or// not. See https://crbug.com/1086273.const bool reassemble_short_messages_;// Temporary buffer for storage of short messages that have been fragmented by// the data pipe. Only messages that are actually fragmented are copied into// here.scoped_refptrnet::IOBuffer message_under_reassembly_;// Number of bytes that have been written to |message_under_reassembly_| so// far.size_t bytes_reassembled_ 0;// Set when StartClosingHandshake() is called while// |pending_send_data_frames_| is non-empty. This can happen due to a race// condition between the readable signal on the data pipe and the channel on// which StartClosingHandshake() is called.std::unique_ptrCloseInfo pending_start_closing_handshake_;const absl::optionalbase::UnguessableToken throttling_profile_id_;uint32_t net_log_source_id_ net::NetLogSource::kInvalidId;std::unique_ptrWebSocketInterceptor frame_interceptor_;base::WeakPtrFactoryWebSocket weak_ptr_factory_{this};
};} // namespace network4、websocket.mojom接口 network实现[render进程]
third_party\blink\renderer\modules\websockets\websocket_channel_impl.h
third_party\blink\renderer\modules\websockets\websocket_channel_impl.cc
HeapMojoRemotenetwork::mojom::blink::WebSocket websocket_;//WebSocketProxy对象定义
WebSocketProxy::SendMessage(和WebSocketClientStubDispatch::OnDataFrame
是与net进程 发送和接收数据的具体实现。 namespace v8 {
class Isolate;
} // namespace v8namespace blink {class BaseFetchContext;
enum class FileErrorCode;
class WebSocketChannelClient;
class WebSocketHandshakeThrottle;// This is an implementation of WebSocketChannel. This is created on the main
// thread for Document, or on the worker thread for WorkerGlobalScope. All
// functions must be called on the execution contexts thread.
class MODULES_EXPORT WebSocketChannelImpl final: public WebSocketChannel,public network::mojom::blink::WebSocketHandshakeClient,public network::mojom::blink::WebSocketClient {USING_PRE_FINALIZER(WebSocketChannelImpl, Dispose);public:// Public for use in tests.static constexpr size_t kMaxWebSocketsPerRenderProcess 255u;// You can specify the source file and the line number information// explicitly by passing the last parameter.// In the usual case, they are set automatically and you dont have to// pass it.static WebSocketChannelImpl* Create(ExecutionContext* context,WebSocketChannelClient* client,std::unique_ptrSourceLocation location);static WebSocketChannelImpl* CreateForTesting(ExecutionContext*,WebSocketChannelClient*,std::unique_ptrSourceLocation,std::unique_ptrWebSocketHandshakeThrottle);WebSocketChannelImpl(ExecutionContext*,WebSocketChannelClient*,std::unique_ptrSourceLocation);~WebSocketChannelImpl() override;// WebSocketChannel functions.bool Connect(const KURL, const String protocol) override;SendResult Send(const std::string message,base::OnceClosure completion_callback) override;SendResult Send(const DOMArrayBuffer,size_t byte_offset,size_t byte_length,base::OnceClosure completion_callback) override;void Send(scoped_refptrBlobDataHandle) override;// Start closing handshake. Use the CloseEventCodeNotSpecified for the code// argument to omit payload.void Close(int code, const String reason) override;void Fail(const String reason,mojom::ConsoleMessageLevel,std::unique_ptrSourceLocation) override;void Disconnect() override;void CancelHandshake() override;void ApplyBackpressure() override;void RemoveBackpressure() override;// network::mojom::blink::WebSocketHandshakeClient methods:void OnOpeningHandshakeStarted(network::mojom::blink::WebSocketHandshakeRequestPtr) override;void OnFailure(const WTF::String message,int net_error,int response_code) override;void OnConnectionEstablished(mojo::PendingRemotenetwork::mojom::blink::WebSocket websocket,mojo::PendingReceivernetwork::mojom::blink::WebSocketClientclient_receiver,network::mojom::blink::WebSocketHandshakeResponsePtr,mojo::ScopedDataPipeConsumerHandle readable,mojo::ScopedDataPipeProducerHandle writable) override;// network::mojom::blink::WebSocketClient methods:void OnDataFrame(bool fin,network::mojom::blink::WebSocketMessageType,uint64_t data_length) override;void OnDropChannel(bool was_clean,uint16_t code,const String reason) override;void OnClosingHandshake() override;void Trace(Visitor*) const override;private:struct DataFrame final {DataFrame(bool fin,network::mojom::blink::WebSocketMessageType type,uint32_t data_length): fin(fin), type(type), data_length(data_length) {}bool fin;network::mojom::blink::WebSocketMessageType type;uint32_t data_length;};// Used by BlobLoader and Message, so defined here so that it can be shared.class MessageDataDeleter {public:// This constructor exists to permit default construction of the MessageData// type, but the deleter cannot be called when it was used.MessageDataDeleter() : isolate_(nullptr), size_(0) {}MessageDataDeleter(v8::Isolate* isolate, size_t size): isolate_(isolate), size_(size) {}MessageDataDeleter(const MessageDataDeleter) default;MessageDataDeleter operator(const MessageDataDeleter) default;void operator()(char* p) const;private:v8::Isolate* isolate_;size_t size_;};using MessageData std::unique_ptrchar[], MessageDataDeleter;static MessageData CreateMessageData(v8::Isolate*, size_t);friend class WebSocketChannelImplHandshakeThrottleTest;FRIEND_TEST_ALL_PREFIXES(WebSocketChannelImplHandshakeThrottleTest,ThrottleSucceedsFirst);FRIEND_TEST_ALL_PREFIXES(WebSocketChannelImplHandshakeThrottleTest,HandshakeSucceedsFirst);FRIEND_TEST_ALL_PREFIXES(WebSocketChannelImplHandshakeThrottleTest,ThrottleReportsErrorBeforeConnect);FRIEND_TEST_ALL_PREFIXES(WebSocketChannelImplHandshakeThrottleTest,ThrottleReportsErrorAfterConnect);class BlobLoader;class Message;struct ConnectInfo;enum MessageType {kMessageTypeText,kMessageTypeBlob,kMessageTypeArrayBuffer,kMessageTypeClose,};struct ReceivedMessage {bool is_message_text;Vectorchar data;};class Message final {DISALLOW_NEW();public:using DidCallSendMessage base::StrongAliasclass DidCallSendMessageTag, bool;// Initializes message as a stringMessage(v8::Isolate*,const std::string,base::OnceClosure completion_callback,DidCallSendMessage did_call_send_message);// Initializes message as a blobexplicit Message(scoped_refptrBlobDataHandle);// Initializes message from the contents of a blobMessage(MessageData, size_t);// Initializes message as a ArrayBufferMessage(v8::Isolate*,base::spanconst char message,base::OnceClosure completion_callback,DidCallSendMessage did_call_send_message);// Initializes a Blank messageMessage(MessageType type,base::spanconst char message,base::OnceClosure completion_callback);// Close messageMessage(uint16_t code, const String reason);Message(const Message) delete;Message operator(const Message) delete;Message(Message);Message operator(Message);MessageType Type() const;scoped_refptrBlobDataHandle GetBlobDataHandle();DidCallSendMessage GetDidCallSendMessage() const;uint16_t Code() const;String Reason() const;base::OnceClosure CompletionCallback();// Returns a mutable |pending_payload_|. Since calling code always mutates// the value, |pending_payload_| only has a mutable getter.base::spanconst char MutablePendingPayload();void SetDidCallSendMessage(DidCallSendMessage did_call_send_message);private:MessageData message_data_;MessageType type_;scoped_refptrBlobDataHandle blob_data_handle_;base::spanconst char pending_payload_;DidCallSendMessage did_call_send_message_ DidCallSendMessage(false);uint16_t code_ 0;String reason_;base::OnceClosure completion_callback_;};// A handle to a global count of the number of WebSockets that have been// created. Can be used to limit the total number of WebSockets that have been// created in this render process.class ConnectionCountTrackerHandle {DISALLOW_NEW();public:enum class CountStatus {kOkayToConnect,kShouldNotConnect,};ConnectionCountTrackerHandle() default;~ConnectionCountTrackerHandle() default;ConnectionCountTrackerHandle(const ConnectionCountTrackerHandle) delete;ConnectionCountTrackerHandle operator(const ConnectionCountTrackerHandle) delete;// Increments the count and returns SHOULD_NOT_CONNECT if it exceeds// kMaxWebSocketsPerRenderProcess. Should only be called once.CountStatus IncrementAndCheckStatus();// Decrements the count. Should be called at least once. If there is no// matching call to IncrementAndCheckStatus() it does nothing, so it is safe// to call multiple times.void Decrement();private:bool incremented_ false;};// The state is defined to see the conceptual state more clearly than checking// various members (for DCHECKs for example). This is only used internally.enum class State {// The channel is running an opening handshake. This is the initial state.// It becomes |kOpen| when the connection is established. It becomes// |kDisconnected| when detecting an error.kConnecting,// The channel is ready to send / receive messages. It becomes// |kDisconnected| when the connection is closed or when an error happens.kOpen,// The channel is not ready for communication. The channel stays in this// state forever.kDisconnected,};State GetState() const;bool MaybeSendSynchronously(network::mojom::blink::WebSocketMessageType,base::spanconst char* data);void ProcessSendQueue();bool SendMessageData(base::spanconst char* data);void FailAsError(const String reason) {Fail(reason, mojom::ConsoleMessageLevel::kError,location_at_construction_-Clone());}void AbortAsyncOperations();void HandleDidClose(bool was_clean, uint16_t code, const String reason);// Completion callback. It is called with the results of throttling.void OnCompletion(const absl::optionalWebString error);// Methods for BlobLoader.void DidFinishLoadingBlob(MessageData, size_t);void BlobTooLarge();void DidFailLoadingBlob(FileErrorCode);void TearDownFailedConnection();bool ShouldDisallowConnection(const KURL);BaseFetchContext* GetBaseFetchContext() const;// Called when |readable_| becomes readable.void OnReadable(MojoResult result, const mojo::HandleSignalsState state);void ConsumePendingDataFrames();void ConsumeDataFrame(bool fin,network::mojom::blink::WebSocketMessageType type,const char* data,size_t data_size);// Called when |writable_| becomes writable.void OnWritable(MojoResult result, const mojo::HandleSignalsState state);MojoResult ProduceData(base::spanconst char* data,uint64_t* consumed_buffered_amount);String GetTextMessage(const Vectorbase::spanconst char chunks,wtf_size_t size);void OnConnectionError(const base::Location set_from,uint32_t custom_reason,const std::string description);void Dispose();const MemberWebSocketChannelClient client_;KURL url_;uint64_t identifier_;MemberBlobLoader blob_loader_;WTF::DequeMessage messages_;MemberWebSocketMessageChunkAccumulator message_chunks_;const MemberExecutionContext execution_context_;bool backpressure_ false;bool receiving_message_type_is_text_ false;bool received_text_is_all_ascii_ true;bool throttle_passed_ false;bool has_initiated_opening_handshake_ false;size_t sent_size_of_top_message_ 0;FrameScheduler::SchedulingAffectingFeatureHandlefeature_handle_for_scheduler_;WTF::String failure_message_;const std::unique_ptrconst SourceLocation location_at_construction_;network::mojom::blink::WebSocketHandshakeRequestPtr handshake_request_;std::unique_ptrWebSocketHandshakeThrottle handshake_throttle_;// This field is only initialised if the object is still waiting for a// throttle response when DidConnect is called.std::unique_ptrConnectInfo connect_info_;HeapMojoRemotenetwork::mojom::blink::WebSocket websocket_;HeapMojoReceivernetwork::mojom::blink::WebSocketHandshakeClient,WebSocketChannelImplhandshake_client_receiver_;HeapMojoReceivernetwork::mojom::blink::WebSocketClient, WebSocketChannelImplclient_receiver_;mojo::ScopedDataPipeConsumerHandle readable_;mojo::SimpleWatcher readable_watcher_;WTF::DequeDataFrame pending_data_frames_;mojo::ScopedDataPipeProducerHandle writable_;mojo::SimpleWatcher writable_watcher_;bool wait_for_writable_ false;ConnectionCountTrackerHandle connection_count_tracker_handle_;const scoped_refptrbase::SingleThreadTaskRunner file_reading_task_runner_;
};MODULES_EXPORT std::ostream operator(std::ostream,const WebSocketChannelImpl*);} // namespace blink
四、调用堆栈参考
Chromium 中HTML5 WebSocket实现分析c二-CSDN博客