Skip to content
This repository has been archived by the owner on Jan 18, 2024. It is now read-only.

Latest commit

 

History

History
117 lines (76 loc) · 4.21 KB

design.md

File metadata and controls

117 lines (76 loc) · 4.21 KB

Google BSD license https://developers.google.com/google-bsd-license
Copyright 2012 Google Inc. wrightt@google.com

iOS WebKit Debug Proxy Design

See the README.md for an overview.

Source

Architecture

The high-level design is shown below:

Alt overview

The various clients are shown below:

Alt clients

The major components of the ios_webkit_debug_proxy are:

  1. A device_listener that listens for iOS device add/remove events
  2. A (port, webinspector) pair for each device, e.g.:
    • [(port 9222 <--> iphoneX's inspector),
    • (port 9223 <--> iphoneY's inspector), ...]
  3. Zero or more active WebSocket clients, e.g.:
    • [websocketA is connected to :9222/devtools/page/7, ...]
  4. A socket_manager that handles all the socket I/O

The code is object-oriented via the use of structs and function pointers. For example, the device_listener struct defines two "public API" functions:

dl_status (*start)(dl_t self);
dl_status (*on_recv)(dl_t self, const char *buf, );

and three "abstract" callback functions:

dl_status (*send)(dl_t self, const char *buf, size_t length);
dl_status (*on_attach)(dl_t self, const char *device_id);
dl_status (*on_detach)(dl_t self, const char *device_id);

plus a field for client use:

void *state;

For example, examples/dl_client.c creates a listener and sets the missing callbacks:

int fd = dl_connect();
dl_t dl = dl_new(); // sets the "start" and "on_recv" functions
dl->state = fd;     // for use by "my_send"
dl->send = my_send; // --> send((int)dl->state, buf, length);
dl->on_attach = my_on_attach; // --> printf("%s", device_id);
dl->on_detach = my_on_detach; // --> ditto

then does:

dl->start();

Lastly, the client forwards all socket input to the listener's "on_recv" handler:

char buf[1024];
while (1) {
   int len = recv(fd, buf, 1024);
   if (dl->on_recv(dl, buf, len)) break;
}

where "on_recv" buffers the input and calls our "my_on_message" when it has a full message.

Note that the "on_recv" and "send" functions abstract the I/O from the interface, which simplifies debugging and unit testing.

The detailed design is shown below:

Alt design

Lines in red are controlled by the main "ios_webkit_debug_proxy". For example, although the figure shows a direct red line from the socket_manager's "on_recv" to the ios_webkit_debug_proxy's handler, this is implemented as a callback through ios_webkit_debug_proxy_main's "iwdpm_on_recv(...)". This design isolate the components from one another and simplifies both offline and per-component unit testing.

The code is single-threaded and uses non-blocking I/O. Instead of having a thread per socket that does blocking reads, the single socket_manager's non-blocking select forwards data to the "on_recv" function of websocket/webinspector/etc. This improves system scalability and makes it easier to debug and unit test.