cURL / Mailing Lists / curl-library / Single Mail

curl-library

Re: HTTP2 and SPDY

From: Tatsuhiro Tsujikawa <tatsuhiro.t_at_gmail.com>
Date: Thu, 30 Jan 2014 23:30:43 +0900

On Thu, Jan 30, 2014 at 9:24 PM, Tatsuhiro Tsujikawa
<tatsuhiro.t_at_gmail.com>wrote:

>
>
>
> On Thu, Jan 30, 2014 at 8:50 AM, Daniel Stenberg <daniel_at_haxx.se> wrote:
>
>> On Wed, 29 Jan 2014, Tatsuhiro Tsujikawa wrote:
>>
>> Feel free to raise the issue at nghttp2 project page.
>>>
>>
>> Good to see you here Tatsuhiro, thanks for helping out!
>>
>> I added more code to libcurl to actually slowly start to receive http2
>> frames but I end up with nghttp2_session_recv() failing for the moment. I
>> filed https://github.com/tatsuhiro-t/nghttp2/issues/24 as I would really
>> like some help from the lib to point out what the problem is!
>>
>> Additionally, I get one invalid frame it says. I will clearly need to add
>> more debugging ability to libcurl for this so that --trace etc works for
>> the http2 data as well!
>>
>> My test output with code from git shows this:
>>
>> <= Recv header, 21 bytes (0x15)
>> 0000: 43 6f 6e 6e 65 63 74 69 6f 6e 3a 20 55 70 67 72 Connection: Upgr
>> 0010: 61 64 65 0d 0a ade..
>> <= Recv header, 28 bytes (0x1c)
>> 0000: 55 70 67 72 61 64 65 3a 20 48 54 54 50 2d 64 72 Upgrade: HTTP-dr
>> 0010: 61 66 74 2d 30 39 2f 32 2e 30 0d 0a aft-09/2.0..
>> == Info: Received 101
>> == Info: We have switched to HTTP2
>> == Info: on_invalid_frame_recv() was called, error_code = 1
>> == Info: Got ':status:200'
>> == Info: Got 'accept-ranges:bytes'
>> == Info: Got 'age:0'
>> == Info: Got 'content-length:10478'
>> == Info: Got 'content-type:text/html'
>> == Info: Got 'date:Wed, 29 Jan 2014 23:47:24 GMT'
>> == Info: Got 'etag:"52daab5b-28ee"'
>> == Info: Got 'last-modified:Sat, 18 Jan 2014 16:27:07 GMT'
>> == Info: Got 'server:nginx/1.4.1 (Ubuntu)'
>> == Info: Got 'x-varnish:2029056218'
>> == Info: Got 'via:1.1 varnish, 1.1 nghttpx'
>> == Info: on_frame_recv() was called with header 1
>> == Info: Failed receiving HTTP2 data
>> == Info: nghttp2_session_recv() returned -902
>>
>> == Info: STATE: PERFORM => DONE handle 0x14e4498; line 1582 (connection
>> #0)
>> == Info: Connection #0 to host 106.186.112.116 left intact
>>
>>
> This mixed result is caused by the bug in nghttp2 and the missing
> nghttp2_session_upgrade() call
> in libcurl code.
> The invalid_frame_recv callback should not be called in this situation,
> but due to the bug,
> the client code recognizes the response from the server as "request" and
> processed as such, but
> because stream ID is odd, the library detects that it is not valid and
> invoked invalid_frame_recv callback. Anyway, the fix is easy so I'll do
> that soon after this email.
>
> For the libcurl part, there is more thing for client to do after 101
> response.
> In HTTP2 spec, client has to send 24 bytes magic string and SETTINGS frame
> as client connection header.
> This 24 bytes byte string is defined as NGHTTP2_CLIENT_CONNECTION_HEADER
> in nghttp2.h.
> Client should first push this off to the socket. Usually,
> nghttp2_submit_settings() is used to send
> SETTINGS frame. But the HTTP upgrade is treated specially and has the
> dedicated function:
> nghttp2_session_upgrade(). Client should call this function with the same
> SETTINGS payload sent
> in HTTP2-Settings header field (but the form before base64-encoded). This
> function opens stream ID=1, which is considered to be sent as the first
> HTTP/1 request and queues SETTINGS frame to transmission queue in
> nghttp2_session.
>
> I think the -902 error, which is NGHTTP2_ERR_CALLBACK_FAILURE, is
> triggered because callback function
> return it when it gets EOF from the remote peer.
>
> As discussed in https://github.com/tatsuhiro-t/nghttp2/issues/13, I've
> implemented the ability to stop processing
> bytes when application requested so. To use this feature, application must
> use nghttp2_session_mem_recv() instead of nghttp2_session_recv().
> nghttp2_session_mem_recv() does not use recv_callback function and takes
> the buffer pointer and its byte length directly. So, current libcurl code
> can be a bit simplified with 1 less callback.
>
>
Attached patch will at least receive the server response without errors.
In the patch, I replaced nghttp2_session_recv() use with
nghttp2_session_mem_recv().
nghttp2_session_upgrade() is also called with sent payload stuff.
But I'm not sure what the return value should I return on error or success
in http2_recv, so please consider this patch as experimental.

I also could not figure out how to send NGHTTP2_CLIENT_CONNECTION_HEADER
and when nghttp2_send is called. Hacking continues...

Best regards,
Tatsuhiro Tsujikawa

-------------------------------------------------------------------
List admin: http://cool.haxx.se/list/listinfo/curl-library
Etiquette: http://curl.haxx.se/mail/etiquette.html

Received on 2014-01-30