Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Conversation

@deweerdt
Copy link
Member

This introduces a new option: http2-origin-frame. It can be either a
scalar or a sequence. When this option is sent, H2O sends an ORIGIN
frame as described here:
https://github.com/httpwg/http-extensions/blob/master/draft-ietf-httpbis-origin-frame.md

The PR is mostly intended to serve as basis for the discussion, rather than intended for merging. It feels like the contents of ORIGIN frame we send should actually depend on the SNI as follows:

  • Config defines an SNI to host names mapping
  • SNI callback adds the SNI to h2o_conn_t
  • expect_preface looks up the SNI in h2o_conn_t and using the config mapping, builds the ORIGIN frame

Thoughts?

This introduces a new option: `http2-origin-frame`. It can be either a
scalar or a sequence. When this option is sent, H2O sends an ORIGIN
frame as described here:
https://github.com/httpwg/http-extensions/blob/master/draft-ietf-httpbis-origin-frame.md
@kazuho
Copy link
Member

kazuho commented Feb 13, 2017

Thank you for opening the PR and starting the discussion.

It seems like that we need to consider how we should design the configuration directives for the frame. I do not have a concrete idea on how the design should be, but trying to find a good way to handle a configuration like below might be a good starting point.

hosts:
    a.example.com:
        ssl:
            port: 443
            certificate-file: wildcard.example.com.crt
    b.example.com:
        ssl:
            port: 443
            certificate-file: wildcard.example.com.crt
    c.example.org:
        ssl:
            port: 443
            certificate-file: c.example.org.crt
    "d.example.net:8443":
        ssl:
            port: 8443
            certificate-file: d.example.net.crt
            ...

For this example, an ORIGIN frame should not be sent when accepting a connection on port 443 with value of the SNI extension set to c.example.org. For connections with other SNIs being accepted on port 443, an ORIGIN frame may be sent (depending on the configuration variables) with its value set to a.example.com and b.example.com. For connections arriving on port 8443, we do not have a need to send an ORIGIN frame.

I am not sure what the correct answer would be, but looking at this example it seems that having a configuration directive for controlling ORIGIN frames next to certificate-file (or maybe next to ssl) seems like a good solution.

Move the config logic under the ssl listener config
@deweerdt
Copy link
Member Author

deweerdt commented Feb 14, 2017

@kazuho thank you for your suggestion. 1194084 moves the config item under ssl, as such:

hosts:
    a.example.com:
        ssl:
            port: 443
            certificate-file: wildcard.example.com.crt
            http2-origin-frame: "https://a.example.com"
    b.example.com:
        ssl:
            port: 443
            certificate-file: wildcard.example.com.crt
            http2-origin-frame: [ "https://img.b.example.com", "https://b.example.com" ]
    c.example.org:
        ssl:
            port: 443
            certificate-file: c.example.org.crt
    "d.example.net:8443":
        ssl:
            port: 8443
            certificate-file: d.example.net.crt
            ...

I think a remaining question is whether we want to handle the "*" case in the config as well, something like:

hosts:
    *:
        ssl:
            port: 443
            certificate-file: wildcard.example.com.crt
            http2-origin-frame:
               a.example.com: "https://a.example.com"

But that might be overkill, what do you think?

Copy link
Member

@kazuho kazuho left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for the updates. I think we are on the right track. I've left some (relatively minor) comments. Please let me know what you think.

}

void h2o_http2_accept(h2o_accept_ctx_t *ctx, h2o_socket_t *sock, struct timeval connected_at)
void h2o_http2_accept(h2o_accept_ctx_t *ctx, h2o_socket_t *sock, h2o_iovec_t *http2_origin_frame, struct timeval connected_at)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need to pass http2_origin_frame as a separate argument? To me, using the value in ctx seems fine.

include/h2o.h Outdated
struct {
SSL_CTX *ssl_ctx;
h2o_iovec_t *http2_origin_frame;
} ssl;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's not move ssl_ctx into a new field, but have both ssl_ctx and http2_origin_frame direct members of h2o_accept_ctx_t.

The reasons are: 1. the change would be smaller 2. in terms of protocol, origin frames can be sent even when SSL is not used.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done. Regarding 2. my understanding of the RFC is that SSL has to be used?

src/main.c Outdated
h2o_strtolower(elems[i*2 + 1].base, elems[i*2 + 1].len);
}
http2_origin_frame = h2o_mem_alloc(sizeof(*http2_origin_frame));
*http2_origin_frame = h2o_concat_list(NULL, elems, value->data.sequence.size * 2);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about creating a function that takes a list of strings to build the frame, instead of having duplicate code for YOML_TYPE_SCALAR and YOML_TYPE_SEQUENCE?

@deweerdt
Copy link
Member Author

@kazuho I believe d6e1850 addresses all your comments so far.

src/main.c Outdated
ssl_config->hostnames.entries[ssl_config->hostnames.size++] = h2o_iovec_init(host.base, host_end - host.base);
}

static h2o_iovec_t *build_http2_origin_frame(const h2o_iovec_t *origins, size_t nr_origins)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it make sense to change the signature of this function to: (h2o_configurator_command_t *cmd, yoml_t *origins, size_t nr_origins)?

If the argument to the directive was a scalar, the caller can just call build_http2_origin_frame(cmd, value, 1). If the argument to the directive was a sequence, the caller should call build_http2_origin_frame(cmd, value.data.sequence.elements, value.data.sequence.size).

@deweerdt
Copy link
Member Author

42c8fdd has a better interface for build_http2_origin_frame. Thank you for the suggestion, @kazuho .

@kazuho
Copy link
Member

kazuho commented Feb 22, 2017

@deweerdt Thank you very much. The code looks perfect!

Let's keep this parked and merge it once we see the draft go forward and/or when we see clients start recognizing the frame.

@deweerdt
Copy link
Member Author

3b749c0 updates the branch to current master and updates the frame type to the latest draft (-04)

@kazuho kazuho added this to the v2.3 milestone Jan 15, 2018
@deweerdt
Copy link
Member Author

deweerdt commented Jun 9, 2018

@kazuho I've refreshed the PR to the latest master, as well as added test coverage.

Since this is now RFC 8336 and there is Firefox support, i believe the PR should be considered for merging.

@kazuho kazuho merged commit 6d082a5 into h2o:master Jun 12, 2018
@kazuho
Copy link
Member

kazuho commented Jun 12, 2018

Thank you for working on this issue and keeping it alive.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants