Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[TW#19288] http2 client (using sh2lib/nghttp2) #1717

Closed
gerardbos opened this issue Mar 13, 2018 · 2 comments
Closed

[TW#19288] http2 client (using sh2lib/nghttp2) #1717

gerardbos opened this issue Mar 13, 2018 · 2 comments

Comments

@gerardbos
Copy link

I'm working on an HTTP2 client on the ESP32 platform. As a basis, I use the sh2lib component from the examples folder (examples/protocols/http2_request/).

This works fine when I use a golang HTTP(2) server:

D (7626) sh2lib: [frame-send] frame type SETTINGS
D (7626) sh2lib: [frame-send] frame type HEADERS
D (7626) sh2lib: [frame-send] C ----------------------------> S (HEADERS)
D (7626) sh2lib: [frame-send] headers nv-len = 3
D (7636) sh2lib: [frame-send] :method : GET
D (7636) sh2lib: [frame-send] :scheme : https
D (7646) sh2lib: [frame-send] :path : /kakulightbulb/desk
D (7656) sh2lib: [frame-recv][sid: 0] frame type SETTINGS
D (7656) sh2lib: [frame-recv][sid: 0] frame type other
D (7676) sh2lib: [frame-send] frame type SETTINGS
D (7696) sh2lib: [frame-recv][sid: 0] frame type SETTINGS
D (7716) sh2lib: [hdr-recv][sid:1] :status : 200
D (7716) sh2lib: [hdr-recv][sid:1] content-type : application/json; charset=UTF-8
D (7716) sh2lib: [hdr-recv][sid:1] content-length : 174
D (7716) sh2lib: [hdr-recv][sid:1] date : Tue, 13 Mar 2018 14:51:48 GMT
D (7726) sh2lib: [frame-recv][sid: 1] frame type HEADERS
D (7736) sh2lib: [data-chunk][sid:1]
D (7736) sh2lib: [data-chunk] C <---------------------------- S (DATA chunk)174 bytes

When I do the same with data from an Apache server that supports http2:

D (6296) sh2lib: [frame-send] frame type SETTINGS
D (6296) sh2lib: [frame-send] frame type HEADERS
D (6296) sh2lib: [frame-send] C ----------------------------> S (HEADERS)
D (6296) sh2lib: [frame-send] headers nv-len = 3
D (6306) sh2lib: [frame-send] :method : GET
D (6306) sh2lib: [frame-send] :scheme : https
D (6316) sh2lib: [frame-send] :path : /test.json
D (6316) sh2lib: [frame-recv][sid: 0] frame type SETTINGS
D (6326) sh2lib: [frame-recv][sid: 0] frame type other
D (6346) sh2lib: [frame-send] frame type SETTINGS
D (6426) sh2lib: [frame-recv][sid: 0] frame type SETTINGS
D (6426) sh2lib: [frame-recv][sid: 1] frame type RST_STREAM
D (6426) sh2lib: [stream-close][sid 1]

Which results in no data transferred to the ESP32. When I use other HTTP2 clients, I do not see the problem (for example using curl, which also uses nghttp2 as a HTTP2 library).

@FayeY FayeY changed the title http2 client (using sh2lib/nghttp2) [TW#19288] http2 client (using sh2lib/nghttp2) Mar 19, 2018
@kedars
Copy link
Member

kedars commented Mar 20, 2018

It seems the server expects the :authority field in the headers. Could you try by quickly adding the following entry in the nva[] array in the function sh2lib_do_get():

 SH2LIB_MAKE_NV(":authority", "your-hostname"),

I will raise an MR in IDF with the fix

@gerardbos
Copy link
Author

That fixes the issue! thanks!

@igrr igrr closed this as completed in 86eaf5d Mar 26, 2018
0xFEEDC0DE64 pushed a commit to 0xFEEDC0DE64/esp-idf that referenced this issue May 5, 2021
* ReSTART fix, Sequencing fix

pr espressif#1665 introduce a problem with ReSTART, when solving this problem I found an interaction between the TxFifo refill, RxFifo empty and CMD[] fill.  during certain sequences a dataqueue command would be skipped, this skipping resulted in a mismatch between the contents of the TxFifo and the i2c command sequence.  The problem manifested as an ACK error. 
In addition to this required bug fix I propose:
* `Wire.begin()` be changed from a `void` to a `bool` this will allow the reset functionality of `Wire.begin()` to be reported.  Currently `Wire.begin()` attempts to reset the i2c Peripheral, but cannot report success/failure.
* `Wire.busy()` be added. this `bool` function returns the hardware status of the bus. This status can be use in multi-master environments for application level interleaving of commands, also in single master environment, it can be used to detect a 'hung' bus.  With the functional change to `Wire.begin()` this allows app level recover of a hung bus.
* `Wire.lastError()` value updated for all errors, previously when interleaving `Wire.endTransmission(false)` and `Wire.readTransmission(false)`, the 128 byte `Wire.write()` buffer was exhausted without generating and error(very exotic). I discovered this error when I created a sequence of directed reads to a EEPROM. Each directed read used 2 bytes of the 128 byte `write()` buffer, so after 64 consecutive ReSTART writes with ReSTART reads, `Wire()`  had no room to record the directed address bytes.  It generated just a NAK check without setting the EEPROMs internal register address.  The succeeding ReSTART read succeeded at incorrect address.
* Changes to the HAL layer:
** added `i2cGetStatus()` which returns the i2c peripheral status word, used to detect bus_busy currently
** added `i2cDebug()` programmatic control of debug buffer output
** changed `i2cAddQueue()` to allow data_only queue element this will allow a i2c transaction to use multiple data pointers.
** removed direct access to DumpInts(), DumpI2c() from app, use i2cDebug() to set trigger points 
 
*

* Update esp32-hal-i2c.c

* Update Wire.cpp

* ReSTART, Sequencing

pr espressif#1665 introduce a problem with ReSTART, when solving this problem I found an interaction between the TxFifo refill, RxFifo empty and CMD[] fill.  during certain sequences a dataqueue command would be skipped, this skipping resulted in a mismatch between the contents of the TxFifo and the i2c command sequence.  The problem manifested as an ACK error. 
In addition to this required bug fix I propose:
* `Wire.begin()` be changed from a `void` to a `bool` this will allow the reset functionality of `Wire.begin()` to be reported.  Currently `Wire.begin()` attempts to reset the i2c Peripheral, but cannot report success/failure.
* `Wire.busy()` be added. this `bool` function returns the hardware status of the bus. This status can be use in multi-master environments for application level interleaving of commands, also in single master environment, it can be used to detect a 'hung' bus.  With the functional change to `Wire.begin()` this allows app level recover of a hung bus.
* `Wire.lastError()` value updated for all errors, previously when interleaving `Wire.endTransmission(false)` and `Wire.readTransmission(false)`, the 128 byte `Wire.write()` buffer was exhausted without generating and error(very exotic). I discovered this error when I created a sequence of directed reads to a EEPROM. Each directed read used 2 bytes of the 128 byte `write()` buffer, so after 64 consecutive ReSTART writes with ReSTART reads, `Wire()`  had no room to record the directed address bytes.  It generated just a NAK check without setting the EEPROMs internal register address.  The succeeding ReSTART read succeeded at incorrect address.
* Changes to the HAL layer:
** added `i2cGetStatus()` which returns the i2c peripheral status word, used to detect bus_busy currently
** added `i2cDebug()` programmatic control of debug buffer output
** changed `i2cAddQueue()` to allow data_only queue element this will allow a i2c transaction to use multiple data pointers.
** removed direct access to DumpInts(), DumpI2c() from app, use i2cDebug() to set trigger points 
 
*

* Forgot DebugFlags Return

@andriyadi found this, total brain fade on my part.
0xFEEDC0DE64 pushed a commit to 0xFEEDC0DE64/esp-idf that referenced this issue May 5, 2021
espressif#1869 exposed a resource exhaustion issue. The current HAL layer for I2C support is designed to use a shared interrupt, But, during debugging to solve the interrupt overloading condition identified in espressif#1588, and the generation of pr espressif#1717, the interrupt allocation parameters were changed.  This change was unnecessary, the code will work successfully with shared interrupts.  So, there is no need to assign a private interrupt for each I2C peripheral.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants