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:34:46 +0900

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

>
>
>
> 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...
>
>
Sorry, the previous patch is incorrect. I re-attached new one.

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