Example #1
0
static
int prepare_h2_session(session *sess)
{
    int ret;
    nghttp2_option *option;
    nghttp2_session_callbacks *callbacks;

    if(nghttp2_option_new(&option)==0 &&
       nghttp2_session_callbacks_new(&callbacks)==0)
    {
        h2session_setup_h2(&sess->S, callbacks, option);

        if(nghttp2_session_server_new2(&sess->S.h2sess, callbacks, sess, option)) {
            fprintf(stderr, "Failed to create server session\n");
            ret = 1;

        } else
            ret = 0;

    } else {
        fprintf(stderr, "Failed to alloc options/callbacks\n");
        ret = 1;
    }
    nghttp2_session_callbacks_del(callbacks);
    nghttp2_option_del(option);
    return ret;
}
Example #2
0
static void initialize_nghttp2_session(http2_session_data *session_data) {
  nghttp2_session_callbacks *callbacks;

  nghttp2_session_callbacks_new(&callbacks);

  nghttp2_session_callbacks_set_send_callback(callbacks, send_callback);

  nghttp2_session_callbacks_set_on_frame_recv_callback(callbacks,
                                                       on_frame_recv_callback);

  nghttp2_session_callbacks_set_on_data_chunk_recv_callback(
      callbacks, on_data_chunk_recv_callback);

  nghttp2_session_callbacks_set_on_stream_close_callback(
      callbacks, on_stream_close_callback);

  nghttp2_session_callbacks_set_on_header_callback(callbacks,
                                                   on_header_callback);

  nghttp2_session_callbacks_set_on_begin_headers_callback(
      callbacks, on_begin_headers_callback);

  nghttp2_session_client_new(&session_data->session, callbacks, session_data);

  nghttp2_session_callbacks_del(callbacks);
}
Example #3
0
/*
 * Initialize nghttp2 for a Curl connection
 */
CURLcode Curl_http2_init(struct connectdata *conn)
{
  if(!conn->proto.httpc.h2) {
    int rc;
    nghttp2_session_callbacks *callbacks;

    conn->proto.httpc.inbuf = malloc(H2_BUFSIZE);
    if(conn->proto.httpc.inbuf == NULL)
      return CURLE_OUT_OF_MEMORY;

    rc = nghttp2_session_callbacks_new(&callbacks);

    if(rc) {
      failf(conn->data, "Couldn't initialize nghttp2 callbacks!");
      return CURLE_OUT_OF_MEMORY; /* most likely at least */
    }

    /* nghttp2_send_callback */
    nghttp2_session_callbacks_set_send_callback(callbacks, send_callback);
    /* nghttp2_on_frame_recv_callback */
    nghttp2_session_callbacks_set_on_frame_recv_callback
      (callbacks, on_frame_recv);
    /* nghttp2_on_invalid_frame_recv_callback */
    nghttp2_session_callbacks_set_on_invalid_frame_recv_callback
      (callbacks, on_invalid_frame_recv);
    /* nghttp2_on_data_chunk_recv_callback */
    nghttp2_session_callbacks_set_on_data_chunk_recv_callback
      (callbacks, on_data_chunk_recv);
    /* nghttp2_before_frame_send_callback */
    nghttp2_session_callbacks_set_before_frame_send_callback
      (callbacks, before_frame_send);
    /* nghttp2_on_frame_send_callback */
    nghttp2_session_callbacks_set_on_frame_send_callback
      (callbacks, on_frame_send);
    /* nghttp2_on_frame_not_send_callback */
    nghttp2_session_callbacks_set_on_frame_not_send_callback
      (callbacks, on_frame_not_send);
    /* nghttp2_on_stream_close_callback */
    nghttp2_session_callbacks_set_on_stream_close_callback
      (callbacks, on_stream_close);
    /* nghttp2_on_begin_headers_callback */
    nghttp2_session_callbacks_set_on_begin_headers_callback
      (callbacks, on_begin_headers);
    /* nghttp2_on_header_callback */
    nghttp2_session_callbacks_set_on_header_callback(callbacks, on_header);

    /* The nghttp2 session is not yet setup, do it */
    rc = nghttp2_session_client_new(&conn->proto.httpc.h2,
                                    callbacks, conn);

    nghttp2_session_callbacks_del(callbacks);

    if(rc) {
      failf(conn->data, "Couldn't initialize nghttp2!");
      return CURLE_OUT_OF_MEMORY; /* most likely at least */
    }
  }
  return CURLE_OK;
}
Example #4
0
static void run_nghttp2_session_send_server(void) {
  nghttp2_session *session;
  nghttp2_session_callbacks *callbacks;
  int rv;
  const uint8_t *txdata;
  ssize_t txdatalen;
  const uint8_t origin[] = "nghttp2.org";
  const uint8_t altsvc_field_value[] = "h2=\":443\"";

  rv = nghttp2_session_callbacks_new(&callbacks);
  if (rv != 0) {
    return;
  }

  rv = nghttp2_session_server_new3(&session, callbacks, NULL, NULL,
                                   nghttp2_mem_fm());

  nghttp2_session_callbacks_del(callbacks);

  if (rv != 0) {
    return;
  }

  rv = nghttp2_submit_altsvc(session, NGHTTP2_FLAG_NONE, 0, origin,
                             sizeof(origin) - 1, altsvc_field_value,
                             sizeof(altsvc_field_value) - 1);
  if (rv != 0) {
    goto fail;
  }

  txdatalen = nghttp2_session_mem_send(session, &txdata);

  if (txdatalen < 0) {
    goto fail;
  }

fail:
  nghttp2_session_del(session);
}
Example #5
0
static h2_session *h2_session_create_int(conn_rec *c,
                                         request_rec *r,
                                         h2_config *config, 
                                         h2_workers *workers)
{
    nghttp2_session_callbacks *callbacks = NULL;
    nghttp2_option *options = NULL;

    apr_pool_t *pool = NULL;
    apr_status_t status = apr_pool_create(&pool, r? r->pool : c->pool);
    h2_session *session;
    if (status != APR_SUCCESS) {
        return NULL;
    }

    session = apr_pcalloc(pool, sizeof(h2_session));
    if (session) {
        int rv;
        session->id = c->id;
        session->c = c;
        session->r = r;
        
        session->max_stream_count = h2_config_geti(config, H2_CONF_MAX_STREAMS);
        session->max_stream_mem = h2_config_geti(config, H2_CONF_STREAM_MAX_MEM);

        session->pool = pool;
        
        status = apr_thread_cond_create(&session->iowait, session->pool);
        if (status != APR_SUCCESS) {
            return NULL;
        }
        
        session->streams = h2_stream_set_create(session->pool);
        
        session->workers = workers;
        session->mplx = h2_mplx_create(c, session->pool, workers);
        
        h2_conn_io_init(&session->io, c);
        session->bbtmp = apr_brigade_create(session->pool, c->bucket_alloc);
        
        status = init_callbacks(c, &callbacks);
        if (status != APR_SUCCESS) {
            ap_log_cerror(APLOG_MARK, APLOG_ERR, status, c, APLOGNO(02927) 
                          "nghttp2: error in init_callbacks");
            h2_session_destroy(session);
            return NULL;
        }
        
        rv = nghttp2_option_new(&options);
        if (rv != 0) {
            ap_log_cerror(APLOG_MARK, APLOG_ERR, APR_EGENERAL, c,
                          APLOGNO(02928) "nghttp2_option_new: %s", 
                          nghttp2_strerror(rv));
            h2_session_destroy(session);
            return NULL;
        }

        nghttp2_option_set_peer_max_concurrent_streams(options, 
                                                       (uint32_t)session->max_stream_count);

        /* We need to handle window updates ourself, otherwise we
         * get flooded by nghttp2. */
        nghttp2_option_set_no_auto_window_update(options, 1);
        
        rv = nghttp2_session_server_new2(&session->ngh2, callbacks,
                                         session, options);
        nghttp2_session_callbacks_del(callbacks);
        nghttp2_option_del(options);
        
        if (rv != 0) {
            ap_log_cerror(APLOG_MARK, APLOG_ERR, APR_EGENERAL, c,
                          APLOGNO(02929) "nghttp2_session_server_new: %s",
                          nghttp2_strerror(rv));
            h2_session_destroy(session);
            return NULL;
        }
        
    }
    return session;
}
Example #6
0
    int nghttp2client_connect(httpclient *pclient, char *url, int port, http2_ssl_custom_conf_t *ssl_config, const struct URI *uri)
    {
        struct Connection connection;
        nghttp2_session_callbacks *callbacks;
        int rv;
        int ret = 0;
        struct Request req;
        request_init(&req, uri);

        if (0 == (ret = nghttp2s_client_conn(pclient, url, port, ssl_config))) {
            pclient->remote_port = HTTPS_PORT;
            nghttp2_socket.fd = pclient->fd.fd;
        } else {
            printf("https_client_conn failed %d\r\n", ret);
            /* Resource cleanup */
            mbedtls_ssl_close_notify( &(pclient->ssl) );
            mbedtls_net_free( &pclient->fd );
            mbedtls_x509_crt_free( &(ssl_config->verify_source.cacertl) );
            mbedtls_ssl_free( &(pclient->ssl) );
            mbedtls_ssl_config_free( &(ssl_config->conf) );
            mbedtls_ctr_drbg_free(&ctr_drbg);
            mbedtls_entropy_free(&entropy);
            request_free(&req);
            return ret;

        }

        //set_tcp_nodelay(nghttp2_socket.fd);

        connection.ssl = &(pclient->ssl);
        rv = nghttp2_session_callbacks_new(&callbacks);

        if (rv != 0) {
            printf("nghttp2_session_callbacks_new1 %d", rv);
        }

        setup_nghttp2_callbacks(callbacks);
        rv = nghttp2_session_client_new(&connection.session, callbacks, &connection);


        nghttp2_session_callbacks_del(callbacks);

        if (rv != 0) {
            printf("nghttp2_session_client_new2 %d", rv);
        }

        nghttp2_submit_settings(connection.session, NGHTTP2_FLAG_NONE, NULL, 0);

        /* Submit the HTTP request to the outbound queue. */

        submit_request(&connection, &req);

        /* Event loop */
        while (1) {
            int read_flag = 0;
            int write_flag = 0;

            write_flag = nghttp2_session_want_write(connection.session);
            if (write_flag) {
                int rv = nghttp2_session_send(connection.session);
                printf("nghttp2_session_send %d\r\n", rv);
                if (rv < 0) {
                    write_flag = 0;
                    //break;
                }
            }

            read_flag = nghttp2_session_want_read(connection.session);
            if (read_flag) {
                int rv = nghttp2_session_recv(connection.session);
                printf("nghttp2_session_recv %d\r\n", rv);
                if (rv < 0) {
                    read_flag = 0;
                    //break;
                }
            }

            printf("write_flag = %d, read_flag = %d\r\n", write_flag, read_flag);

            if ((read_flag == 0) && (write_flag == 0)) {
                printf("No active stream!\r\n");
                break;
            }
        }

        /* Resource cleanup */

        nghttp2_session_del(connection.session);

        mbedtls_ssl_close_notify( &(pclient->ssl) );
        mbedtls_net_free( &pclient->fd );
        mbedtls_x509_crt_free( &(ssl_config->verify_source.cacertl) );
        mbedtls_ssl_free( &(pclient->ssl) );
        mbedtls_ssl_config_free( &(ssl_config->conf) );
        mbedtls_ctr_drbg_free(&ctr_drbg);
        mbedtls_entropy_free(&entropy);

        request_free(&req);
        return 0;

    }
Example #7
0
static h2_session *h2_session_create_int(conn_rec *c,
                                         request_rec *r,
                                         h2_config *config)
{
    nghttp2_session_callbacks *callbacks = NULL;
    nghttp2_option *options = NULL;
    
    apr_allocator_t *allocator = NULL;
    apr_status_t status = apr_allocator_create(&allocator);
    if (status != APR_SUCCESS) {
        return NULL;
    }
    
    apr_pool_t *pool = NULL;
    status = apr_pool_create_ex(&pool, c->pool, NULL, allocator);
    if (status != APR_SUCCESS) {
        return NULL;
    }

    h2_session *session = apr_pcalloc(pool, sizeof(h2_session));
    if (session) {
        session->id = c->id;
        
        session->allocator = allocator;
        session->pool = pool;
        status = apr_thread_mutex_create(&session->alock, 
                                         APR_THREAD_MUTEX_DEFAULT,
                                         session->pool);
        if (status != APR_SUCCESS) {
            return NULL;
        }
        apr_allocator_mutex_set(session->allocator, session->alock);
        
        status = apr_thread_cond_create(&session->iowait, session->pool);
        if (status != APR_SUCCESS) {
            return NULL;
        }
        
        session->c = c;
        session->r = r;
        session->ngh2 = NULL;
        
        session->streams = h2_stream_set_create(session->pool);
        session->zombies = h2_stream_set_create(session->pool);
        
        session->mplx = h2_mplx_create(c, session->pool);
        
        h2_conn_io_init(&session->io, c, 0);
        
        apr_status_t status = init_callbacks(c, &callbacks);
        if (status != APR_SUCCESS) {
            ap_log_cerror(APLOG_MARK, APLOG_ERR, status, c,
                          "nghttp2: error in init_callbacks");
            h2_session_destroy(session);
            return NULL;
        }
        
        int rv = nghttp2_option_new(&options);
        if (rv != 0) {
            ap_log_cerror(APLOG_MARK, APLOG_ERR, APR_EGENERAL, c,
                          "nghttp2_option_new: %s", nghttp2_strerror(rv));
            h2_session_destroy(session);
            return NULL;
        }

        /* Nowadays, we handle the preface ourselves. We had problems
         * with nghttp2 internal state machine when traffic action occured
         * before the preface was read. 
         */
        nghttp2_option_set_recv_client_preface(options, 1);
        /* Set a value, to be observed before we receive any SETTINGS
         * from the client. */
        nghttp2_option_set_peer_max_concurrent_streams(options, 100);

        /* We need to handle window updates ourself, otherwise we
         * get flooded by nghttp2. */
        nghttp2_option_set_no_auto_window_update(options, 1);
        
        rv = nghttp2_session_server_new2(&session->ngh2, callbacks,
                                         session, options);
        nghttp2_session_callbacks_del(callbacks);
        nghttp2_option_del(options);
        
        if (rv != 0) {
            ap_log_cerror(APLOG_MARK, APLOG_ERR, APR_EGENERAL, c,
                          "nghttp2_session_server_new: %s",
                          nghttp2_strerror(rv));
            h2_session_destroy(session);
            return NULL;
        }
        
    }
    return session;
}
Example #8
0
/*
 * Fetches the resource denoted by |uri|.
 */
