注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

写着玩

Bob

 
 
 

日志

 
 
 
 

Chromium Web Socket design doc  

2010-01-10 22:33:24|  分类: Chrome |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |
Authors: yuzo, ukai, tyoshino
Status: Draft (as of Oct 23, 2009)

Table of Contents
This document describes Chromium HTML5 Web Socket design.
It is based on WebKit Web Socket design and describes chromium side in more detail.

High Level Structure

Chromium Web Socket design doc - yolcy - 写着玩

Legend:
  • green: webkit part (WebCore and platform)
  • orange: chromium IPC
  • blue: new code in chromium part
  • gray: existing code in chromium part

V8WebSocketCustom:  custom binding of WebSocket for V8 Engine.  It sits between V8 and WebCore::WebSocket.
will be in WebKit/WebCore/binding/v8/custom/.
   
WebCore::WebSocket: C++ class corresponding to WebSocket interface in JavaScript.  It also implements WebCore::WebSocketChannelClient so that it would receive events from WebCore::WebSocketChannelHandle. 
will be in WebKit/WebCore/websockets/.

WebCore::WebSocketChannel: Web Socket channel in WebCore.  It process Web Socket handshaking and data framing. Use WebCore::WebSocketHandshake to handshake. packing data in a frame and sent it to WebCore::SocketStreamHandle.  It implements WebCore::SocketStreamHandleClient, so that it will receive a frame from WebCore::SocketStreamHandle and depacking data from a frame.

WebCore::WebSocketHandshake: Perform WebSocket handshaking.

WebCore::SocketStreamHandle: Socket stream handle in WebCore/platform/network.  This is boundary between WebCore and platform.
It handles raw connection establishment (direct / via proxy / TLS) and send/receive data on the connection. 
In chromium, it is implemented by WebKit::WebSocketStreamHandle.  Each instance of WebKit::WebSocketStreamHandle has a unique socket_id that is used in chromium IPC. socket_id is given by browser process in response of ViewHostMsg_SocketStream_Connect.

In WebKit::WebSocketStreamHandle, it uses webkit_glue::WebSocketStreamHandleBridge to communicate with browser process. it will send ViewHostMsg_SocketStream* messages to browser or receive ViewMsg_SocketStream* messages from browser.
will be in webkit/api/src and webkit/glue.  Chromium IPC code is in chrome/browser/renderer_host.
All messages are "control" and async (IPC_MESSAGE_CONTROL), except Connect (this is sync messages).  Each socket is identified by socket_id, which is given by SocketStreamHost in browser process in response of ViewHostMsg_SocketStream_Connect.

WebKit::WebSocketStreamHandle: Explained above.
in webkit/api/public/WebSocketStreamHandle.h
webkit_glue::WebSocketStreamHandleImpl: Explained above. Implementation of WebKit::WebSocketStreamHandle
in webkit/glue/websocketstreamhandle_impl.*

webkit_glue::WebSocketStreamHandleBridge: Bridge interface explained above.
in webkit/glue/websocketstreamhandle_bridge.h
IPCWebSocketStreamHandleBridge (internal class): Implementaion of webkit_glue::WebSocketStreamHandleBridge
in chrome/renderer/socket_stream_dispatcher.cc
SocketStreamDispatcher: Handling IPC. Peer of SocketStreamDispatcherHost.
in chrome/renderer/socket_stream_dispatcher.cc

ViewHostMsg_SocketStream*: IPC messages sent from renderer to browser.
  • ViewHostMsg_SocketStream_Connect: request to open a new socket. called by WebSocketStreamHandle::connect(). return immediately once it gets socket_id and schedule to open the connection asynchronously.
    • GRUL url;  destination url
    • int* socket_id; response. unique id for the socket handle.
  • ViewHostMsg_SocketStream_SendData: trasmit data over the socket connection.  called by WebSocketStreamHandle::send().  if more bytes than max_amount_send_allowed will be sent, close the connection. Otherwise, accept the request and data will be sent asynchronously.  When data are sent, browser will send ViewMsg_SocketStream_DataSent back.
    • int socket_id  // Identify socket handle.
    • std::vector<char> dataopen issue: size limit? need multiplexing? -ukai 6/23/09 2:14 PM 
  • ViewHostMsg_SocketStream_Close: close the socket connection. called by WebSocketStreamHandle::close().  socket handle will be alive until ViewMsg_SocketStream_Closed received.
    • int request_id  // Identify socket handle.

