Request in a QUIC way @shibuya.apk#28

A374f41eab3f73c50d8bab0652cb207a?s=47 TakuSemba
September 27, 2018

Request in a QUIC way @shibuya.apk#28

A374f41eab3f73c50d8bab0652cb207a?s=128

TakuSemba

September 27, 2018
Tweet

Transcript

  1. None
  2. @takusemba https://github.com/TakuSemba

  3. QUIC?

  4. Quick UDP Internet Connections

  5. QUIC

  6. Google QUIC https://www.chromium.org/quic

  7. QUIC for IETF https://tools.ietf.org/html/draft-hamilton-early-deployment-quic-00

  8. Merits

  9. Merits ɾConnection establishment latency

  10. Connection establishment latency Client Server

  11. Connection establishment latency TCP Client Server

  12. Connection establishment latency TCP Client Server

  13. Connection establishment latency Client Server TCP + TLS

  14. Connection establishment latency TCP + TLS Client Server

  15. Connection establishment latency TCP + TLS Client Server 1-3 roundtrips

  16. Connection establishment latency TCP + TLS Application Data Client Server

    1-3 roundtrips
  17. Connection establishment latency QUIC Client Server

  18. Connection establishment latency QUIC Client Server

  19. Connection establishment latency QUIC Client Server 0-1 roundtrips

  20. Connection establishment latency QUIC Application Data Client Server 0-1 roundtrips

  21. Merits ɾConnection establishment latency

  22. Merits ɾConnection establishment latency ɾMultiplexing

  23. Multiplexing TCP Client Server

  24. Multiplexing TCP Client Server

  25. Multiplexing TCP head of line blocking Client Server

  26. Multiplexing QUIC stream 1 stream 2 stream 3 Client Server

  27. Multiplexing QUIC stream 1 stream 2 stream 3 Client Server

  28. Multiplexing QUIC … … stream 1 stream 2 stream 3

    Client Server
  29. Merits ɾConnection establishment latency ɾMultiplexing

  30. Merits ɾConnection establishment latency ɾMultiplexing ɾConnection Migration

  31. Connection Migration TCP IP: yyy.yyy.yyy.yyy Port: bb IP: xxx.xxx.xxx.xxx Port:

    aa Client Server
  32. Connection Migration TCP IP: yyy.yyy.yyy.yyy Port: bb IP: zzz.zzz.zzz.zzz Port:

    cc Client Server
  33. Connection Migration QUIC Connection ID: xxxxxx Connection ID: yyyyyy Client

    Server
  34. Connection Migration QUIC Connection ID: xxxxxx Connection ID: yyyyyy Client

    Server
  35. Merits ɾConnection establishment latency ɾMultiplexing ɾConnection Migration

  36. Merits ɾConnection establishment latency ɾMultiplexing ɾConnection Migration ɾCongestion Control

  37. Merits ɾConnection establishment latency ɾMultiplexing ɾConnection Migration ɾCongestion Control ɾForward

    Error Correction
  38. Cronet

  39. https://developer.android.com/guide/topics/connectivity/cronet

  40. Quicstart

  41. dependencies { implementation "org.chromium.net:cronet-embedded:x.x.x" }

  42. val cronetEngine = CronetEngine.Builder(context) .enableHttp2(true) .enableQuic(true) .build() val request =

    cronetEngine.newUrlRequestBuilder(url, callback, executor) .setHttpMethod("GET") .addHeader("hoge", "huga") .build() request.start()
  43. val cronetEngine = CronetEngine.Builder(context) .enableHttp2(true) .enableQuic(true) .build() val request =

    cronetEngine.newUrlRequestBuilder(url, callback, executor) .setHttpMethod("GET") .addHeader("hoge", "huga") .build() request.start() .enableQuic(true)
  44. val cronetEngine = CronetEngine.Builder(context) .enableHttp2(true) .enableQuic(true) .build() val request =

    cronetEngine.newUrlRequestBuilder(url, callback, executor) .setHttpMethod("GET") .addHeader("hoge", "huga") .build() request.start()
  45. val cronetEngine = CronetEngine.Builder(context) .enableHttp2(true) .enableQuic(true) .build() val request =

    cronetEngine.newUrlRequestBuilder(url, callback, executor) .setHttpMethod("GET") .addHeader("hoge", "huga") .build() request.start() newUrlRequestBuilder(url, callback, executor)
  46. val cronetEngine = CronetEngine.Builder(context) .enableHttp2(true) .enableQuic(true) .build() val request =

    cronetEngine.newUrlRequestBuilder(url, callback, executor) .setHttpMethod("GET") .addHeader("hoge", "huga") .build() request.start() .setHttpMethod("GET") .addHeader("hoge", "huga")
  47. val cronetEngine = CronetEngine.Builder(context) .enableHttp2(true) .enableQuic(true) .build() val request =

    cronetEngine.newUrlRequestBuilder(url, callback, executor) .setHttpMethod("GET") .addHeader("hoge", "huga") .build() request.start()
  48. val cronetEngine = CronetEngine.Builder(context) .enableHttp2(true) .enableQuic(true) .build() val request =

    cronetEngine.newUrlRequestBuilder(url, callback, executor) .setHttpMethod("GET") .addHeader("hoge", "huga") .build() request.start()
  49. val cronetEngine = CronetEngine.Builder(context) .enableHttp2(true) .enableQuic(true) .build() val request =

    cronetEngine.newUrlRequestBuilder(url, callback, executor) .setHttpMethod("GET") .addHeader("hoge", "huga") .build() request.start() callback
  50. val callback = object : UrlRequest.Callback() { private val bytesReceived

    = ByteArrayOutputStream() private val receiveChannel = Channels.newChannel(bytesReceived) override fun onResponseStarted(request: UrlRequest, info: UrlResponseInfo) { // read response request.read(ByteBuffer.allocateDirect(32 * 1024)) } … }
  51. val callback = object : UrlRequest.Callback() { private val bytesReceived

    = ByteArrayOutputStream() private val receiveChannel = Channels.newChannel(bytesReceived) override fun onResponseStarted(request: UrlRequest, info: UrlResponseInfo) { // read response request.read(ByteBuffer.allocateDirect(32 * 1024)) } … } override fun onResponseStarted(request: UrlRequest, info: UrlResponseInfo) { // read response request.read(ByteBuffer.allocateDirect(32 * 1024)) }
  52. val callback = object : UrlRequest.Callback() { private val bytesReceived

    = ByteArrayOutputStream() private val receiveChannel = Channels.newChannel(bytesReceived) override fun onReadCompleted( request: UrlRequest, info: UrlResponseInfo, byteBuffer: ByteBuffer) { // write response byteBuffer.flip() receiveChannel.write(byteBuffer) // read response byteBuffer.clear() request.read(byteBuffer) } … }
  53. val callback = object : UrlRequest.Callback() { private val bytesReceived

    = ByteArrayOutputStream() private val receiveChannel = Channels.newChannel(bytesReceived) override fun onReadCompleted( request: UrlRequest, info: UrlResponseInfo, byteBuffer: ByteBuffer) { // write response byteBuffer.flip() receiveChannel.write(byteBuffer) // read response byteBuffer.clear() request.read(byteBuffer) } … } override fun onReadCompleted( request: UrlRequest, info: UrlResponseInfo, byteBuffer: ByteBuffer) { // write response byteBuffer.flip() receiveChannel.write(byteBuffer) // read response byteBuffer.clear() request.read(byteBuffer) }
  54. val callback = object : UrlRequest.Callback() { private val bytesReceived

    = ByteArrayOutputStream() private val receiveChannel = Channels.newChannel(bytesReceived) override fun onReadCompleted( request: UrlRequest, info: UrlResponseInfo, byteBuffer: ByteBuffer) { // write response byteBuffer.flip() receiveChannel.write(byteBuffer) // read response byteBuffer.clear() request.read(byteBuffer) } … } override fun onReadCompleted( byteBuffer: ByteBuffer
  55. val callback = object : UrlRequest.Callback() { private val bytesReceived

    = ByteArrayOutputStream() private val receiveChannel = Channels.newChannel(bytesReceived) override fun onReadCompleted( request: UrlRequest, info: UrlResponseInfo, byteBuffer: ByteBuffer) { // write response byteBuffer.flip() receiveChannel.write(byteBuffer) // read response byteBuffer.clear() request.read(byteBuffer) } … } private val receiveChannel = Channels.newChannel(bytesReceived) override fun onReadCompleted( request: UrlRequest, info: UrlResponseInfo, byteBuffer: ByteBuffer) { // write response byteBuffer.flip() receiveChannel.write(byteBuffer) }
  56. val callback = object : UrlRequest.Callback() { private val bytesReceived

    = ByteArrayOutputStream() private val receiveChannel = Channels.newChannel(bytesReceived) override fun onReadCompleted( request: UrlRequest, info: UrlResponseInfo, byteBuffer: ByteBuffer) { // write response byteBuffer.flip() receiveChannel.write(byteBuffer) // read response byteBuffer.clear() request.read(byteBuffer) } … } override fun onReadCompleted( request: UrlRequest, info: UrlResponseInfo, byteBuffer: ByteBuffer) { // read response byteBuffer.clear() request.read(byteBuffer) }
  57. val callback = object : UrlRequest.Callback() { private val bytesReceived

    = ByteArrayOutputStream() private val receiveChannel = Channels.newChannel(bytesReceived) override fun onReadCompleted( request: UrlRequest, info: UrlResponseInfo, byteBuffer: ByteBuffer) { // write response byteBuffer.flip() receiveChannel.write(byteBuffer) // read response byteBuffer.clear() request.read(byteBuffer) } … } override fun onReadCompleted( request: UrlRequest, info: UrlResponseInfo, byteBuffer: ByteBuffer) { // write response byteBuffer.flip() receiveChannel.write(byteBuffer) // read response byteBuffer.clear() request.read(byteBuffer) }
  58. val callback = object : UrlRequest.Callback() { private val bytesReceived

    = ByteArrayOutputStream() private val receiveChannel = Channels.newChannel(bytesReceived) override fun onSucceeded(request: UrlRequest, info: UrlResponseInfo) { // succeeded val result = bytesReceived.toByteArray() } … }
  59. val callback = object : UrlRequest.Callback() { private val bytesReceived

    = ByteArrayOutputStream() private val receiveChannel = Channels.newChannel(bytesReceived) override fun onSucceeded(request: UrlRequest, info: UrlResponseInfo) { // succeeded val result = bytesReceived.toByteArray() } … } override fun onSucceeded(request: UrlRequest, info: UrlResponseInfo) { // succeeded val result = bytesReceived.toByteArray() }
  60. val callback = object : UrlRequest.Callback() { private val bytesReceived

    = ByteArrayOutputStream() private val receiveChannel = Channels.newChannel(bytesReceived) override fun onFailed(request: UrlRequest, info: UrlResponseInfo, e: CronetException) { // failed Log.d("CRONET_SAMPLE", "failed: ${e.message}") } … } override fun onFailed(request: UrlRequest, info: UrlResponseInfo, e: CronetException) { // failed Log.d("CRONET_SAMPLE", "failed: ${e.message}") }
  61. QUIC for ExoPlayer

  62. https://github.com/google/ExoPlayer/tree/release-v2/extensions/cronet

  63. Client .m3u8 .mp4 .mp4 .ts OkHttp

  64. Client .m3u8 .mp4 .mp4 .ts Cronet

  65. OkHttpClient

  66. val userAgent = "takusemba" val okHttpClient = OkHttpClient() val transferListener

    = DefaultBandwidthMeter() val factory = OkHttpDataSourceFactory(okHttpClient, userAgent, transferListener) OkHttpClient
  67. val userAgent = "takusemba" val okHttpClient = OkHttpClient() val transferListener

    = DefaultBandwidthMeter() val factory = OkHttpDataSourceFactory(okHttpClient, userAgent, transferListener) OkHttpClient Cronet
  68. val userAgent = "takusemba" val okHttpClient = OkHttpClient() val transferListener

    = DefaultBandwidthMeter() val factory = OkHttpDataSourceFactory(okHttpClient, userAgent, transferListener) OkHttpClient val userAgent = "takusemba" val cronetEngine = CronetEngine.Builder(context).enableQuic(true).build() val wrapper = CronetEngineWrapper(cronetEngine) val executor = Executors.newSingleThreadExecutor() val predicate = Predicate { contentType: String -> true } val factory = CronetDataSourceFactory(wrapper, executor, predicate, userAgent) Cronet
  69. val userAgent = "takusemba" val okHttpClient = OkHttpClient() val transferListener

    = DefaultBandwidthMeter() val factory = OkHttpDataSourceFactory(okHttpClient, userAgent, transferListener) OkHttpClient val userAgent = "takusemba" val cronetEngine = CronetEngine.Builder(context).enableQuic(true).build() val wrapper = CronetEngineWrapper(cronetEngine) val executor = Executors.newSingleThreadExecutor() val predicate = Predicate { contentType: String -> true } val factory = CronetDataSourceFactory(wrapper, executor, predicate, userAgent) val wrapper = CronetEngineWrapper(cronetEngine) val executor = Executors.newSingleThreadExecutor() val predicate = Predicate { contentType: String -> true } Cronet
  70. val userAgent = "takusemba" val okHttpClient = OkHttpClient() val transferListener

    = DefaultBandwidthMeter() val factory = OkHttpDataSourceFactory(okHttpClient, userAgent, transferListener) OkHttpClient Cronet val userAgent = "takusemba" val cronetEngine = CronetEngine.Builder(context).enableQuic(true).build() val wrapper = CronetEngineWrapper(cronetEngine) val executor = Executors.newSingleThreadExecutor() val predicate = Predicate { contentType: String -> true } val factory = CronetDataSourceFactory(wrapper, executor, predicate, userAgent) val factory = CronetDataSourceFactory(wrapper, executor, predicate, userAgent)
  71. None
  72. https://github.com/TakuSemba/QuicPlayer Sample App

  73. https://github.com/takusemba https://twitter.com/takusemba Request in a QUIC way