static void fetch_uri(const struct URI *uri) {
  nghttp2_session_callbacks *callbacks;
  int fd;
  SSL_CTX *ssl_ctx;
  SSL *ssl;
  struct Request req;
  struct Connection connection;
  int rv;
  nfds_t npollfds = 1;
  struct pollfd pollfds[1];

  request_init(&req, uri);

  /* Establish connection and setup SSL */
  fd = connect_to(req.host, req.port);
  if (fd == -1) {
    die("Could not open file descriptor");
  }
  ssl_ctx = SSL_CTX_new(SSLv23_client_method());
  if (ssl_ctx == NULL) {
    dief("SSL_CTX_new", ERR_error_string(ERR_get_error(), NULL));
  }
  init_ssl_ctx(ssl_ctx);
  ssl = SSL_new(ssl_ctx);
  if (ssl == NULL) {
    dief("SSL_new", ERR_error_string(ERR_get_error(), NULL));
  }
  /* To simplify the program, we perform SSL/TLS handshake in blocking
     I/O. */
  ssl_handshake(ssl, fd);

  connection.ssl = ssl;
  connection.want_io = IO_NONE;

  /* Here make file descriptor non-block */
  make_non_block(fd);
  set_tcp_nodelay(fd);

  printf("[INFO] SSL/TLS handshake completed\n");

  rv = nghttp2_session_callbacks_new(&callbacks);

  if (rv != 0) {
    diec("nghttp2_session_callbacks_new", rv);
  }

  setup_nghttp2_callbacks(callbacks);

  rv = nghttp2_session_client_new(&connection.session, callbacks, &connection);

  nghttp2_session_callbacks_del(callbacks);

  if (rv != 0) {
    diec("nghttp2_session_client_new", rv);
  }

  rv = nghttp2_submit_settings(connection.session, NGHTTP2_FLAG_NONE, NULL, 0);

  if (rv != 0) {
    diec("nghttp2_submit_settings", rv);
  }

  /* Submit the HTTP request to the outbound queue. */
  submit_request(&connection, &req);

  pollfds[0].fd = fd;
  ctl_poll(pollfds, &connection);

  /* Event loop */
  while (nghttp2_session_want_read(connection.session) ||
         nghttp2_session_want_write(connection.session)) {
    int nfds = poll(pollfds, npollfds, -1);
    if (nfds == -1) {
      dief("poll", strerror(errno));
    }
    if (pollfds[0].revents & (POLLIN | POLLOUT)) {
      exec_io(&connection);
    }
    if ((pollfds[0].revents & POLLHUP) || (pollfds[0].revents & POLLERR)) {
      die("Connection error");
    }
    ctl_poll(pollfds, &connection);
  }

  /* Resource cleanup */
  nghttp2_session_del(connection.session);
  SSL_shutdown(ssl);
  SSL_free(ssl);
  SSL_CTX_free(ssl_ctx);
  shutdown(fd, SHUT_WR);
  close(fd);
  request_free(&req);
}