ViewMsg_SocketStream*: IPC messages sent from browser to renderer.
  • ViewMsg_SocketStream_Connected: A connection is established. will call WebSocketStreamHandle::client()->didOpen().  renderer can send data on the connection. start receiving data on the connection.
    • int socket_id  // Identify socket handle.
    • int max_amount_send_allowed  // maximum amount to be sent at the same time. (max buffer size)
  • ViewMsg_SocketStream_DataSent:  The socket sends data so that renderer can send data by ViewHostMsg_SocketStream_SendData.
    • int socket_id  // Identify socket handle.
    • int amount_sent  // the number of bytes sent on the socket.
    • ViewMsg_SocketStream_ReceivedData: data is received on the socket.
      • int socket_id  // Identify socket handle.
      • std::vector<char> data 
    • ViewMsg_SocketStream_Closed: the socket is closed (in the browser).  SocketStreamHandle has been released.  socket_id is invalidated.
      • int socket_id  // Identify socket handle.

    SocketStreamDispatcherHost: Processes ViewHostMsg_SocketStream* and sends ViewMsg_SocketStream*.  Injected in ResourceMessageFilter.
    in chrome/browser/renderer_host/socket_stream_dispatcher_host.*

    SocketStreamHost: Host of WebCore::WebSocketStreamHandle. It will receive ViewHostMsg_SocketStream*. messages from renderer.  
    in chrome/browser/renderer_host/socket_stream_host.*
    It manages mapping between socket_id and SocketStream.

    SocketStream: Manages socket stream.  connect/read/write/close over ClientSocket (net/socket).
    in net/socket_stream/socket_stream.*

    WebKit API

    We'll add new API in WebKit API / WebKitClient API. 

    webkit/api/public/WebKit.h:

    namespace WebKit {
    ...
      // Enables HTML5 Web Sockets support.
      WEBKIT_API void enableWebSockets();
    ...
    }

    webkit/api/public/WebKitClient.h:

    namespace WebKit {
    ...
      // Network
    ...
      // Returns a new WebKit::WebSocketStreamHandle instance.
      virtual WebSocketStreamHandle* createSocketStreamHandle() = 0;
    ...
    }

    webkit/api/public/WebSocketStreamHandle.h:

    namespace WebKit {
      class WebSocketStreamHandleClient;
      class WebData;

      class WebSocketStreamHandle {
      public:
          virtual ~WebSocketStreamHandle() {}
          virtual void connect(const WebURL&, WebSocketStreamHandleClient*) = 0;
          virtual void send(const WebData& data) = 0;
          virtual void close() = 0;
      };
    }

    webkit/api/public/WebSocketStreamHandleClient.h:

    namespace WebKit {
      class WebSocketStreamHandle;
      class WebData;

      class WebSocketStreamHandleClient {
      public:
         virtual void didOpen(WebSocketStreamHandle*, int max_amount_send_allowed) = 0;
         virtual void canDataSent(WebSocketStraemHandle*, int amount_sent) = 0;
         virtual void didReceiveData(WebSocketStreamHandle*, const WebData&) = 0;
         virtual void didClose(WebSocketStreamHandle*) = 0;
      };
    }

    Flows

    Establish WebSocket connection

    In renderer:
    1. in JavaScript, WebSocket(url [,protocol]) constructor is called
    2. create WebCore::WebSocket object and associate it with the JavaScript WebSocket object.
    3. it calls WebCore::WebSocketChannel::connect(), which calls WebCore::SocketStreamHandle::connect().
    4. WebCore::SocketStreamHandle::connect() calls WebKit::WebSocketStreamHandle::connect()
    5. in WebKit::WebSocketStreamHandle::connect(), send ViewHostMsg_SocketStream_Connect message to browser and get socket_id.
    In browser: (IO thread)
    1. handle ViewHostMsg_SocketStream_Connect message by SocketStreamDispatcherHost.
    2. create SocketStreamHost for the request. Assign new socket_id to it. SocketStreamDispatcherHost is its delegate.
    3. create SocketStreamRequest for it.
    4. SocketStreamRequest start job.
    5. return socket_id to the renderer.
    6. In SocketStreamJob.
      1. connect via proxy with method="CONNECT" over TCPClientSocket if proxy is configured.
      2. use SSLClientSocket if the connection is secure.
    7. Once connected, send ViewMsg_SocketStream_Connected to the renderer.
    In renderer
    1. handle ViewMsg_SocketStream_Connected message.  find associated WebSocketStreamHandle for its socket_id.
    2. make socket idle.
    3. call WebSocketClient::didOpen.  WebSocketChannel start performing web socket handshaking.
      1. send client handshake message
      2. receive server handshake message
      3. check handshake message.
    4. if it's ok, establish the connection, call m_client->didConnect()
    5. readyState is OPEN and "open" event is dispatched in JavaScript

    Send a message

    In renderer:
    1. in JavaScript, WebSocket::send is used to send message.
    2. WebCore::WebSocket::send() calls m_channel->send().
    3. WebCore::WebSocketChannel::send() builds web socket frame and call m_handle->send(buf, buflen)
    4. WebCore::SocketStreamHandle::send() creates WebData from buf,buflen and call WebKit::WebSocketStreamHandle::send().
    5. In WebKit::WebSocketStreamHandle::send()
      1. if it will exceed max_amount_send_allowed, return false.
      1. Otherwise, send ViewHostMsg_SocketStream_SendData message to browser. 
    In browser: (IO thread)
    1. handle ViewHostMsg_SocketStream_SendData message by SocketStreamDispatcherHost.
    2. find SocketStreamHost by socket_id.
    3. call SocketStreamJob::Send for the SocketStreamHost.
    4. SocketStreamHost tries to write on ClientSocket.
    5. ClientSocket wrote data, call canSend of SocketStreamRequest::Delegate.
    6. SocketStreamDispatcherHost send ViewMsg_SocketStream_DataSent to renderer
    In renderer:
    1. handle ViewMsg_SocketStream_CanSend in SocketStreamDispatcher. find associated WebSocketStreamHandle for its socket_id.
    2. make socket idle.
    3. call WebSocketStreamHandleClient::DataSent

    Receive a message

    In browser: (IO thread)
    1. ClientSocket receives data from the connection (TCPClientSocket or SSLCLientSocket)
    2. call didReceiveData of SocketStreamRequest::Delegate.
    3. SocketStreamDispacherHost send ViewMsg_SocketStream_ReceivedData to renderer
    In renderer:
    1. handle ViewMsg_SocketStream_ReceivedData message.  find associated WebSocketStreamHandle for its socket_id.
    2. call client()->didReceiveData()
    3. WebCore::WebSocketChannel::didReceive() process web socket fram in m_handle->bufferedData()
      1. remove web socket frame from m_handle->bufferedData()
      2. extract message if frame_type == 0x00, call m_client->didReceiveMessage()
    4. WebCore::WebSocket::didReceiveMessage() create MessageEvent for the message and dispatch the event.

    Disconnect the connection (from JavaScript)

    In renderer:
    1. In JavaScript, WebSocket::close is called
    2. WebCore::WebSocket::close() change readyState to CLOSED and calls m_channel->close()
    3. WebCore::WebSocketChannel::disconnect() calls m_handle->close()
    4. WebCore::SocketStreamHandle::close(), calls WebKit::WebSocketStreamHandle::close()
    5. WebKit::WebSocketStreamHandle::close() sends ViewHostMsg_SocketStream_Close message to browser
    In browser: (IO thread)
    1. handle ViewHostMsg_SocketStream_Close message by SocketStreamDispatcherHost.  find associated SocketStreamHost for its socket_id.
    2. call SocketStreamJob::Close for the SocketStreamHost.
    3. SocketStreamHost closes the ClientSocket.
    4. SocketStreamJob will notice the connection is closed.

    Connection closed (from raw connection)

    In browser: (IO thread)
    1. SocketStreamJob notices client socket is not connected.  delete the client socket and notify it delegate.
    2. SocketStreamDispatcherHost sends ViewMsg_SocketStream_Closed to renderer and delete SocketStreamHost for the socket_id.
    In renderer:
    1. handle ViewMsg_SocketStream_Closed message.  find associate WebSocketStreamHandle for its socket_id.
    2. WebSocketStreamHandle calls client()->didClose()
    3. WebCore::WebSocketChannel::didClose() destroys m_handle and call m_client->didClose()
    4. WebCore::WebSocket::didClose() changes readyState to CLOSED, create "close" event and dispatch the event.

    Other modification

    Adds "ws" and "wss" in googleurl. (Web Socket URL scheme)

    Security Considerations

    See Security Consideration secion in WebKit Web Socket design doc.

    ** Any chromium specific ISSUE? ** ...

    Layout Test Plan

    WebKit and Chromium uses different http server for layout tests.  WebKit uses apache  (launched by WebKitTools/Scripts/run-webkit-httpd, configuration in LayoutTests/http/conf/).  Chromium uses lighttpd (launched by webkit/tools/layout_tests/run_webkit_tests.py that imports webkit/tools/layout_tests/layout_package/http_server.py).
    Since there are no apache Web Socket module nor lighttpd Web Sockets module yet.
    So, we're developing simple Web Socket server implementation by python to use it for layout tests in both WebKit and chromium.

    Open Issues

    • Do we need to split/multiplexing frame in chromium IPC? (in case if websocket transmits huge data and it occupies chromium IPC long time?)
      • spec says: "If the user agent is faced with content that is too large to be handled appropriately, then it must fail the Web Socket connection.".  how large is the limit?

      Work Estimates

      By End of '09 Q2: design doc reviewed.
      By End of '09 Q3: land minimum functionalities in webkit.
      By End of Oct '09: land basic functionalities in chromium/webkit.  ready to use in trunk.

      Reference


      Document History

      DateAuthorDescription
      Oct 23, 2009tyoshinoUpdated High Level Architecture section and the diagram in it
      Sept 8, 2009ukaiCanSend -> DataSent. add max_amount_send_allowed and amount_sent
      Sept 4, 2009
      ukai
      make SendData async (remove accepted)
      Sept 2, 2009ukaiChange to SocketStreamHandle.
      June 26, 2009ukaiupdating by chromium-dev review feedback
      June 23, 2009ukaiInitial draft

        评论这张
       
      阅读(1360)| 评论(0)
      推荐 转载

      历史上的今天

      评论

      <#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
       
       
       
       
       
       
       
       
       
       
       
       
       
       

      页脚

      网易公司版权所有 ©1997-2017