message:
sip: SIP/TLS Server Name Indication
A change in the API of ctrans and transp is necessary. At the
calls between request and ctrans, the hostname information of the
next hop is lost. This information is crucial for SNI, which is set
in transp.

diff:
@@ -45,6 +45,7 @@ struct sip_ctrans {
struct sip_connqent *qent;
char *met;
char *branch;
+ char *host;
sip_resp_h *resph;
void *arg;
enum sip_transp tp;
@@ -112,6 +113,7 @@ static void destructor(void *arg)
tmr_cancel(&ct->tmre);
mem_deref(ct->met);
mem_deref(ct->branch);
+ mem_deref(ct->host);
mem_deref(ct->qent);
mem_deref(ct->req);
mem_deref(ct->mb);
@@ -205,7 +207,7 @@ static void retransmit_handler(void *arg)
tmr_start(&ct->tmre, timeout, retransmit_handler, ct);
err = sip_transp_send(&ct->qent, ct->sip, NULL, ct->tp, &ct->dst,
- ct->mb, transport_handler, ct);
+ ct->host, ct->mb, transport_handler, ct);
if (err) {
terminate(ct, err);
mem_deref(ct);
@@ -309,7 +311,7 @@ static bool response_handler(const struct sip_msg *msg, void *arg)
int sip_ctrans_request(struct sip_ctrans **ctp, struct sip *sip,
enum sip_transp tp, const struct sa *dst, char *met,
- char *branch, struct mbuf *mb,
+ char *branch, char *host, struct mbuf *mb,
sip_resp_h *resph, void *arg)
{
struct sip_ctrans *ct;
@@ -326,6 +328,7 @@ int sip_ctrans_request(struct sip_ctrans **ctp, struct sip *sip,
ct->invite = !strcmp(met, "INVITE");
ct->branch = mem_ref(branch);
+ ct->host = mem_ref(host);
ct->met = mem_ref(met);
ct->mb = mem_ref(mb);
ct->dst = *dst;
@@ -335,7 +338,7 @@ int sip_ctrans_request(struct sip_ctrans **ctp, struct sip *sip,
ct->resph = resph ? resph : dummy_handler;
ct->arg = arg;
- err = sip_transp_send(&ct->qent, sip, NULL, tp, dst, mb,
+ err = sip_transp_send(&ct->qent, sip, NULL, tp, dst, host, mb,
transport_handler, ct);
if (err)
goto out;
@@ -386,7 +389,7 @@ int sip_ctrans_cancel(struct sip_ctrans *ct)
goto out;
err = sip_ctrans_request(NULL, ct->sip, ct->tp, &ct->dst, cancel,
- ct->branch, mb, NULL, NULL);
+ ct->branch, NULL, mb, NULL, NULL);
if (err)
goto out;

diff:
@@ -194,7 +194,8 @@ static int request(struct sip_request *req, enum sip_transp tp,
err = sip_send(req->sip, NULL, tp, dst, mb);
else
err = sip_ctrans_request(&req->ct, req->sip, tp, dst, req->met,
- branch, mb, response_handler, req);
+ branch, req->host, mb,
+ response_handler, req);
if (err)
goto out;

diff:
@@ -207,7 +207,7 @@ void sip_close(struct sip *sip, bool force)
int sip_send(struct sip *sip, void *sock, enum sip_transp tp,
const struct sa *dst, struct mbuf *mb)
{
- return sip_transp_send(NULL, sip, sock, tp, dst, mb, NULL, NULL);
+ return sip_transp_send(NULL, sip, sock, tp, dst, NULL, mb, NULL, NULL);
}

diff:
@@ -51,8 +51,8 @@ struct sip_ctrans;
int sip_ctrans_request(struct sip_ctrans **ctp, struct sip *sip,
enum sip_transp tp, const struct sa *dst, char *met,
- char *branch, struct mbuf *mb, sip_resp_h *resph,
- void *arg);
+ char *branch, char *host, struct mbuf *mb,
+ sip_resp_h *resph, void *arg);
int sip_ctrans_cancel(struct sip_ctrans *ct);
int sip_ctrans_init(struct sip *sip, uint32_t sz);
int sip_ctrans_debug(struct re_printf *pf, const struct sip *sip);
@@ -70,8 +70,8 @@ typedef void(sip_transp_h)(int err, void *arg);
int sip_transp_init(struct sip *sip, uint32_t sz);
int sip_transp_send(struct sip_connqent **qentp, struct sip *sip, void *sock,
- enum sip_transp tp, const struct sa *dst, struct mbuf *mb,
- sip_transp_h *transph, void *arg);
+ enum sip_transp tp, const struct sa *dst, char *host,
+ struct mbuf *mb, sip_transp_h *transph, void *arg);
bool sip_transp_supported(struct sip *sip, enum sip_transp tp, int af);
const char *sip_transp_srvid(enum sip_transp tp);
bool sip_transp_reliable(enum sip_transp tp);

diff:
@@ -632,13 +632,17 @@ static void tcp_connect_handler(const struct sa *paddr, void *arg)
static int conn_send(struct sip_connqent **qentp, struct sip *sip, bool secure,
- const struct sa *dst, struct mbuf *mb,
+ const struct sa *dst, char *host, struct mbuf *mb,
sip_transp_h *transph, void *arg)
{
struct sip_conn *conn, *new_conn = NULL;
struct sip_connqent *qent;
int err = 0;
+#ifndef USE_TLS
+ (void) host;
+#endif
+
conn = conn_find(sip, dst, secure);
if (conn) {
if (!conn->established)
@@ -683,6 +687,10 @@ static int conn_send(struct sip_connqent **qentp, struct sip *sip, bool secure,
err = tls_start_tcp(&conn->sc, transp->tls, conn->tc, 0);
if (err)
goto out;
+
+ err = tls_set_verify_server(conn->sc, host);
+ if (err)
+ goto out;
}
#endif
@@ -1155,8 +1163,8 @@ void sip_transp_flush(struct sip *sip)
int sip_transp_send(struct sip_connqent **qentp, struct sip *sip, void *sock,
- enum sip_transp tp, const struct sa *dst, struct mbuf *mb,
- sip_transp_h *transph, void *arg)
+ enum sip_transp tp, const struct sa *dst, char *host,
+ struct mbuf *mb, sip_transp_h *transph, void *arg)
{
const struct sip_transport *transp;
struct sip_conn *conn;
@@ -1196,7 +1204,7 @@ int sip_transp_send(struct sip_connqent **qentp, struct sip *sip, void *sock,
err = tcp_send(conn->tc, mb);
}
else
- err = conn_send(qentp, sip, secure, dst, mb,
+ err = conn_send(qentp, sip, secure, dst, host, mb,
transph, arg);
break;

original_message:
sip: SIP/TLS Server Name Indication (#67)

A change in the API of ctrans and transp is necessary. At the
calls between request and ctrans, the hostname information of the
next hop is lost. This information is crucial for SNI, which is set
in transp.


message:
tls: tls_get_issuer/subject return the info of the first loaded ca
Openssl uses two different certificate storages by SSL_CTX_use_certificate_chain_file
The first certificate loaded from a file is saved in a sepparate storage.
Upcoming certificates are located in an extra chain cert storage

change_type: MODIFY

diff:
@@ -1218,7 +1218,7 @@ static int convert_X509_NAME_to_mbuf(X509_NAME *field, struct mbuf *mb,
*
* @param tls TLS Object
* @param mb Memory buffer
- * @param field_getter Functionpointer to the X509 getter functon
+ * @param field_getter Functionpointer to the X509 getter function
* @param flags X509_NAME_print_ex flags
*
* @return 0 if success, othewise errorcode
@@ -1226,35 +1226,18 @@ static int convert_X509_NAME_to_mbuf(X509_NAME *field, struct mbuf *mb,
static int tls_get_ca_chain_field(struct tls *tls, struct mbuf *mb,
tls_get_certfield_h *field_getter, unsigned long flags)
{
- STACK_OF(X509) *certstack;
- X509 *cert;
+ X509 *crt = NULL;
X509_NAME *field;
- int err = EINVAL;
- if (!field_getter)
+ crt = SSL_CTX_get0_certificate(tls->ctx);
+ if (!crt)
return EINVAL;
- if (!SSL_CTX_get0_chain_certs(tls->ctx, &certstack) || !certstack)
- goto out;
-
- for (int i = 0; i < sk_X509_num(certstack); i++) {
- cert = sk_X509_value(certstack, i);
- if (!cert)
- goto out;
-
- field = field_getter(cert);
+ field = field_getter(crt);
if (!field)
- goto out;
-
- err = convert_X509_NAME_to_mbuf(field, mb, flags);
- if (err)
- goto out;
- }
-
- err = 0;
+ return EINVAL;
- out:
- return err;
+ return convert_X509_NAME_to_mbuf(field, mb, flags);
}

license: BSD 3-Clause New or Revised License

repo: baresip/re


message: tls: more generic function to set cafile and capath

diff:
@@ -33,6 +33,8 @@ enum tls_keytype {
int tls_alloc(struct tls **tlsp, enum tls_method method, const char *keyfile,
const char *pwd);
int tls_add_ca(struct tls *tls, const char *cafile);
+int tls_add_cafile_path(struct tls *tls, const char *cafile,
+ const char *capath);
int tls_add_capem(struct tls *tls, const char *capem);
int tls_set_selfsigned(struct tls *tls, const char *cn);
int tls_set_selfsigned_rsa(struct tls *tls, const char *cn, size_t bits);

diff:
@@ -249,12 +249,32 @@ int tls_alloc(struct tls **tlsp, enum tls_method method, const char *keyfile,
*/
int tls_add_ca(struct tls *tls, const char *cafile)
{
- if (!tls || !cafile || !tls->ctx)
+ return tls_add_cafile_path(tls, cafile, NULL);
+}
+
+
+/**
+ * Set default file and path for trusted CA certificates
+ *
+ * @param tls TLS Context
+ * @param cafile PEM file with CA certificate
+ * @param capath Path containing CA certificates
+ *
+ * @return 0 if success, otherwise errorcode
+ */
+int tls_add_cafile_path(struct tls *tls, const char *cafile,
+ const char *capath)
+{
+ if (!tls || (!cafile && !capath) || !tls->ctx)
return EINVAL;
/* Load the CAs we trust */
- if (!(SSL_CTX_load_verify_locations(tls->ctx, cafile, NULL))) {
+ if (!(SSL_CTX_load_verify_locations(tls->ctx, cafile, capath))) {
+ if (str_isset(cafile))
DEBUG_WARNING("Can't read CA file: %s\n", cafile);
+ if (str_isset(capath))
+ DEBUG_WARNING("Can't read CA path: %s\n", capath);
+
ERR_clear_error();
return EINVAL;
}


message: sys: filesystem isdir function

diff:
@@ -71,3 +71,4 @@ void rand_bytes(uint8_t *p, size_t size);
/* File-System */
int fs_mkdir(const char *path, uint16_t mode);
int fs_gethome(char *path, size_t sz);
+bool fs_isdir(const char *path);

diff:
*
* Copyright (C) 2010 Creytiv.com
*/
+#define _DEFAULT_SOURCE 1
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
@@ -105,3 +106,27 @@ int fs_gethome(char *path, size_t sz)
return ENOSYS;
#endif
}
+
+
+/**
+ * Check if given path is directory
+ *
+ * @param path Directory
+ *
+ * @return True if directory, False if not
+ */
+bool fs_isdir(const char *path)
+{
+ struct stat st;
+
+ if (!path)
+ return false;
+
+ if (stat(path, &st) < 0)
+ return false;
+
+ if ((st.st_mode & S_IFMT) != S_IFDIR)
+ return false;
+
+ return true;
+}

original_message: sys: filesystem isdir function


message: tls: check capath is directory

diff:
@@ -268,12 +268,15 @@ int tls_add_cafile_path(struct tls *tls, const char *cafile,
if (!tls || (!cafile && !capath) || !tls->ctx)
return EINVAL;
+ if (capath && !fs_isdir(capath)) {
+ DEBUG_WARNING("capath is not a directory\n");
+ return ENOENT;
+ }
+
/* Load the CAs we trust */
if (!(SSL_CTX_load_verify_locations(tls->ctx, cafile, capath))) {
if (str_isset(cafile))
DEBUG_WARNING("Can't read CA file: %s\n", cafile);
- if (str_isset(capath))
- DEBUG_WARNING("Can't read CA path: %s\n", capath);
ERR_clear_error();
return ENOENT;

original_message: tls: check capath is directory


message: tls: use ENOTDIR in tls_add_cafile_path if capath is not a dir

diff:
@@ -270,7 +270,7 @@ int tls_add_cafile_path(struct tls *tls, const char *cafile,
if (capath && !fs_isdir(capath)) {
DEBUG_WARNING("capath is not a directory\n");
- return ENOENT;
+ return ENOTDIR;
}
/* Load the CAs we trust */


message: sys: filesystem isfile function

diff:
@@ -72,3 +72,4 @@ void rand_bytes(uint8_t *p, size_t size);
int fs_mkdir(const char *path, uint16_t mode);
int fs_gethome(char *path, size_t sz);
bool fs_isdir(const char *path);
+bool fs_isfile(const char *file);

diff:
@@ -131,3 +131,27 @@ bool fs_isdir(const char *path)
return true;
}
+
+
+/**
+ * Check if given file exists and is a regular file
+ *
+ * @param file Filepath
+ *
+ * @return True if exists and is regular file, False if not
+ */
+bool fs_isfile(const char *file)
+{
+ struct stat st;
+
+ if (!file)
+ return false;
+
+ if (stat(file, &st) < 0)
+ return false;
+
+ if ((st.st_mode & S_IFMT) != S_IFREG)
+ return false;
+
+ return true;
+}

original_message: sys: filesystem isfile function


message: tls: function to replace cert for SSL object of a connection

diff:
@@ -69,6 +69,7 @@ void tls_disable_verify_server(struct tls *tls);
/* TCP */
+int tls_conn_change_cert(struct tls_conn *tc, const char *file);
int tls_start_tcp(struct tls_conn **ptc, struct tls *tls,
struct tcp_conn *tcp, int layer);

diff:
@@ -347,6 +347,44 @@ static bool send_handler(int *err, struct mbuf *mb, void *arg)
}
+/**
+ * Change used certificate+key of an existing SSL object
+ *
+ * @param tc TLS connection object
+ * @param file Cert+Key file
+ *
+ * @return int 0 if success, otherwise errorcode
+ */
+int tls_conn_change_cert(struct tls_conn *tc, const char *file)
+{
+ int r = 0;
+
+ if (!tc || !file)
+ return EINVAL;
+
+#if (OPENSSL_VERSION_NUMBER >= 0x10100000L)
+ r = SSL_use_certificate_chain_file(tc->ssl, file);
+#else
+ r = SSL_use_certificate_file(tc->ssl, file, SSL_FILETYPE_PEM);
+#endif
+ if (r <= 0) {
+ DEBUG_WARNING("change cert: "
+ "cant't read certificate file: %s\n", file);
+ ERR_clear_error();
+ return EINVAL;
+ }
+
+ r = SSL_use_PrivateKey_file(tc->ssl, file, SSL_FILETYPE_PEM);
+ if (r <= 0) {
+ DEBUG_WARNING("change cert: key missmatch in %s\n", file);
+ ERR_clear_error();
+ return EKEYREJECTED;
+ }
+
+ return 0;
+}
+
+
/**
* Start TLS on a TCP-connection
*


message:
transp: add and use different client certificates
Allows to handle different client certificates for
different TLS connections. In case no specific client
certificate is set for a connection, just use the
SIP server TLS certificate.

diff:
@@ -270,6 +270,8 @@ int sip_transp_add(struct sip *sip, enum sip_transp tp,
int sip_transp_add_websock(struct sip *sip, enum sip_transp tp,
const struct sa *laddr,
bool server, const char *cert);
+int sip_transp_add_ccert(struct sip *sip, const struct uri *uri,
+ const char *ccertfile);
void sip_transp_flush(struct sip *sip);
bool sip_transp_isladdr(const struct sip *sip, enum sip_transp tp,
const struct sa *laddr);

diff:
@@ -35,10 +35,17 @@ enum {
};
+struct sip_ccert {
+ struct le he;
+ struct pl file;
+};
+
+
struct sip_transport {
struct le le;
struct sa laddr;
struct sip *sip;
+ struct hash *ht_ccert;
struct tls *tls;
void *sock;
enum sip_transp tp;
@@ -95,6 +102,8 @@ static void transp_destructor(void *arg)
udp_handler_set(transp->sock, NULL, NULL);
list_unlink(&transp->le);
+ hash_flush(transp->ht_ccert);
+ mem_deref(transp->ht_ccert);
mem_deref(transp->sock);
mem_deref(transp->tls);
mem_deref(transp->http_cli);
@@ -630,6 +639,40 @@ static void tcp_connect_handler(const struct sa *paddr, void *arg)
}
}
+#ifdef USE_TLS
+static uint32_t get_hash_of_fromhdr(struct mbuf *mb)
+{
+ struct sip_msg *msg;
+ struct mbuf *sup = NULL;
+ uint32_t hsup = 0;
+ int err = 0;
+
+ err = sip_msg_decode(&msg, mb);
+ if (err)
+ return 0;
+
+ sup = mbuf_alloc(30);
+ if (!sup)
+ return ENOMEM;
+
+ err = mbuf_printf(sup, "\"%r\" <%r:%r@%r:%d>", &msg->from.uri.user,
+ &msg->from.uri.scheme, &msg->from.uri.user,
+ &msg->from.uri.host, msg->from.uri.port);
+ if (err)
+ goto out;
+
+ mbuf_set_pos(sup, 0);
+ hsup = hash_joaat(mbuf_buf(sup), mbuf_get_left(sup));
+ mbuf_set_pos(mb, 0);
+
+ out:
+ mem_deref(msg);
+ mem_deref(sup);
+
+ return hsup;
+}
+#endif
+
static int conn_send(struct sip_connqent **qentp, struct sip *sip, bool secure,
const struct sa *dst, char *host, struct mbuf *mb,
@@ -677,6 +720,8 @@ static int conn_send(struct sip_connqent **qentp, struct sip *sip, bool secure,
#ifdef USE_TLS
if (secure) {
const struct sip_transport *transp;
+ struct sip_ccert *ccert;
+ uint32_t hash = 0;
transp = transp_find(sip, SIP_TRANSP_TLS, sa_af(dst), dst);
if (!transp || !transp->tls) {
@@ -688,7 +733,22 @@ static int conn_send(struct sip_connqent **qentp, struct sip *sip, bool secure,
if (err)
goto out;
- err = tls_set_verify_server(conn->sc, host);
+ hash = get_hash_of_fromhdr(mb);
+ ccert = list_ledata(
+ list_head(hash_list(transp->ht_ccert, hash)));
+ if (ccert) {
+ char *f;
+ err = pl_strdup(&f, &ccert->file);
+ if (err)
+ goto out;
+
+ err = tls_conn_change_cert(conn->sc, f);
+ mem_deref(f);
+ if (err)
+ goto out;
+ }
+
+ err |= tls_set_verify_server(conn->sc, host);
if (err)
goto out;
}
@@ -1036,6 +1096,14 @@ int sip_transp_add(struct sip *sip, enum sip_transp tp,
if (!transp)
return ENOMEM;
+ if (tp == SIP_TRANSP_TLS) {
+ err = hash_alloc(&transp->ht_ccert, 32);
+ if (err) {
+ mem_deref(transp);
+ return err;
+ }
+ }
+
list_append(&sip->transpl, &transp->le, transp);
transp->sip = sip;
transp->tp = tp;
@@ -1147,6 +1215,71 @@ int sip_transp_add_websock(struct sip *sip, enum sip_transp tp,
}
+/**
+ * Add a client certificate to the TLS transport object
+ * Client certificates are saved as hash-table.
+ * Hashtable-Key: "username" <sip:username\@address:port>
+ *
+ * @param sip Global SIP stack
+ * @param uri Account uri information
+ * @param cert Certificate + Key file
+ *
+ * @return int 0 if success, otherwise errorcode
+ */
+int sip_transp_add_ccert(struct sip *sip, const struct uri *uri,
+ const char *cert)
+{
+ int err = 0;
+ const struct sip_transport *transp = NULL;
+ struct sip_ccert *ccert = NULL;
+ struct mbuf *sup = NULL;
+ uint32_t hsup = 0;
+
+ if (!sip || !uri || !cert)
+ return EINVAL;
+
+ sup = mbuf_alloc(30);
+ if (!sup)
+ return ENOMEM;
+
+ err = mbuf_printf(sup, "\"%r\" <%r:%r@%r:%d>", &uri->user,
+ &uri->scheme, &uri->user, &uri->host, uri->port);
+ if (err)
+ goto out;
+
+ mbuf_set_pos(sup, 0);
+
+ hsup = hash_joaat(mbuf_buf(sup), mbuf_get_left(sup));
+ transp = transp_find(sip, SIP_TRANSP_TLS, AF_INET, NULL);
+ if (transp) {
+ ccert = mem_zalloc(sizeof(*ccert), NULL);
+ if (!ccert) {
+ err = ENOMEM;
+ goto out;
+ }
+
+ pl_set_str(&ccert->file, cert);
+ hash_append(transp->ht_ccert, hsup, &ccert->he, ccert);
+ }
+
+ transp = transp_find(sip, SIP_TRANSP_TLS, AF_INET6, NULL);
+ if (transp) {
+ ccert = mem_zalloc(sizeof(*ccert), NULL);
+ if (!ccert) {
+ err = ENOMEM;
+ goto out;
+ }
+
+ pl_set_str(&ccert->file, cert);
+ hash_append(transp->ht_ccert, hsup, &ccert->he, ccert);
+ }
+
+ out:
+ mem_deref(sup);
+ return err;
+}
+
+
/**
* Flush all transports of a SIP stack instance
*

diff:
@@ -362,7 +362,8 @@ int tls_conn_change_cert(struct tls_conn *tc, const char *file)
if (!tc || !file)
return EINVAL;
-#if (OPENSSL_VERSION_NUMBER >= 0x10100000L)
+#if OPENSSL_VERSION_NUMBER >= 0x10100000L && \
+ !defined(LIBRESSL_VERSION_NUMBER)
r = SSL_use_certificate_chain_file(tc->ssl, file);
#else
r = SSL_use_certificate_file(tc->ssl, file, SSL_FILETYPE_PEM);


message:
sipsess: add a new redirect handler callback way
Adding a redirect handler allows libre to push information into baresip
about an ongoing redirections resulting from a 3xx code.

diff:
@@ -347,6 +347,7 @@ int sip_dialog_fork(struct sip_dialog **dlgp, struct sip_dialog *odlg,
int sip_dialog_update(struct sip_dialog *dlg, const struct sip_msg *msg);
bool sip_dialog_rseq_valid(struct sip_dialog *dlg, const struct sip_msg *msg);
const char *sip_dialog_callid(const struct sip_dialog *dlg);
+const char *sip_dialog_uri(const struct sip_dialog *dlg);
uint32_t sip_dialog_lseq(const struct sip_dialog *dlg);
bool sip_dialog_established(const struct sip_dialog *dlg);
bool sip_dialog_cmp(const struct sip_dialog *dlg, const struct sip_msg *msg);

diff:
@@ -20,6 +20,8 @@ typedef void (sipsess_refer_h)(struct sip *sip, const struct sip_msg *msg,
void *arg);
typedef void (sipsess_close_h)(int err, const struct sip_msg *msg, void *arg);
+typedef void (sipsess_redirect_h)(const struct sip_msg *msg,
+ const char *uri, void *arg);
int sipsess_listen(struct sipsess_sock **sockp, struct sip *sip,
int htsize, sipsess_conn_h *connh, void *arg);
@@ -45,6 +47,9 @@ int sipsess_accept(struct sipsess **sessp, struct sipsess_sock *sock,
sipsess_refer_h *referh, sipsess_close_h *closeh,
void *arg, const char *fmt, ...);
+int sipsess_set_redirect_handler(struct sipsess *sess,
+ sipsess_redirect_h *redirecth);
+
int sipsess_progress(struct sipsess *sess, uint16_t scode,
const char *reason, struct mbuf *desc,
const char *fmt, ...);

diff:
@@ -87,7 +87,6 @@ int sip_auth_encode(struct mbuf *mb, struct sip_auth *auth, const char *met,
/* dialog */
int sip_dialog_encode(struct mbuf *mb, struct sip_dialog *dlg, uint32_t cseq,
const char *met);
-const char *sip_dialog_uri(const struct sip_dialog *dlg);
const struct uri *sip_dialog_route(const struct sip_dialog *dlg);
uint32_t sip_dialog_hash(const struct sip_dialog *dlg);

diff:
@@ -90,6 +90,10 @@ static void invite_resp_handler(int err, const struct sip_msg *msg, void *arg)
if (err)
goto out;
+ if (sess->redirecth)
+ sess->redirecth(msg, sip_dialog_uri(sess->dlg),
+ sess->arg);
+
err = invite(sess);
if (err)
goto out;

diff:
@@ -203,6 +203,18 @@ int sipsess_alloc(struct sipsess **sessp, struct sipsess_sock *sock,
}
+int sipsess_set_redirect_handler(struct sipsess *sess,
+ sipsess_redirect_h *redirecth)
+{
+ if (!sess || !redirecth)
+ return EINVAL;
+
+ sess->redirecth = redirecth;
+
+ return 0;
+}
+
+
void sipsess_terminate(struct sipsess *sess, int err,
const struct sip_msg *msg)
{

diff:
@@ -30,6 +30,7 @@ struct sipsess {
sipsess_info_h *infoh;
sipsess_refer_h *referh;
sipsess_close_h *closeh;
+ sipsess_redirect_h *redirecth;
void *arg;
bool owner;
bool sent_offer;


message: fmt: add string to bool function

diff:
@@ -105,6 +105,7 @@ uint8_t ch_hex(char ch);
/* String functions */
+int str_bool(bool *val, const char *str);
int str_hex(uint8_t *hex, size_t len, const char *str);
void str_ncpy(char *dst, const char *src, size_t n);
int str_dup(char **dst, const char *src);

diff:
@@ -140,3 +140,56 @@ size_t str_len(const char *s)
{
return s ? strlen(s) : 0;
}
+
+
+/**
+ * Convert various possible boolean strings to a bool
+ *
+ * @param val Pointer to bool for returned value
+ * @param str String to be converted
+ *
+ * @return int 0 if success, otherwise errorcode
+ */
+int str_bool(bool *val, const char *str)
+{
+ int err = 0;
+
+ if (!val || !str_isset(str))
+ return EINVAL;
+
+ if (!str_casecmp(str, "0")) {
+ *val = false;
+ }
+ else if (!str_casecmp(str, "1")) {
+ *val = true;
+ }
+ else if (!str_casecmp(str, "false")) {
+ *val = false;
+ }
+ else if (!str_casecmp(str, "true")) {
+ *val = true;
+ }
+ else if (!str_casecmp(str, "disable")) {
+ *val = false;
+ }
+ else if (!str_casecmp(str, "enable")) {
+ *val = true;
+ }
+ else if (!str_casecmp(str, "off")) {
+ *val = false;
+ }
+ else if (!str_casecmp(str, "on")) {
+ *val = true;
+ }
+ else if (!str_casecmp(str, "no")) {
+ *val = false;
+ }
+ else if (!str_casecmp(str, "yes")) {
+ *val = true;
+ }
+ else {
+ err = EINVAL;
+ }
+
+ return err;
+}

original_message: fmt: add string to bool function


message: sip: fix possible "???" dns srv queries by skipping lines without srvid

diff:
@@ -294,6 +294,11 @@ static bool transp_next_srv(struct sip *sip, enum sip_transp *tp)
enum sip_transp i;
for (i=(enum sip_transp)(*tp-1); i>SIP_TRANSP_NONE; i--) {
+ const char *srvid;
+
+ srvid = sip_transp_srvid(i);
+ if (0 == str_cmp(srvid, "???"))
+ continue;
if (!sip_transp_supported(sip, i, AF_UNSPEC))
continue;


message:
tls: fix client certificate replacement
* SSL_use_certificate_chain_file does not always replace existing
certificates in the SSL objects cert storage.
* To force the usage of the client cert, the cert store of the
SSL object is now cleared befor a new certificate is loaded

diff:
@@ -362,6 +362,10 @@ int tls_conn_change_cert(struct tls_conn *tc, const char *file)
if (!tc || !file)
return EINVAL;
+#if !defined(LIBRESSL_VERSION_NUMBER)
+ SSL_certs_clear(tc->ssl);
+#endif
+
#if OPENSSL_VERSION_NUMBER >= 0x10100000L && \
!defined(LIBRESSL_VERSION_NUMBER)
r = SSL_use_certificate_chain_file(tc->ssl, file);


message: sdp: differentiate between media line disabled or rejected

diff:
@@ -354,7 +354,8 @@ static int media_encode(const struct sdp_media *m, struct mbuf *mb, bool offer)
enum sdp_bandwidth i;
const char *proto;
int err, supc = 0;
- bool disabled;
+ bool disabled = false;
+ bool rejected = false;
struct le *le;
uint16_t port;
@@ -366,25 +367,29 @@ static int media_encode(const struct sdp_media *m, struct mbuf *mb, bool offer)
++supc;
}
- if (m->uproto && !offer) {
+ /*disable if: local supported and (m->disabled or raddr port 0)*/
+ if (supc && (m->disabled || (!offer && !sa_port(&m->raddr)))) {
disabled = true;
- port = 0;
- proto = m->uproto;
+ port = sa_port(&m->laddr);
+ proto = m->proto;
}
- else if (m->disabled || supc == 0 || (!offer && !sa_port(&m->raddr))) {
- disabled = true;
+ /*reject if: not supported or not supported proto in the offer*/
+ else if (supc == 0 || (!offer && m->uproto)) {
+ rejected = true;
port = 0;
+ if (str_isset(m->uproto))
+ proto = m->uproto;
+ else
proto = m->proto;
}
+ /*everything works*/
else {
- disabled = false;
port = sa_port(&m->laddr);
proto = m->proto;
}
err = mbuf_printf(mb, "m=%s %u %s", m->name, port, proto);
-
- if (disabled) {
+ if (rejected) {
err |= mbuf_write_str(mb, " 0\r\n");
return err;
}
@@ -446,7 +451,8 @@ static int media_encode(const struct sdp_media *m, struct mbuf *mb, bool offer)
err |= mbuf_printf(mb, "a=rtcp:%u\r\n",
sa_port(&m->laddr_rtcp));
- err |= mbuf_printf(mb, "a=%s\r\n",
+ err |= mbuf_printf(mb, "a=%s\r\n", disabled ?
+ sdp_dir_name(SDP_INACTIVE) :
sdp_dir_name(offer ? m->ldir : m->ldir & m->rdir));
for (le = m->lattrl.head; le; le = le->next)


message: Add script to build mvfst and update README

diff:
@@ -31,3 +31,45 @@ sudo apt-get install \
```
Then, build and install folly and fizz
+
+Alternatively, run the helper script `build_helper.sh` in this subdirectory.
+It will install and link the required dependencies and also build folly and fizz.
+This may take several minutes the first time.
+
+```
+./build_helper.sh
+```
+
+After building, the directory `_build/` will contain the dependencies
+(under `_build/deps`) whereas `_build/build` will contain all the
+built libraries and binaries for `mvfst`.
+
+You can also install `mvfst` as well as its dependencies `folly` and `fizz`
+to a custom directory using the build script, by supplying an `INSTALL_PREFIX`
+env var.
+
+```
+./build_helper.sh -i /usr/local
+```
+See `./build_helper.sh --help` for more options
+
+You might need to run the script as root to install to certain directories.
+
+## Contributing
+
+We'd love to have your help in making MVFST better. If you're interested, please
+read our guide to [guide to contributing](CONTRIBUTING.md)
+
+## License
+MVFST is MIT licensed, as found in the LICENSE file.
+
+## Reporting and Fixing Security Issues
+
+Please do not open GitHub issues or pull requests - this makes the problem
+immediately visible to everyone, including malicious actors. Security issues in
+MVFST can be safely reported via Facebook's Whitehat Bug Bounty program:
+
+https://www.facebook.com/whitehat
+
+Facebook's security team will triage your report and determine whether or not is
+it eligible for a bounty under our program.

change_type: ADD

diff:
+#!/bin/bash -eu
+
+# Copyright (c) Facebook, Inc. and its affiliates.
+#
+# This source code is licensed under the MIT license found in the
+# LICENSE file in the root directory of this source tree.
+
+
+# This is a helpful script to build MVFST in the supplied dir
+# It pulls in dependencies such as folly and fizz in the _build/deps dir.
+
+# Useful constants
+COLOR_RED="\033[0;31m"
+COLOR_GREEN="\033[0;32m"
+COLOR_OFF="\033[0m"
+
+usage() {
+cat 1>&2 <<EOF
+
+Usage ${0##*/} [-h|?] [-p PATH] [-i INSTALL_PREFIX]
+ -p BUILD_DIR (optional): Path of the base dir for mvfst
+ -i INSTALL_PREFIX (optional): install prefix path
+ -h|? Show this help message
+EOF
+}
+
+while getopts ":hp:" arg; do
+ case $arg in
+ p)
+ BUILD_DIR="${OPTARG}"
+ ;;
+ h | *) # Display help.
+ usage
+ exit 0
+ ;;
+ esac
+done
+
+# Validate required parameters
+if [ -z "${BUILD_DIR-}" ] ; then
+ echo -e "${COLOR_RED}[ INFO ] Build dir is not set. So going to build into _build ${COLOR_OFF}"
+ BUILD_DIR=_build
+ mkdir -p $BUILD_DIR
+fi
+
+### configure necessary build and install directories
+
+cd $BUILD_DIR || exit
+BWD=$(pwd)
+DEPS_DIR=$BWD/deps
+mkdir -p "$DEPS_DIR"
+
+MVFST_BUILD_DIR=$BWD/build
+mkdir -p "$MVFST_BUILD_DIR"
+
+if [ -z "${INSTALL_PREFIX-}" ]; then
+ FOLLY_INSTALL_DIR=$DEPS_DIR
+ FIZZ_INSTALL_DIR=$DEPS_DIR
+ GTEST_INSTALL_DIR=$DEPS_DIR
+ MVFST_INSTALL_DIR=$BWD
+else
+ FOLLY_INSTALL_DIR=$INSTALL_PREFIX
+ FIZZ_INSTALL_DIR=$INSTALL_PREFIX
+ GTEST_INSTALL_DIR=$INSTALL_PREFIX
+ MVFST_INSTALL_DIR=$INSTALL_PREFIX
+fi
+
+function install_dependencies_linux() {
+ sudo apt-get install \
+ g++ \
+ cmake \
+ libboost-all-dev \
+ libevent-dev \
+ libdouble-conversion-dev \
+ libgoogle-glog-dev \
+ libgflags-dev \
+ libiberty-dev \
+ liblz4-dev \
+ liblzma-dev \
+ libsnappy-dev \
+ make \
+ zlib1g-dev \
+ binutils-dev \
+ libjemalloc-dev \
+ libssl-dev \
+ pkg-config \
+ libsodium-dev
+}
+
+function install_dependencies_mac() {
+ # install the default dependencies from homebrew
+ brew install \
+ cmake \
+ boost \
+ double-conversion \
+ gflags \
+ glog \
+ libevent \
+ lz4 \
+ snappy \
+ xz \
+ openssl \
+ libsodium
+
+ brew link \
+ boost \
+ double-conversion \
+ gflags \
+ glog \
+ libevent \
+ lz4 \
+ snappy \
+ xz \
+ libsodium
+}
+
+function setup_folly() {
+ FOLLY_DIR=$DEPS_DIR/folly
+ FOLLY_BUILD_DIR=$DEPS_DIR/folly/build/
+
+ if [ ! -d "$FOLLY_DIR" ] ; then
+ echo -e "${COLOR_GREEN}[ INFO ] Cloning folly repo ${COLOR_OFF}"
+ git clone https://github.com/facebook/folly.git "$FOLLY_DIR"
+ echo -e "${COLOR_GREEN}[ INFO ] install dependencies ${COLOR_OFF}"
+ if [ "$Platform" = "Linux" ]; then
+ install_dependencies_linux
+ elif [ "$Platform" = "Mac" ]; then
+ install_dependencies_mac
+ else
+ echo -e "${COLOR_RED}[ ERROR ] Unknown platform: $Platform ${COLOR_OFF}"
+ exit 1
+ fi
+ fi
+ echo -e "${COLOR_GREEN}Building Folly ${COLOR_OFF}"
+ mkdir -p "$FOLLY_BUILD_DIR"
+ cd "$FOLLY_BUILD_DIR" || exit
+ cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo \
+ -DCMAKE_PREFIX_PATH="$FOLLY_INSTALL_DIR" \
+ -DCMAKE_INSTALL_PREFIX="$FOLLY_INSTALL_DIR" \
+ ..
+ make -j "$(nproc)"
+ make install
+ cd "$BWD" || exit
+}
+
+function setup_fizz() {
+ FIZZ_DIR=$DEPS_DIR/fizz
+ FIZZ_BUILD_DIR=$DEPS_DIR/fizz/build/
+ if [ ! -d "$FIZZ_DIR" ] ; then
+ echo -e "${COLOR_GREEN}[ INFO ] Cloning fizz repo ${COLOR_OFF}"
+ git clone https://github.com/facebookincubator/fizz "$FIZZ_DIR"
+ echo -e "${COLOR_GREEN}[ INFO ] install dependencies ${COLOR_OFF}"
+ fi
+ echo -e "${COLOR_GREEN}Building Fizz ${COLOR_OFF}"
+ mkdir -p "$FIZZ_BUILD_DIR"
+ cd "$FIZZ_BUILD_DIR" || exit
+ cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo \
+ -DCMAKE_PREFIX_PATH="$FIZZ_INSTALL_DIR" \
+ -DCMAKE_INSTALL_PREFIX="$FIZZ_INSTALL_DIR" \
+ "$FIZZ_DIR/fizz"
+ make -j "$(nproc)"
+ make install
+ echo -e "${COLOR_GREEN}Folly is installed ${COLOR_OFF}"
+ cd "$BWD" || exit
+}
+
+function setup_googletest() {
+ GTEST_DIR=$DEPS_DIR/googletest-release-1.8.0
+ GTEST_BUILD_DIR=$GTEST_DIR/build
+ # requires googletest-1.8
+ if [ ! -d "$GTEST_DIR" ] ; then
+ echo -e "${COLOR_GREEN}[ INFO ] Downloading gtest-1.8 ${COLOR_OFF}"
+ TMP_DIR=$(mktemp -d)
+ pushd .
+ cd "$TMP_DIR"
+ wget https://github.com/google/googletest/archive/release-1.8.0.zip -O "googletest.zip"
+ unzip "googletest.zip" -d "$DEPS_DIR"
+ popd
+ fi
+ echo -e "${COLOR_GREEN}Building Googletest ${COLOR_OFF}"
+ mkdir -p "$GTEST_BUILD_DIR"
+ cd "$GTEST_BUILD_DIR" || exit
+ cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo \
+ -DCMAKE_PREFIX_PATH="$GTEST_INSTALL_DIR" \
+ -DCMAKE_INSTALL_PREFIX="$GTEST_INSTALL_DIR" \
+ ..
+ make -j "$(nproc)"
+ make install
+ echo -e "${COLOR_GREEN}Googletest is installed ${COLOR_OFF}"
+ cd "$BWD" || exit
+}
+
+function detect_platform() {
+ unameOut="$(uname -s)"
+ case "${unameOut}" in
+ Linux*) Platform=Linux;;
+ Darwin*) Platform=Mac;;
+ *) Platform="UNKNOWN:${unameOut}"
+ esac
+ echo -e "${COLOR_GREEN}Detected platform: $Platform ${COLOR_OFF}"
+}
+
+detect_platform
+setup_googletest
+setup_folly
+setup_fizz
+
+# build mvfst:
+cd "$MVFST_BUILD_DIR" || exit
+cmake -DCMAKE_PREFIX_PATH="$FOLLY_INSTALL_DIR" \
+ -DCMAKE_INSTALL_PREFIX="$MVFST_INSTALL_DIR" \
+ -DCMAKE_BUILD_TYPE=RelWithDebInfo \
+ -DBUILD_TESTS=On \
+ -DFIZZ_PROJECT="$DEPS_DIR/fizz" \
+ ../..
+make -j "$(nproc)"
+echo -e "${COLOR_GREEN}MVFST build is complete. To run unit test: \
+ cd _build/build && make test ${COLOR_OFF}"

license: MIT License

repo: facebookincubator/mvfst


message: Sync changes to rename onNewStream and CongestionController factory

diff:
@@ -44,7 +44,7 @@ class QuicSocket {
* Invoked when the peer creates a new bidirectional stream. The most
* common flow would be to set the ReadCallback from here
*/
- virtual void onNewStream(StreamId id) noexcept = 0;
+ virtual void onNewBidirectionalStream(StreamId id) noexcept = 0;
/**
* Invoked when the peer creates a new unidirectional stream. The most
@@ -445,7 +445,7 @@ class QuicSocket {
/**
* Usage:
* class Application {
- * void onNewStream(StreamId id) {
+ * void onNewBidirectionalStream(StreamId id) {
* socket_->setPeekCallback(id, this);
* }
*
@@ -844,7 +844,7 @@ class QuicSocket {
* A control stream outlives all the other streams in a connection, therefore,
* if the transport knows about it, can enable some optimizations.
* Applications should declare all their control streams after either calling
- * createStream() or receiving onNewStream()
+ * createStream() or receiving onNewBidirectionalStream()
*/
virtual folly::Optional<LocalErrorCode> setControlStream(StreamId id) = 0;
};

diff:
@@ -1247,7 +1247,7 @@ void QuicTransportBase::processCallbacksAfterNetworkData() {
for (const auto& stream : conn_->streamManager->newPeerStreams()) {
CHECK_NOTNULL(connCallback_);
if (isBidirectionalStream(stream)) {
- connCallback_->onNewStream(stream);
+ connCallback_->onNewBidirectionalStream(stream);
} else {
connCallback_->onNewUnidirectionalStream(stream);
}

diff:
@@ -101,7 +101,7 @@ class MockConnectionCallback : public QuicSocket::ConnectionCallback {
~MockConnectionCallback() override = default;
GMOCK_METHOD1_(, noexcept, , onFlowControlUpdate, void(StreamId));
- GMOCK_METHOD1_(, noexcept, , onNewStream, void(StreamId));
+ GMOCK_METHOD1_(, noexcept, , onNewBidirectionalStream, void(StreamId));
GMOCK_METHOD1_(, noexcept, , onNewUnidirectionalStream, void(StreamId));
GMOCK_METHOD2_(
,

diff:
@@ -690,7 +690,7 @@ TEST_F(QuicTransportImplTest, ReadCallbackForClientOutOfOrderStream) {
for (StreamId start = 0x00; start <= clientOutOfOrderStream;
start += kStreamIncrement) {
- EXPECT_CALL(connCallback, onNewStream(start))
+ EXPECT_CALL(connCallback, onNewBidirectionalStream(start))
.WillOnce(Invoke(
[&](StreamId id) { transport->setReadCallback(id, &streamRead); }));
}
@@ -770,15 +770,15 @@ TEST_F(QuicTransportImplTest, ReadCallbackDeleteTransport) {
transport.reset();
}
-TEST_F(QuicTransportImplTest, OnNewStreamCallback) {
+TEST_F(QuicTransportImplTest, onNewBidirectionalStreamCallback) {
auto readData = folly::IOBuf::copyBuffer("actual stream data");
StreamId stream2 = 0x00;
- EXPECT_CALL(connCallback, onNewStream(stream2));
+ EXPECT_CALL(connCallback, onNewBidirectionalStream(stream2));
transport->addDataToStream(stream2, StreamBuffer(readData->clone(), 0, true));
StreamId stream3 = 0x04;
- EXPECT_CALL(connCallback, onNewStream(stream3));
+ EXPECT_CALL(connCallback, onNewBidirectionalStream(stream3));
transport->addDataToStream(stream3, StreamBuffer(readData->clone(), 0, true));
StreamId uniStream3 = 0xa;
@@ -793,13 +793,13 @@ TEST_F(QuicTransportImplTest, OnNewStreamCallback) {
transport.reset();
}
-TEST_F(QuicTransportImplTest, OnNewStreamStreamOutOfOrder) {
+TEST_F(QuicTransportImplTest, onNewBidirectionalStreamStreamOutOfOrder) {
InSequence dummy;
auto readData = folly::IOBuf::copyBuffer("actual stream data");
StreamId biStream1 = 28;
StreamId uniStream1 = 30;
for (StreamId id = 0x00; id <= biStream1; id += kStreamIncrement) {
- EXPECT_CALL(connCallback, onNewStream(id));
+ EXPECT_CALL(connCallback, onNewBidirectionalStream(id));
}
for (StreamId id = 0x02; id <= uniStream1; id += kStreamIncrement) {
EXPECT_CALL(connCallback, onNewUnidirectionalStream(id));
@@ -813,7 +813,7 @@ TEST_F(QuicTransportImplTest, OnNewStreamStreamOutOfOrder) {
StreamId uniStream2 = 38;
for (StreamId id = biStream1 + kStreamIncrement; id <= biStream2;
id += kStreamIncrement) {
- EXPECT_CALL(connCallback, onNewStream(id));
+ EXPECT_CALL(connCallback, onNewBidirectionalStream(id));
}
for (StreamId id = uniStream1 + kStreamIncrement; id <= uniStream2;
id += kStreamIncrement) {
@@ -826,14 +826,14 @@ TEST_F(QuicTransportImplTest, OnNewStreamStreamOutOfOrder) {
transport.reset();
}
-TEST_F(QuicTransportImplTest, OnNewStreamSetReadCallback) {
+TEST_F(QuicTransportImplTest, onNewBidirectionalStreamSetReadCallback) {
InSequence dummy;
auto readData = folly::IOBuf::copyBuffer("actual stream data");
transport->addCryptoData(StreamBuffer(readData->clone(), 0, true));
MockReadCallback stream2Read;
StreamId stream2 = 0x00;
- EXPECT_CALL(connCallback, onNewStream(stream2))
+ EXPECT_CALL(connCallback, onNewBidirectionalStream(stream2))
.WillOnce(Invoke(
[&](StreamId id) { transport->setReadCallback(id, &stream2Read); }));
transport->addDataToStream(stream2, StreamBuffer(readData->clone(), 0, true));
@@ -842,7 +842,7 @@ TEST_F(QuicTransportImplTest, OnNewStreamSetReadCallback) {
MockReadCallback streamRead;
for (StreamId start = stream2 + kStreamIncrement; start <= stream3;
start += kStreamIncrement) {
- EXPECT_CALL(connCallback, onNewStream(start))
+ EXPECT_CALL(connCallback, onNewBidirectionalStream(start))
.WillOnce(Invoke(
[&](StreamId id) { transport->setReadCallback(id, &streamRead); }));
}

diff:
@@ -1287,7 +1287,7 @@ TEST_F(QuicClientTransportTest, SocketClosedDuringOnTransportReady) {
}
GMOCK_METHOD1_(, noexcept, , onFlowControlUpdate, void(StreamId));
- GMOCK_METHOD1_(, noexcept, , onNewStream, void(StreamId));
+ GMOCK_METHOD1_(, noexcept, , onNewBidirectionalStream, void(StreamId));
GMOCK_METHOD1_(, noexcept, , onNewUnidirectionalStream, void(StreamId));
GMOCK_METHOD2_(
,

diff:
@@ -54,7 +54,7 @@ class EchoClient : public quic::QuicSocket::ConnectionCallback,
<< ", error=" << toString(error);
}
- void onNewStream(quic::StreamId id) noexcept override {
+ void onNewBidirectionalStream(quic::StreamId id) noexcept override {
LOG(INFO) << "EchoClient: new bidirectional stream=" << id;
quicClient_->setReadCallback(id, this);
}

diff:
@@ -28,7 +28,7 @@ class EchoHandler : public quic::QuicSocket::ConnectionCallback,
sock = socket;
}
- void onNewStream(quic::StreamId id) noexcept override {
+ void onNewBidirectionalStream(quic::StreamId id) noexcept override {
LOG(INFO) << "Got bidirectional stream id=" << id;
sock->setReadCallback(id, this);
}

diff:
@@ -53,7 +53,8 @@ void QuicServer::setListenerSocketFactory(
void QuicServer::setCongestionControllerFactory(
std::shared_ptr<CongestionControllerFactory> ccFactory) {
CHECK(!initialized_)
- << " Congestion Control Factorty must be set before the server is initialized.";
+ << " Congestion Control Factorty must be set before the server is "
+ << "initialized.";
CHECK(ccFactory);
ccFactory_ = std::move(ccFactory);
}

diff:
@@ -362,9 +362,9 @@ void QuicServerWorker::dispatchPacketData(
trans->setRoutingCallback(this);
trans->setSupportedVersions(supportedVersions_);
trans->setOriginalPeerAddress(client);
+ trans->setCongestionControllerFactory(ccFactory_);
trans->setTransportSettings(transportSettings_);
trans->setConnectionIdAlgo(connIdAlgo_.get());
- trans->setCongestionControllerFactory(ccFactory_);
// parameters to create server chosen connection id
ServerConnectionIdParams serverConnIdParams(
hostId_, static_cast<uint8_t>(processId_), workerId_);

diff:
@@ -1414,7 +1414,7 @@ TEST_F(QuicServerTransportTest, RecvStopSendingBeforeStream) {
ASSERT_TRUE(builder.canBuildPacket());
writeFrame(std::move(stopSendingFrame), builder);
auto packet = std::move(builder).buildPacket();
- EXPECT_CALL(connCallback, onNewStream(streamId));
+ EXPECT_CALL(connCallback, onNewBidirectionalStream(streamId));
EXPECT_CALL(
connCallback, onStopSending(streamId, ApplicationErrorCode::STOPPING));
deliverData(packetToBuf(packet));

diff:
@@ -29,7 +29,7 @@ class QuicSocketTest : public Test {
void openStream(StreamId) {
EXPECT_CALL(*socket_, setReadCallback(3, &handler_));
- socket_->cb_->onNewStream(3);
+ socket_->cb_->onNewBidirectionalStream(3);
}
protected:

diff:
@@ -307,7 +307,7 @@ void QuicStreamManager::removeClosedStream(StreamId streamId) {
writableStreams_.erase(streamId);
blockedStreams_.erase(streamId);
deliverableStreams_.erase(streamId);
- flowControlUpdated_.erase(streamId);
+ windowUpdates_.erase(streamId);
auto itr = std::find(lossStreams_.begin(), lossStreams_.end(), streamId);
if (itr != lossStreams_.end()) {
lossStreams_.erase(itr);

diff:
@@ -1506,6 +1506,31 @@ TEST_F(QuicStreamFunctionsTest, HolbTimingReadDataCallsUpdateRL) {
EXPECT_EQ(1, stream->holbCount);
}
+TEST_F(QuicStreamFunctionsTest, RemovedClosedState) {
+ auto stream = conn.streamManager->createNextBidirectionalStream().value();
+ auto streamId = stream->id;
+ conn.streamManager->readableStreams().emplace(streamId);
+ conn.streamManager->peekableStreams().emplace(streamId);
+ conn.streamManager->addWritable(streamId);
+ conn.streamManager->queueBlocked(streamId, 0);
+ conn.streamManager->addDeliverable(streamId);
+ conn.streamManager->addLoss(streamId);
+ conn.streamManager->queueWindowUpdate(streamId);
+ conn.streamManager->addStopSending(
+ streamId, ApplicationErrorCode::HTTP_NO_ERROR);
+ stream->state = StreamStates::Closed{};
+ conn.streamManager->removeClosedStream(streamId);
+ EXPECT_FALSE(conn.streamManager->streamExists(streamId));
+ EXPECT_TRUE(conn.streamManager->readableStreams().empty());
+ EXPECT_TRUE(conn.streamManager->peekableStreams().empty());
+ EXPECT_FALSE(conn.streamManager->writableContains(streamId));
+ EXPECT_FALSE(conn.streamManager->hasBlocked());
+ EXPECT_FALSE(conn.streamManager->deliverableContains(streamId));
+ EXPECT_FALSE(conn.streamManager->hasLoss());
+ EXPECT_FALSE(conn.streamManager->pendingWindowUpdate(streamId));
+ EXPECT_TRUE(conn.streamManager->stopSendingStreams().empty());
+}
+
TEST_F(QuicServerStreamFunctionsTest, ServerGetClientQuicStream) {
StreamId clientStream = 0x10;
std::deque<StreamId> newStreams = {0x0, 0x4, 0x8, 0xc, 0x10};


message: Add tools to generate transport event traces

new_path: quic/tools/TARGETS

diff:
+# @autodeps
+
+load("@fbcode_macros//build_defs:python_binary.bzl", "python_binary")
+load("@fbcode_macros//build_defs:python_library.bzl", "python_library")
+
+python_library(
+ name = "base",
+ srcs = [
+ "base.py",
+ ],
+ base_module = "mvfst",
+ external_deps = [
+ ("bcc-cpp", None, "bcc"),
+ ("bcc-py", None),
+ ],
+)
+
+python_binary(
+ name = "print",
+ srcs = [
+ "print.py",
+ ],
+ base_module = "mvfst",
+ main_module = "mvfst.print",
+ strip_libpar = False,
+ deps = [
+ ":base",
+ ],
+ external_deps = [
+ ("bcc-cpp", None, "bcc"),
+ ("bcc-py", None),
+ ],
+)

diff:
+#!/usr/bin/env bcc-py
+# @lint-avoid-python-3-compatibility-imports
+
+# Copyright (c) Facebook, Inc. and its affiliates.
+#
+# This source code is licensed under the MIT license found in the
+# LICENSE file in the root directory of this source tree.
+
+from __future__ import absolute_import
+from __future__ import division
+from __future__ import unicode_literals
+from __future__ import print_function
+import argparse
+from bcc import BPF, USDT
+import ctypes as ct
+import string
+import random
+
+program = """
+struct packet_sent_event {
+ u64 evt_time;
+ u64 conn_id;
+ u64 packet_num;
+ u64 encoded_size;
+ int is_handshake;
+ int pure_ack;
+};
+
+BPF_PERF_OUTPUT(PREFIX_packets_sent);
+
+int on_packet_sent(struct pt_regs *ctx) {
+ struct packet_sent_event evt = {};
+ evt.evt_time = bpf_ktime_get_ns();
+ bpf_usdt_readarg(1, ctx, &evt.conn_id);
+ bpf_usdt_readarg(2, ctx, &evt.packet_num);
+ bpf_usdt_readarg(3, ctx, &evt.encoded_size);
+ bpf_usdt_readarg(4, ctx, &evt.is_handshake);
+ bpf_usdt_readarg(5, ctx, &evt.pure_ack);
+ PREFIX_packets_sent.perf_submit(ctx, &evt, sizeof(evt));
+ return 0;
+}
+
+struct packet_acked_event {
+ u64 evt_time;
+ u64 conn_id;
+ u64 packet_num;
+};
+
+BPF_PERF_OUTPUT(PREFIX_packets_acked);
+
+int on_packet_acked(struct pt_regs *ctx) {
+ struct packet_acked_event evt = {};
+ evt.evt_time = bpf_ktime_get_ns();
+ bpf_usdt_readarg(1, ctx, &evt.conn_id);
+ bpf_usdt_readarg(2, ctx, &evt.packet_num);
+ PREFIX_packets_acked.perf_submit(ctx, &evt, sizeof(evt));
+ return 0;
+}
+
+struct packet_lost_event {
+ u64 evt_time;
+ u64 conn_id;
+ u64 largest_lost_packet_num;
+ u64 lost_bytes;
+ u32 lost_packets;
+};
+
+BPF_PERF_OUTPUT(PREFIX_packets_lost);
+
+int on_packets_lost(struct pt_regs *ctx) {
+ struct packet_lost_event evt = {};
+ evt.evt_time = bpf_ktime_get_ns();
+ bpf_usdt_readarg(1, ctx, &evt.conn_id);
+ bpf_usdt_readarg(2, ctx, &evt.largest_lost_packet_num);
+ bpf_usdt_readarg(3, ctx, &evt.lost_bytes);
+ bpf_usdt_readarg(4, ctx, &evt.lost_packets);
+ PREFIX_packets_lost.perf_submit(ctx, &evt, sizeof(evt));
+ return 0;
+}
+
+struct packet_recvd_event {
+ u64 evt_time;
+ u64 conn_id;
+ u64 packet_num;
+ u64 size;
+};
+
+BPF_PERF_OUTPUT(PREFIX_packets_recvd);
+
+int on_packet_recvd(struct pt_regs *ctx) {
+ struct packet_recvd_event evt = {};
+ evt.evt_time = bpf_ktime_get_ns();
+ bpf_usdt_readarg(1, ctx, &evt.conn_id);
+ bpf_usdt_readarg(2, ctx, &evt.packet_num);
+ bpf_usdt_readarg(3, ctx, &evt.size);
+ PREFIX_packets_recvd.perf_submit(ctx, &evt, sizeof(evt));
+ return 0;
+}
+
+struct handshake_alarm_event {
+ u64 evt_time;
+ u64 conn_id;
+ u64 largest_sent;
+ u64 handshake_count;
+ u64 outstanding_handshake_packets;
+ u64 outstanding_packets;
+};
+
+BPF_PERF_OUTPUT(PREFIX_handshake_events);
+
+int on_handshake_alarm(struct pt_regs *ctx) {
+ struct handshake_alarm_event evt = {};
+ evt.evt_time = bpf_ktime_get_ns();
+ bpf_usdt_readarg(1, ctx, &evt.conn_id);
+ bpf_usdt_readarg(2, ctx, &evt.largest_sent);
+ bpf_usdt_readarg(3, ctx, &evt.handshake_count);
+ bpf_usdt_readarg(4, ctx, &evt.outstanding_handshake_packets);
+ bpf_usdt_readarg(5, ctx, &evt.outstanding_packets);
+ PREFIX_handshake_events.perf_submit(ctx, &evt, sizeof(evt));
+ return 0;
+}
+
+struct rto_alarm_event {
+ u64 evt_time;
+ u64 conn_id;
+ u64 largest_sent;
+ u64 largest_sent_before_rto;
+ u64 rto_count;
+ u64 outstanding_packets;
+};
+
+BPF_PERF_OUTPUT(PREFIX_rto_events);
+
+int on_rto_alarm(struct pt_regs *ctx) {
+ struct rto_alarm_event evt = {};
+ evt.evt_time = bpf_ktime_get_ns();
+ bpf_usdt_readarg(1, ctx, &evt.conn_id);
+ bpf_usdt_readarg(2, ctx, &evt.largest_sent);
+ bpf_usdt_readarg(3, ctx, &evt.largest_sent_before_rto);
+ bpf_usdt_readarg(4, ctx, &evt.rto_count);
+ bpf_usdt_readarg(5, ctx, &evt.outstanding_packets);
+ PREFIX_rto_events.perf_submit(ctx, &evt, sizeof(evt));
+ return 0;
+}
+
+struct tlp_alarm_event {
+ u64 evt_time;
+ u64 conn_id;
+ u64 largest_sent;
+ u64 tlp_count;
+ u64 outstanding_packets;
+};
+
+BPF_PERF_OUTPUT(PREFIX_tlp_events);
+
+int on_tlp_alarm(struct pt_regs *ctx) {
+ struct tlp_alarm_event evt = {};
+ evt.evt_time = bpf_ktime_get_ns();
+ bpf_usdt_readarg(1, ctx, &evt.conn_id);
+ bpf_usdt_readarg(2, ctx, &evt.largest_sent);
+ bpf_usdt_readarg(3, ctx, &evt.tlp_count);
+ bpf_usdt_readarg(4, ctx, &evt.outstanding_packets);
+ PREFIX_tlp_events.perf_submit(ctx, &evt, sizeof(evt));
+ return 0;
+}
+
+struct rto_verified_event {
+ u64 evt_time;
+ u64 conn_id;
+ u64 largest_acked_packet;
+ u64 largest_sent_before_rto;
+ u64 outstanding_packets;
+};
+
+BPF_PERF_OUTPUT(PREFIX_rto_verified_events);
+
+int on_rto_verified(struct pt_regs *ctx) {
+ struct rto_verified_event evt = {};
+ evt.evt_time = bpf_ktime_get_ns();
+ bpf_usdt_readarg(1, ctx, &evt.conn_id);
+ bpf_usdt_readarg(2, ctx, &evt.largest_acked_packet);
+ bpf_usdt_readarg(3, ctx, &evt.largest_sent_before_rto);
+ bpf_usdt_readarg(4, ctx, &evt.outstanding_packets);
+ PREFIX_rto_verified_events.perf_submit(ctx, &evt, sizeof(evt));
+ return 0;
+}
+
+/*
+struct packet_clone_event {
+ u64 evt_time;
+ u64 conn_id;
+ u64 packet_num;
+ u64 cloned_packet_num;
+ u64 frames;
+};
+
+BPF_PERF_OUTPUT(PREFIX_packets_cloned);
+
+int on_packet_clone(struct pt_regs *ctx) {
+ struct packet_clone_event evt = {};
+ evt.evt_time = bpf_ktime_get_ns();
+ bpf_usdt_readarg(1, ctx, &evt.conn_id);
+ bpf_usdt_readarg(2, ctx, &evt.packet_num);
+ bpf_usdt_readarg(3, ctx, &evt.cloned_packet_num);
+ bpf_usdt_readarg(4, ctx, &evt.frames);
+ PREFIX_packets_cloned.perf_submit(ctx, &evt, sizeof(evt));
+ return 0;
+}
+*/
+
+struct packet_drop_event {
+ u64 evt_time;
+ u64 conn_id;
+ char reason[50];
+};
+
+BPF_PERF_OUTPUT(PREFIX_packet_drop_events);
+
+int on_packet_drop(struct pt_regs *ctx) {
+ struct packet_drop_event evt = {};
+ evt.evt_time = bpf_ktime_get_ns();
+ bpf_usdt_readarg(1, ctx, &evt.conn_id);
+ bpf_usdt_readarg_p(2, ctx, &evt.reason, sizeof(evt.reason) - 1);
+ PREFIX_packet_drop_events.perf_submit(ctx, &evt, sizeof(evt));
+ return 0;
+}
+
+struct udp_recvd_event {
+ u64 evt_time;
+ u64 conn_id;
+ u64 len;
+};
+
+BPF_PERF_OUTPUT(PREFIX_udp_recvd_events);
+
+int on_udp_recvd(struct pt_regs *ctx) {
+ struct udp_recvd_event evt = {};
+ evt.evt_time = bpf_ktime_get_ns();
+ bpf_usdt_readarg(1, ctx, &evt.conn_id);
+ bpf_usdt_readarg(2, ctx, &evt.len);
+ PREFIX_udp_recvd_events.perf_submit(ctx, &evt, sizeof(evt));
+ return 0;
+}
+
+struct close_event {
+ u64 evt_time;
+ u64 conn_id;
+ u64 drain;
+ u64 send_close_immediate;
+ char close_sent[100];
+ char peer_sent[100];
+};
+
+BPF_PERF_OUTPUT(PREFIX_close_events);
+
+int on_close(struct pt_regs *ctx) {
+ struct close_event evt = {};
+ evt.evt_time = bpf_ktime_get_ns();
+ bpf_usdt_readarg(1, ctx, &evt.conn_id);
+ bpf_usdt_readarg(2, ctx, &evt.drain);
+ bpf_usdt_readarg(3, ctx, &evt.send_close_immediate);
+ bpf_usdt_readarg_p(4, ctx, &evt.close_sent, sizeof(evt.close_sent) - 1);
+ bpf_usdt_readarg_p(5, ctx, &evt.peer_sent, sizeof(evt.peer_sent) - 1);
+ PREFIX_close_events.perf_submit(ctx, &evt, sizeof(evt));
+ return 0;
+}
+
+BPF_PERF_OUTPUT(PREFIX_recvd_close_event);
+
+struct recvd_close_event {
+ u64 evt_time;
+ u64 conn_id;
+ char close_recvd[100];
+};
+
+int on_recvd_close(struct pt_regs *ctx) {
+ struct recvd_close_event evt = {};
+ evt.evt_time = bpf_ktime_get_ns();
+ bpf_usdt_readarg(1, ctx, &evt.conn_id);
+ bpf_usdt_readarg_p(2, ctx, &evt.close_recvd, sizeof(evt.close_recvd) - 1);
+ PREFIX_recvd_close_event.perf_submit(ctx, &evt, sizeof(evt));
+ return 0;
+}
+
+struct cubic_ack_event {
+ u64 evt_time;
+ u64 conn_id;
+ char newstate[10];
+ u64 cwnd;
+ u64 inflight_bytes;
+ u64 last_max_cwnd;
+};
+
+BPF_PERF_OUTPUT(PREFIX_cubic_ack_event);
+
+int on_cubic_ack(struct pt_regs* ctx) {
+ struct cubic_ack_event evt = {};
+ evt.evt_time = bpf_ktime_get_ns();
+ bpf_usdt_readarg(1, ctx, &evt.conn_id);
+ bpf_usdt_readarg_p(2, ctx, &evt.newstate, sizeof(evt.newstate) - 1);
+ bpf_usdt_readarg(3, ctx, &evt.cwnd);
+ bpf_usdt_readarg(4, ctx, &evt.inflight_bytes);
+ bpf_usdt_readarg(5, ctx, &evt.last_max_cwnd);
+ PREFIX_cubic_ack_event.perf_submit(ctx, &evt, sizeof(evt));
+ return 0;
+}
+
+struct cubic_steady_cwnd_event {
+ u64 evt_time;
+ u64 conn_id;
+ u64 curr_cwnd;
+ long long delta;
+ u64 time_to_origin_ms;
+ u64 time_elapsed_ms;
+};
+
+BPF_PERF_OUTPUT(PREFIX_cubic_steady_cwnd_event);
+
+int on_cubic_steady_cwnd_changed(struct pt_regs* ctx) {
+ struct cubic_steady_cwnd_event evt = {};
+ evt.evt_time = bpf_ktime_get_ns();
+ bpf_usdt_readarg(1, ctx, &evt.conn_id);
+ bpf_usdt_readarg(2, ctx, &evt.curr_cwnd);
+ bpf_usdt_readarg(3, ctx, &evt.delta);
+ bpf_usdt_readarg(4, ctx, &evt.time_to_origin_ms);
+ bpf_usdt_readarg(5, ctx, &evt.time_elapsed_ms);
+ PREFIX_cubic_steady_cwnd_event.perf_submit(ctx, &evt, sizeof(evt));
+ return 0;
+}
+
+BPF_PERF_OUTPUT(PREFIX_fst_trace_events);
+
+struct fst_trace_event {
+ u64 evt_time;
+ u64 conn_id;
+ char log[100];
+};
+
+int on_fst_trace_event(struct pt_regs* ctx) {
+ struct fst_trace_event evt = {};
+ evt.evt_time = bpf_ktime_get_ns();
+ bpf_usdt_readarg(1, ctx, &evt.conn_id);
+ bpf_usdt_readarg_p(2, ctx, &evt.log, sizeof(evt.log) - 1);
+ PREFIX_fst_trace_events.perf_submit(ctx, &evt, sizeof(evt));
+ return 0;
+}
+
+BPF_PERF_OUTPUT(PREFIX_stream_events);
+
+struct stream_event {
+ u64 evt_time;
+ u64 conn_id;
+ char name[20];
+ u64 stream_id;
+ u64 time_since_start;
+};
+
+int on_stream_event(struct pt_regs* ctx) {
+ struct stream_event evt = {};
+ evt.evt_time = bpf_ktime_get_ns();
+ bpf_usdt_readarg(1, ctx, &evt.conn_id);
+ bpf_usdt_readarg_p(2, ctx, &evt.name, sizeof(evt.name) - 1);
+ bpf_usdt_readarg(3, ctx, &evt.stream_id);
+ bpf_usdt_readarg(4, ctx, &evt.time_since_start);
+ PREFIX_stream_events.perf_submit(ctx, &evt, sizeof(evt));
+ return 0;
+}
+
+BPF_PERF_OUTPUT(PREFIX_pacing_updates);
+
+struct pacing_update_event {
+ u64 evt_time;
+ u64 conn_id;
+ u64 interval;
+ u64 burst;
+};
+
+int on_pacing_update(struct pt_regs* ctx) {
+ struct pacing_update_event evt = {};
+ evt.evt_time = bpf_ktime_get_ns();
+ bpf_usdt_readarg(1, ctx, &evt.conn_id);
+ bpf_usdt_readarg(2, ctx, &evt.interval);
+ bpf_usdt_readarg(3, ctx, &evt.burst);
+ PREFIX_pacing_updates.perf_submit(ctx, &evt, sizeof(evt));
+ return 0;
+}
+
+"""
+
+def randomword(length):
+ letters = string.ascii_lowercase
+ return ''.join(random.choice(letters) for i in range(length))
+
+randprefix = randomword(4)
+
+parser = argparse.ArgumentParser(
+ description="Trace quic events",
+ formatter_class=argparse.RawDescriptionHelpFormatter)
+parser.add_argument("pid", type=int, help="pid to attach to")
+args = parser.parse_args()
+
+usdt = USDT(pid=args.pid)
+usdt.enable_probe_or_bail("packet_acked", "on_packet_acked")
+usdt.enable_probe_or_bail("packet_sent", "on_packet_sent")
+usdt.enable_probe("packets_lost", "on_packets_lost")
+usdt.enable_probe("packet_recvd", "on_packet_recvd")
+usdt.enable_probe("rto_alarm", "on_rto_alarm")
+usdt.enable_probe("tlp_alarm", "on_tlp_alarm")
+usdt.enable_probe("handshake_alarm", "on_handshake_alarm")
+usdt.enable_probe("rto_verified", "on_rto_verified")
+#usdt.enable_probe("packet_clone", "on_packet_clone")
+usdt.enable_probe("packet_drop", "on_packet_drop")
+usdt.enable_probe("conn_close", "on_close")
+usdt.enable_probe("recvd_close", "on_recvd_close")
+usdt.enable_probe("cubic_ack", "on_cubic_ack")
+usdt.enable_probe("cubic_steady_cwnd", "on_cubic_steady_cwnd_changed")
+usdt.enable_probe("pacing_update", "on_pacing_update")
+try:
+ usdt.enable_probe("udp_recvd", "on_udp_recvd")
+ usdt.enable_probe("fst_trace", "on_fst_trace_event")
+ usdt.enable_probe("stream_event", "on_stream_event")
+except:
+ pass
+
+CFLAGS = [
+]
+
+replaced = bytes(program.replace('PREFIX', randprefix), 'utf-8')
+bpf = BPF(text=replaced, usdt_contexts=[usdt], cflags=CFLAGS)
+print("Tracing quic events in process %d ... Ctrl-C to quit." %
+ (args.pid))
+
+# not necessarily thread safe, but we just need a best effort
+# kind of thing
+running = True
+
+
+def sent_event(listener):
+ class PacketSentEvent(ct.Structure):
+ _fields_ = [
+ ("time", ct.c_ulonglong),
+ ("conn_id", ct.c_ulonglong),
+ ("packet_num", ct.c_ulonglong),
+ ("encoded_size", ct.c_ulonglong),
+ ("is_handshake", ct.c_int),
+ ("pure_ack", ct.c_int),
+ ]
+ def inner_call(cpu, data, size):
+ event = ct.cast(data, ct.POINTER(PacketSentEvent)).contents
+ listener.sent_event(event)
+ return inner_call
+
+
+def acked_event(listener):
+ class PacketAckedEvent(ct.Structure):
+ _fields_ = [
+ ("time", ct.c_ulonglong),
+ ("conn_id", ct.c_ulonglong),
+ ("packet_num", ct.c_ulonglong),
+ ]
+ def inner_call(cpu, data, size):
+ event = ct.cast(data, ct.POINTER(PacketAckedEvent)).contents
+ listener.acked_event(event)
+ return inner_call
+
+
+def lost_event(listener):
+ class PacketLostEvent(ct.Structure):
+ _fields_ = [
+ ("time", ct.c_ulonglong),
+ ("conn_id", ct.c_ulonglong),
+ ("largest_lost_packet_num", ct.c_ulonglong),
+ ("lost_bytes", ct.c_ulonglong),
+ ("lost_packets", ct.c_ulong),
+ ]
+ def inner_call(cpu, data, size):
+ event = ct.cast(data, ct.POINTER(PacketLostEvent)).contents
+ listener.lost_event(event)
+ return inner_call
+
+
+def recvd_event(listener):
+ class PacketRecvdEvent(ct.Structure):
+ _fields_ = [
+ ("time", ct.c_ulonglong),
+ ("conn_id", ct.c_ulonglong),
+ ("packet_num", ct.c_ulonglong),
+ ("size", ct.c_ulonglong),
+ ]
+ def inner_call(cpu, data, size):
+ event = ct.cast(data, ct.POINTER(PacketRecvdEvent)).contents
+ listener.recvd_event(event)
+ return inner_call
+
+
+def handshake_event(listener):
+ class HandshakeAlarmEvent(ct.Structure):
+ _fields_ = [
+ ("time", ct.c_ulonglong),
+ ("conn_id", ct.c_ulonglong),
+ ("largest_sent", ct.c_ulonglong),
+ ("handshake_count", ct.c_ulonglong),
+ ("outstanding_handshake_packets", ct.c_ulonglong),
+ ("outstanding_packets", ct.c_ulonglong),
+ ]
+ def inner_call(cpu, data, size):
+ event = ct.cast(data, ct.POINTER(HandshakeAlarmEvent)).contents
+ listener.handshake_alarm_event(event)
+ return inner_call
+
+
+def tlp_event(listener):
+ class TLPAlarmEvent(ct.Structure):
+ _fields_ = [
+ ("time", ct.c_ulonglong),
+ ("conn_id", ct.c_ulonglong),
+ ("largest_sent", ct.c_ulonglong),
+ ("tlp_count", ct.c_ulonglong),
+ ("outstanding_packets", ct.c_ulonglong),
+ ]
+ def inner_call(cpu, data, size):
+ event = ct.cast(data, ct.POINTER(TLPAlarmEvent)).contents
+ listener.tlp_alarm_event(event)
+ return inner_call
+
+
+def rto_event(listener):
+ class RTOAlarmEvent(ct.Structure):
+ _fields_ = [
+ ("time", ct.c_ulonglong),
+ ("conn_id", ct.c_ulonglong),
+ ("largest_sent", ct.c_ulonglong),
+ ("largest_sent_before_rto", ct.c_ulonglong),
+ ("rto_count", ct.c_ulonglong),
+ ("outstanding_packets", ct.c_ulonglong),
+ ]
+ def inner_call(cpu, data, size):
+ event = ct.cast(data, ct.POINTER(RTOAlarmEvent)).contents
+ listener.rto_alarm_event(event)
+ return inner_call
+
+
+def rto_verified_event(listener):
+ class RTOVerifiedEvent(ct.Structure):
+ _fields_ = [
+ ("time", ct.c_ulonglong),
+ ("conn_id", ct.c_ulonglong),
+ ("largest_acked_packet", ct.c_ulonglong),
+ ("largest_sent_before_rto", ct.c_ulonglong),
+ ("outstanding_packets", ct.c_ulonglong),
+ ]
+ def inner_call(cpu, data, size):
+ event = ct.cast(data, ct.POINTER(RTOVerifiedEvent)).contents
+ listener.rto_verified_event(event)
+ return inner_call
+
+
+def packet_clone_event(listener):
+ class PacketCloneEvent(ct.Structure):
+ _fields_ = [
+ ("time", ct.c_ulonglong),
+ ("conn_id", ct.c_ulonglong),
+ ("packet_num", ct.c_ulonglong),
+ ("cloned_packet_num", ct.c_ulonglong),
+ ("frames", ct.c_ulonglong),
+ ]
+ def inner_call(cpu, data, size):
+ event = ct.cast(data, ct.POINTER(PacketCloneEvent)).contents
+ listener.packet_clone_event(event)
+ return inner_call
+
+
+def packet_drop_event(listener):
+ class PacketDropEvent(ct.Structure):
+ _fields_ = [
+ ("time", ct.c_ulonglong),
+ ("conn_id", ct.c_ulonglong),
+ ("_reason", ct.c_char * 50),
+ ]
+ def inner_call(cpu, data, size):
+ event = ct.cast(data, ct.POINTER(PacketDropEvent)).contents
+ event.reason = event._reason.decode('utf-8')
+ listener.packet_drop_event(event)
+ return inner_call
+
+
+def udp_recvd_event(listener):
+ class UdpRecvdEvent(ct.Structure):
+ _fields_ = [
+ ("time", ct.c_ulonglong),
+ ("conn_id", ct.c_ulonglong),
+ ("len", ct.c_ulonglong),
+ ]
+ def inner_call(cpu, data, size):
+ event = ct.cast(data, ct.POINTER(UdpRecvdEvent)).contents
+ listener.udp_recvd_event(event)
+ return inner_call
+
+
+def close_event(listener):
+ class CloseEvent(ct.Structure):
+ _fields_ = [
+ ("time", ct.c_ulonglong),
+ ("conn_id", ct.c_ulonglong),
+ ("drain", ct.c_ulonglong),
+ ("send_close_immediate", ct.c_ulonglong),
+ ("_close_sent", ct.c_char * 100),
+ ("_peer_sent", ct.c_char * 100),
+ ]
+ def inner_call(cpu, data, size):
+ event = ct.cast(data, ct.POINTER(CloseEvent)).contents
+ event.close_sent = event._close_sent.decode('utf-8')
+ event.peer_sent = event._peer_sent.decode('utf-8')
+ listener.close_event(event)
+ return inner_call
+
+def recvd_close_event(listener):
+ class RecvdCloseEvent(ct.Structure):
+ _fields_ = [
+ ("time", ct.c_ulonglong),
+ ("conn_id", ct.c_ulonglong),
+ ("_recvd_close", ct.c_char * 100),
+ ]
+ def inner_call(cpu, data, size):
+ event = ct.cast(data, ct.POINTER(RecvdCloseEvent)).contents
+ event.recvd_close = event._recvd_close.decode('utf-8')
+ listener.recvd_close_event(event)
+ return inner_call
+
+
+def cubic_ack_event(listener):
+ class CubicAckEvent(ct.Structure):
+ _fields_ = [
+ ("time", ct.c_ulonglong),
+ ("conn_id", ct.c_ulonglong),
+ ("_state", ct.c_char * 10),
+ ("cwnd", ct.c_ulonglong),
+ ("inflight", ct.c_ulonglong),
+ ("last_max_cwnd", ct.c_ulonglong),
+ ]
+ def inner_call(cpu, data, size):
+ event = ct.cast(data, ct.POINTER(CubicAckEvent)).contents
+ event.state = event._state.decode('utf-8')
+ listener.cubic_ack_event(event)
+ return inner_call
+
+
+def cubic_steady_cwnd_event(listener):
+ class CubicSteadyCwndChangedEvent(ct.Structure):
+ _fields_ = [
+ ("time", ct.c_ulonglong),
+ ("conn_id", ct.c_ulonglong),
+ ("curr_cwnd", ct.c_ulonglong),
+ ("delta", ct.c_longlong),
+ ("time_to_origin", ct.c_ulonglong),
+ ("time_elapsed", ct.c_ulonglong),
+ ]
+ def inner_call(cpu, data, size):
+ event = ct.cast(data, ct.POINTER(CubicSteadyCwndChangedEvent)).contents
+ listener.cubic_steady_cwnd_event(event)
+ return inner_call
+
+
+def fst_trace_event(listener):
+ class FstTraceEvent(ct.Structure):
+ _fields_ = [
+ ("time", ct.c_ulonglong),
+ ("conn_id", ct.c_ulonglong),
+ ("_log", ct.c_char * 100),
+ ]
+ def inner_call(cpu, data, size):
+ event = ct.cast(data, ct.POINTER(FstTraceEvent)).contents
+ event.log = event._log.decode('utf-8')
+ listener.fst_trace_event(event)
+ return inner_call
+
+
+def stream_event(listener):
+ class StreamEvent(ct.Structure):
+ _fields_ = [
+ ("time", ct.c_ulonglong),
+ ("conn_id", ct.c_ulonglong),
+ ("_name", ct.c_char * 20),
+ ("stream_id", ct.c_ulonglong),
+ ("time_since_start", ct.c_ulonglong),
+ ]
+ def inner_call(cpu, data, size):
+ event = ct.cast(data, ct.POINTER(StreamEvent)).contents
+ event.name = event._name.decode('utf-8')
+ listener.stream_event(event)
+ return inner_call
+
+
+def pacing_update(listener):
+ class PacingUpdate(ct.Structure):
+ _fields_ = [
+ ("time", ct.c_ulonglong),
+ ("conn_id", ct.c_ulonglong),
+ ("interval", ct.c_ulonglong),
+ ("burst", ct.c_ulonglong),
+ ]
+ def inner_call(cpu, data, size):
+ event = ct.cast(data, ct.POINTER(PacingUpdate)).contents
+ listener.pacing_update(event)
+ return inner_call
+
+
+PAGE_COUNT=4096
+
+def start_listening(listener):
+ packets_sent = "%s_packets_sent" % randprefix
+ packets_acked = "%s_packets_acked" % randprefix
+ packets_lost = "%s_packets_lost" % randprefix
+ packets_recvd = "%s_packets_recvd" % randprefix
+ handshake_events = "%s_handshake_events" % randprefix
+ tlp_events = "%s_tlp_events" % randprefix
+ rto_events = "%s_rto_events" % randprefix
+ rto_verified_events = "%s_rto_verified_events" % randprefix
+ #packets_cloned = "%s_packets_cloned" % randprefix
+ packets_drop = "%s_packet_drop_events" % randprefix
+ udp_recvd = "%s_udp_recvd_events" % randprefix
+ conn_close = "%s_close_events" % randprefix
+ recvd_close = "%s_recvd_close_event" % randprefix
+ cubic_ack = "%s_cubic_ack_event" % randprefix
+ cubic_steady_cwnd = "%s_cubic_steady_cwnd_event" % randprefix
+ fst_trace = "%s_fst_trace_events" % randprefix
+ stream_trace_event = "%s_stream_events" % randprefix
+ pacing_update_event = "%s_pacing_updates" % randprefix
+
+ print("randprefix=%s" % randprefix)
+
+ bpf[packets_sent].open_perf_buffer(sent_event(listener),
+ page_cnt=PAGE_COUNT)
+ bpf[packets_acked].open_perf_buffer(acked_event(listener),
+ page_cnt=PAGE_COUNT)
+ bpf[packets_lost].open_perf_buffer(lost_event(listener),
+ page_cnt=PAGE_COUNT)
+ bpf[packets_recvd].open_perf_buffer(recvd_event(listener),
+ page_cnt=PAGE_COUNT)
+ bpf[handshake_events].open_perf_buffer(handshake_event(listener),
+ page_cnt=PAGE_COUNT)
+ bpf[tlp_events].open_perf_buffer(tlp_event(listener), page_cnt=PAGE_COUNT)
+ bpf[rto_events].open_perf_buffer(rto_event(listener), page_cnt=PAGE_COUNT)
+ bpf[rto_verified_events].open_perf_buffer(rto_verified_event(listener),
+ page_cnt=PAGE_COUNT)
+ #bpf[packets_cloned].open_perf_buffer(packet_clone_event(listener),
+ # page_cnt=PAGE_COUNT)
+ bpf[packets_drop].open_perf_buffer(packet_drop_event(listener),
+ page_cnt=PAGE_COUNT)
+ bpf[udp_recvd].open_perf_buffer(udp_recvd_event(listener),
+ page_cnt=PAGE_COUNT)
+ bpf[conn_close].open_perf_buffer(close_event(listener),
+ page_cnt=PAGE_COUNT)
+ bpf[recvd_close].open_perf_buffer(recvd_close_event(listener),
+ page_cnt=PAGE_COUNT)
+ bpf[cubic_ack].open_perf_buffer(cubic_ack_event(listener),
+ page_cnt=PAGE_COUNT)
+ bpf[cubic_steady_cwnd].open_perf_buffer(cubic_steady_cwnd_event(listener),
+ page_cnt=PAGE_COUNT)
+ bpf[fst_trace].open_perf_buffer(fst_trace_event(listener),
+ page_cnt=PAGE_COUNT)
+ bpf[stream_trace_event].open_perf_buffer(stream_event(listener),
+ page_cnt=PAGE_COUNT)
+ bpf[pacing_update_event].open_perf_buffer(pacing_update(listener),
+ page_cnt=PAGE_COUNT)
+ while running:
+ bpf.perf_buffer_poll()

diff:
+# Copyright (c) Facebook, Inc. and its affiliates.
+#
+# This source code is licensed under the MIT license found in the
+# LICENSE file in the root directory of this source tree.
+
+from __future__ import absolute_import, division, print_function, unicode_literals
+import mvfst.base as base
+import struct
+
+def conn_id_to_hex(conn_id):
+ return struct.pack('<Q', conn_id).hex()
+
+class PrintListener:
+ def sent_event(self, event):
+ print("sent time=%s, connid=%s, packet_num=%s, size=%s, is_handshake=%s, pure_ack=%s" %
+ (str(event.time),
+ conn_id_to_hex(event.conn_id),
+ str(event.packet_num), str(event.encoded_size),
+ str(event.is_handshake), str(event.pure_ack)))
+
+ def acked_event(self, event):
+ print("acked time=%s, connid=%s, packet_num=%s" % (str(event.time),
+ conn_id_to_hex(event.conn_id),
+ str(event.packet_num)))
+
+ def lost_event(self, event):
+ print("lost time=%s, connid=%s, largest_lost=%s, lost_bytes=%s, lost_packets=%s" %
+ (str(event.time),
+ conn_id_to_hex(event.conn_id),
+ str(event.largest_lost_packet_num), str(event.lost_bytes),
+ str(event.lost_packets)))
+
+ def recvd_event(self, event):
+ print("recvd time=%s, connid=%s, packet_num=%s, size=%s" %
+ (str(event.time),
+ conn_id_to_hex(event.conn_id),
+ str(event.packet_num),
+ str(event.size)))
+
+ def handshake_alarm_event(self, event):
+ print("handshake alarm time=%s, connid=%s, largest_sent=%s, "\
+ "handshake_count=%s, outstanding_handshake_packets=%s, "\
+ "outstanding_packets=%s" % (str(event.time), conn_id_to_hex(event.conn_id),
+ str(event.largest_sent), str(event.handshake_count),
+ str(event.outstanding_handshake_packets),
+ str(event.outstanding_packets)))
+
+ def tlp_alarm_event(self, event):
+ print("tlp alarm time=%s, connid=%s, largest_sent=%s, "\
+ "tlp_count=%s outstanding_packets=%s" %
+ (str(event.time), conn_id_to_hex(event.conn_id),
+ str(event.largest_sent), str(event.tlp_count),
+ str(event.outstanding_packets)))
+
+ def rto_alarm_event(self, event):
+ print("rto alarm time=%s, connid=%s, largest_sent=%s, "\
+ "largest_sent_before_rto=%s rto_count=%s outstanding_packets=%s" %
+ (str(event.time), conn_id_to_hex(event.conn_id),
+ str(event.largest_sent), str(event.largest_sent_before_rto),
+ str(event.rto_count),
+ str(event.outstanding_packets)))
+
+ def rto_verified_event(self, event):
+ print("rto verified time=%s, connid=%s, largest_acked_packet=%s, "\
+ "largest_sent_before_rto=%s, outstanding_packets=%s" %
+ (str(event.time), conn_id_to_hex(event.conn_id),
+ str(event.largest_acked_packet),
+ str(event.largest_sent_before_rto),
+ str(event.outstanding_packets)))
+
+ def packet_clone_event(self, event):
+ print("cloned time=%s, connid=%s, packet_num=%s cloned_packet_num=%s " \
+ "frames=%s" % (str(event.time),
+ conn_id_to_hex(event.conn_id),
+ str(event.packet_num),
+ str(event.cloned_packet_num),
+ str(event.frames)))
+
+ def packet_drop_event(self, event):
+ print("dropped time=%s, connid=%s, reason=%s" % (
+ str(event.time),
+ conn_id_to_hex(event.conn_id),
+ str(event.reason)))
+
+ def udp_recvd_event(self, event):
+ print("udp recv time=%s, connid=%s, len=%s" % (
+ str(event.time),
+ conn_id_to_hex(event.conn_id),
+ str(event.len)))
+
+ def close_event(self, event):
+ print("close time=%s, connid=%s, drain=%s, send_close_immediate=%s, sent=%s, peer=%s" % (
+ str(event.time),
+ conn_id_to_hex(event.conn_id),
+ str(event.drain),
+ str(event.send_close_immediate),
+ str(event.close_sent),
+ str(event.peer_sent)))
+
+ def recvd_close_event(self, event):
+ print("peer close time=%s, connid=%s, peer=%s" % (
+ str(event.time),
+ conn_id_to_hex(event.conn_id),
+ str(event.recvd_close)))
+
+ def cubic_ack_event(self, event):
+ print("cubic ack time=%s, connid=%s, state=%s, cwnd=%s, inflight=%s, last_max_cwnd=%s" % (
+ str(event.time),
+ conn_id_to_hex(event.conn_id),
+ str(event.state),
+ str(event.cwnd),
+ str(event.inflight),
+ str(event.last_max_cwnd)))
+
+ def cubic_steady_cwnd_event(self, event):
+ print("cubic steady cwnd time=%s, connid=%s, cur_cwnd=%s, delta=%s, time_to_origin=%sms, time_elapsed=%sms" % (
+ str(event.time),
+ conn_id_to_hex(event.conn_id),
+ str(event.curr_cwnd),
+ str(event.delta),
+ str(event.time_to_origin),
+ str(event.time_elapsed)))
+
+ def fst_trace_event(self, event):
+ print("trace time=%s, connid=%s, log=%s" % (
+ str(event.time),
+ conn_id_to_hex(event.conn_id),
+ str(event.log)))
+
+ def stream_event(self, event):
+ print("stream evt=%s time=%s, connid=%s, stream_id=%s, duration=%s" % (
+ str(event.name),
+ str(event.time),
+ conn_id_to_hex(event.conn_id),
+ str(event.stream_id),
+ str(event.time_since_start)))
+
+ def pacing_update(self, event):
+ print("pacing update=%s, connid=%s, interval=%s, burst=%s" % (
+ str(event.time),
+ conn_id_to_hex(event.conn_id),
+ str(event.interval),
+ str(event.burst)))
+
+
+if __name__ == "__main__":
+ base.start_listening(PrintListener())


diff:
@@ -962,7 +962,7 @@ TEST_F(AckHandlersTest, PureAckDoesNotUpdateRtt) {
auto regularPacket = createNewPacket(packetNum, PacketNumberSpace::AppData);
conn.outstandingPackets.emplace_back(OutstandingPacket(
std::move(regularPacket),
- Clock::now(),
+ Clock::now() - std::chrono::milliseconds(200),
111,
false /* handshake */,
true /* pureAck */,
@@ -970,16 +970,16 @@ TEST_F(AckHandlersTest, PureAckDoesNotUpdateRtt) {
conn.outstandingPureAckPacketsCount++;
ASSERT_FALSE(conn.outstandingPackets.empty());
ReadAckFrame ackFrame;
- ackFrame.largestAcked = 0;
+ ackFrame.largestAcked = packetNum;
ackFrame.ackDelay = std::chrono::microseconds(100);
- ackFrame.ackBlocks.emplace_back(0, 0);
+ ackFrame.ackBlocks.emplace_back(packetNum, packetNum);
processAckFrame(
conn,
PacketNumberSpace::AppData,
ackFrame,
[&](const auto&, const auto&, const auto&) {},
[&](auto&, auto&, bool, auto) {},
- Clock::now());
+ Clock::now() - std::chrono::milliseconds(150));
EXPECT_EQ(std::chrono::microseconds::max(), conn.lossState.mrtt);
EXPECT_EQ(std::chrono::microseconds::zero(), conn.lossState.srtt);
EXPECT_EQ(std::chrono::microseconds::zero(), conn.lossState.lrtt);
@@ -990,16 +990,16 @@ TEST_F(AckHandlersTest, PureAckDoesNotUpdateRtt) {
regularPacket = createNewPacket(packetNum, PacketNumberSpace::AppData);
conn.outstandingPackets.emplace_back(OutstandingPacket(
std::move(regularPacket),
- Clock::now(),
+ Clock::now() - std::chrono::milliseconds(100),
111,
false /* handshake */,
false /* pureAck */,
111));
ASSERT_FALSE(conn.outstandingPackets.empty());
- ackFrame.largestAcked = 1;
+ ackFrame.largestAcked = packetNum;
ackFrame.ackDelay = std::chrono::microseconds(100);
ackFrame.ackBlocks.clear();
- ackFrame.ackBlocks.emplace_back(1, 1);
+ ackFrame.ackBlocks.emplace_back(packetNum, packetNum);
processAckFrame(
conn,
PacketNumberSpace::AppData,

original_message:
Fix flaky quic AckHandler test

Summary:
You run it fast enough all these Clock::now() are just the same i
guess.

Reviewed By: siyengar

Differential Revision: D15081863

fbshipit-source-id: 2f1502ca97d20410db7b45e9be8a580f15e3c75f


diff:
-
-## Building
+![alt text](logo.png "MVFST")
+
+## Introduction
+`mvfst` is a client and server implementation of [IETF QUIC](https://tools.ietf.org/html/draft-ietf-quic-transport-20) protocol in C++ by Facebook. QUIC is a UDP based reliable, multiplexed transport protocol that will become an internet standard. The goal of `mvfst` is to build a performant implementation of the QUIC transport protocol that applications could adapt for use cases on both the internet and the data-center. `mvfst` has been tested at scale on android, iOS apps, as well as servers and has several features to support large scale deployments.
+
+## Features
+**Server features**:
+- Multi-threaded UDP socket server with a thread local architecture to be able to scale to multi-core servers
+- Customizable Connection-Id routing. The default Connection-Id routing implementation integrates seamlessly with [katran](https://github.com/facebookincubator/katran)
+- APIs to enable zero-downtime restarts of servers, so that applications do not have to drop connections when restarting.
+- APIs to expose transport and server statistics for debuggability
+- Zero-Rtt connection establishment and customizable zero rtt path validation
+- Support for UDP Generic segmentation offloading (GSO) for faster UDP writes.
+
+**Client features**:
+- Native happy eyeballs support between ipv4 and ipv6 so that applications do not need to implement it themselves
+- Pluggable congestion control and support for turning off congestion control to plug in application specific control algorithms
+- QUIC trace APIs to retrieve deep transport level stats.
+
+## Source Layout
+- `quic/api`: Defines API that applications can use to interact with the QUIC transport layer.
+- `quic/client`: Client transport implementation
+- `quic/server`: Server transport implementation
+- `quic/codec`: Read and write codec implementation for the protocol
+- `quic/common`: Implementation of common utility functions
+- `quic/congestion_control`: Implementation of different congestion control algorithms such as Cubic and Copa
+- `quic/flowcontrol`: Implementations of flowcontrol functions
+- `quic/handshake`: Implementations cryptographic handshake layer
+- `quic/loss`: Implementations of different loss recovery algotithms
+- `quic/logging`: Implementation of logging framework
+- `quic/happyeyeballs`: Implementation of mechanism to race IPV4 and IPV6 connection and pick a winner
+- `quic/state`: Defines and implements both connection and stream level state artifacts and state machines
+- `quic/tools`: Implementation of tools such as one to trace transport events within a connection
+- `quic/sample`: Example client and server
+
+
+## Dependencies
+
+`mvfst` largely depends on two libraries: [folly](https://www.github.com/facebook/folly) and [fizz](https://www.github.com/facebookincubator/fizz).
+
+## Building mvfst
### Ubuntu 16+
@@ -47,7 +86,6 @@ built libraries and binaries for `mvfst`.
You can also install `mvfst` as well as its dependencies `folly` and `fizz`
to a custom directory using the build script, by supplying an `INSTALL_PREFIX`
env var.
-
```
./build_helper.sh -i /usr/local
```
@@ -55,19 +93,34 @@ See `./build_helper.sh --help` for more options
You might need to run the script as root to install to certain directories.
+By default the build script `build_helper.sh` enables the building of test target (i.e. runs with `-DBUILD_TEST=ON` option). Since some of tests in `mvfst` require some test artifacts of Fizz, it is necessary to supply the path of the Fizz src directory (via option `DFIZZ_PROJECT`) to correctly build all test targets in `mvfst`.
+
+## Run a sample client and server
+Building the test targets of `mvfst` (or via `build_helper.sh`) should automatically build the sample client and server binaries as well. You can then spin a simple echo server by running:
+```
+./quic/samples/echo -mode=server -host=<ip> -port=<port>
+```
+and to run a client:
+```
+./quic/samples/echo -mode=client -host=<ip> -port=<port>
+```
+For more options, see
+```
+./quic/samples/echo --help
+```
## Contributing
-We'd love to have your help in making MVFST better. If you're interested, please
+We'd love to have your help in making `mvfst` better. If you're interested, please
read our guide to [guide to contributing](CONTRIBUTING.md)
## License
-MVFST is MIT licensed, as found in the LICENSE file.
+`mvfst` is MIT licensed, as found in the LICENSE file.
## Reporting and Fixing Security Issues
Please do not open GitHub issues or pull requests - this makes the problem
immediately visible to everyone, including malicious actors. Security issues in
-MVFST can be safely reported via Facebook's Whitehat Bug Bounty program:
+`mvfst` can be safely reported via Facebook's Whitehat Bug Bounty program:
https://www.facebook.com/whitehat

diff: Binary files /dev/null and b/logo.png differ

original_message:
add overview of MVFST and other info in README

Summary: Adds more info on README

Reviewed By: siyengar

Differential Revision: D15145263

fbshipit-source-id: 93fa6cb37250a08fd78577013d9eb9d20d74430b


diff:
*
*/
-#include <gflags/gflags.h>
#include <glog/logging.h>
+#include <fizz/crypto/Utils.h>
#include <folly/init/Init.h>
+#include <folly/portability/GFlags.h>
#include <quic/samples/echo/EchoClient.h>
#include <quic/samples/echo/EchoServer.h>
@@ -22,9 +23,14 @@ DEFINE_bool(pr, false, "Enable partially realible mode");
using namespace quic::samples;
int main(int argc, char* argv[]) {
+#if FOLLY_HAVE_LIBGFLAGS
+ // Enable glog logging to stderr by default.
+ gflags::SetCommandLineOptionWithMode(
+ "logtostderr", "1", gflags::SET_FLAGS_DEFAULT);
+#endif
gflags::ParseCommandLineFlags(&argc, &argv, false);
- google::InitGoogleLogging(argv[0]);
- folly::ssl::init();
+ folly::Init init(&argc, &argv);
+ fizz::CryptoUtils::init();
if (FLAGS_mode == "server") {
EchoServer server(FLAGS_port, FLAGS_pr);

original_message:
Init folly and set logtostderr in sample binary

Summary:
By default log messages aren't set to go to stderr
https://github.com/google/glog/blob/5c576f78c49b28d89b23fbb1fc80f54c879ec02e/src/glog/logging.h.in#L1476

Reviewed By: siyengar

Differential Revision: D15145787

fbshipit-source-id: b1de63d840e58cc5eb7fa91b84513cd09a1deeae


diff:
@@ -36,7 +36,7 @@ CodecResult QuicReadCodec::parseLongHeaderPacket(
// packet ends. Clear the queue since no other data in this packet is
// parse-able.
queue.clear();
- return folly::none;
+ return CodecResult(folly::none);
}
if (longHeaderInvariant->invariant.version ==
QuicVersion::VERSION_NEGOTIATION) {
@@ -116,7 +116,7 @@ CodecResult QuicReadCodec::parseLongHeaderPacket(
VLOG(4) << nodeToString(nodeType_)
<< " dropping initial packet for exceeding key timeout"
<< connIdToHex();
- return folly::none;
+ return CodecResult(folly::none);
}
}
headerCipher = initialHeaderCipher_.get();
@@ -133,7 +133,7 @@ CodecResult QuicReadCodec::parseLongHeaderPacket(
VLOG(4) << nodeToString(nodeType_)
<< " dropping zero rtt packet for exceeding key timeout"
<< connIdToHex();
- return folly::none;
+ return CodecResult(folly::none);
}
}
headerCipher = zeroRttHeaderCipher_.get();

original_message:
wrap folly::none with 'CodecResult' in ReadCodec

Summary: Fix for issue https://github.com/facebookincubator/mvfst/issues/1

Reviewed By: siyengar

Differential Revision: D15172405

fbshipit-source-id: 3e935ae42e445ae605b8e55e080ff7502bafaa83


message:
Require Boost 1.62 as a minimum version
Summary:
Fix for
The issue is fixed in
(1.62)

diff:
@@ -17,7 +17,7 @@ list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
set(QUIC_FBCODE_ROOT ${CMAKE_CURRENT_SOURCE_DIR})
# Dependencies
-find_package(Boost 1.58
+find_package(Boost 1.62
REQUIRED COMPONENTS
iostreams
system

original_message:
Require Boost 1.62 as a minimum version

Summary:
Fix for https://github.com/facebookincubator/mvfst/issues/1
The issue is fixed in
https://github.com/boostorg/variant/commit/b3650685f941a0c35cadfd878a185f274e132788
(1.62)

Reviewed By: yangchi

Differential Revision: D15182758

fbshipit-source-id: d6886a74fbf817dafa22494361f7f00d5a25af26


diff:
@@ -129,13 +129,10 @@ class MockConnectionCallback : public QuicSocket::ConnectionCallback {
class MockDeliveryCallback : public QuicSocket::DeliveryCallback {
public:
~MockDeliveryCallback() override = default;
- GMOCK_METHOD3_(
- ,
- ,
- ,
+ MOCK_METHOD3(
onDeliveryAck,
void(StreamId, uint64_t, std::chrono::microseconds));
- GMOCK_METHOD2_(, , , onCanceled, void(StreamId, size_t));
+ MOCK_METHOD2(onCanceled, void(StreamId, uint64_t));
};
class MockDataExpiredCallback : public QuicSocket::DataExpiredCallback {

diff:
@@ -161,7 +161,7 @@ class TransportClosingDeliveryCallback : public QuicSocket::DeliveryCallback {
}
}
- void onCanceled(StreamId, size_t) override {
+ void onCanceled(StreamId, uint64_t) override {
transport_->close(folly::none);
}
@@ -280,7 +280,7 @@ void verifyCorrectness(
const folly::IOBuf& expected,
bool finExpected = false,
bool writeAll = true) {
- size_t endOffset = 0;
+ uint64_t endOffset = 0;
size_t totalLen = 0;
bool finSet = false;
std::vector<uint64_t> offsets;

diff:
@@ -15,7 +15,6 @@ quic_add_test(TARGET QuicClientTransportTest
${LIBGMOCK_LIBRARIES}
mvfst_client
mvfst_codec_types
- mvfst_echohandler
mvfst_handshake
mvfst_server
mvfst_test_utils

diff:
@@ -7,28 +7,6 @@ if(NOT BUILD_TESTS)
return()
endif()
-add_library(mvfst_mock_codec STATIC
- Mocks.h
-)
-
-target_include_directories(
- mvfst_mock_codec PUBLIC
- $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
-)
-
-add_dependencies(
- mvfst_mock_codec
- mvfst_codec_pktbuilder
- mvfst_test_utils
-)
-
-target_link_libraries(
- mvfst_mock_codec PUBLIC
- Folly::folly
- mvfst_codec_pktbuilder
- mvfst_test_utils
-)
-
quic_add_test(TARGET QuicHeaderCodecTest
SOURCES
QuicHeaderCodecTest.cpp
@@ -60,7 +38,6 @@ quic_add_test(TARGET QuicWriteCodecTest
mvfst_codec_decode
mvfst_codec_types
mvfst_exception
- mvfst_mock_codec
mvfst_test_utils
${LIBGTEST_LIBRARY}
)
@@ -128,7 +105,6 @@ quic_add_test(TARGET QuicPacketBuilderTest
mvfst_codec_pktrebuilder
mvfst_codec_types
mvfst_handshake
- mvfst_mock_codec
mvfst_server
mvfst_state_functions
mvfst_state_machine

diff:
@@ -7,26 +7,6 @@ if(NOT BUILD_TESTS)
return()
endif()
-add_library(mvfst_cubic_test_utils STATIC
- TestingCubic.h
-)
-
-target_include_directories(
- mvfst_cubic_test_utils PUBLIC
- $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
-)
-
-add_dependencies(
- mvfst_cubic_test_utils
- mvfst_cc_algo
-)
-
-target_link_libraries(
- mvfst_cubic_test_utils PUBLIC
- Folly::folly
- mvfst_cc_algo
-)
-
quic_add_test(TARGET CongestionControllerTests
SOURCES
CongestionControlFunctionsTest.cpp
@@ -40,7 +20,6 @@ quic_add_test(TARGET CongestionControllerTests
DEPENDS
Folly::folly
mvfst_cc_algo
- mvfst_cubic_test_utils
mvfst_test_utils
${LIBGTEST_LIBRARY}
)

diff:
@@ -7,22 +7,6 @@ if(NOT BUILD_TESTS)
return()
endif()
-add_library(quic_mock_handshake STATIC
- Mocks.h
-)
-
-target_include_directories(
- quic_mock_handshake PUBLIC
- $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
-)
-
-target_link_libraries(
- quic_mock_handshake PUBLIC
- Folly::folly
- ${LIBGMOCK_LIBRARIES}
- ${LIBGTEST_LIBRARY}
-)
-
quic_add_test(TARGET TransportParametersTest
SOURCES
TransportParametersTest.cpp
@@ -40,7 +24,6 @@ quic_add_test(TARGET HandshakeLayerTest
Folly::folly
mvfst_codec_types
mvfst_handshake
- quic_mock_handshake
mvfst_test_utils
${LIBGTEST_LIBRARY}
)

diff:
@@ -7,42 +7,6 @@ if(NOT BUILD_TESTS)
return()
endif()
-add_library(
- mvfst_echohandler STATIC
- echo/EchoClient.h
- echo/EchoHandler.h
- echo/EchoServer.h
-)
-
-target_include_directories(
- mvfst_echohandler PUBLIC
- $<BUILD_INTERFACE:${QUIC_FBCODE_ROOT}>
- ${QUIC_EXTRA_INCLUDE_DIRECTORIES}
- $<INSTALL_INTERFACE:include/>
-)
-
-target_compile_options(
- mvfst_echohandler
- PRIVATE
- ${_QUIC_COMMON_COMPILE_OPTIONS}
-)
-
-target_link_libraries(
- mvfst_echohandler PUBLIC
- Folly::folly
- fizz::fizz
- mvfst_transport
- mvfst_client
- mvfst_test_utils
- mvfst_server
- ${LIBGTEST_LIBRARY}
-)
-
-install(
- TARGETS mvfst_echohandler
- DESTINATION lib
-)
-
file(
GLOB_RECURSE QUIC_API_HEADERS_TOINSTALL
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
@@ -55,9 +19,15 @@ foreach(header ${QUIC_API_HEADERS_TOINSTALL})
endforeach()
add_executable(echo echo/main.cpp)
+
+target_compile_options(
+ echo
+ PRIVATE
+ ${_QUIC_COMMON_COMPILE_OPTIONS}
+)
+
target_link_libraries(
echo PUBLIC
- mvfst_echohandler
mvfst_test_utils
${GFLAGS_LIBRARIES}
${LIBGMOCK_LIBRARIES}

diff:
@@ -81,7 +81,7 @@ class EchoClient : public quic::QuicSocket::ConnectionCallback,
void onStreamWriteReady(
quic::StreamId id,
- size_t maxToSend) noexcept override {
+ uint64_t maxToSend) noexcept override {
LOG(INFO) << "EchoClient socket is write ready with maxToSend="
<< maxToSend;
sendMessage(id, pendingOutput_[id]);

diff:
@@ -160,7 +160,7 @@ class EchoHandler : public quic::QuicSocket::ConnectionCallback,
void onStreamWriteReady(
quic::StreamId id,
- size_t maxToSend) noexcept override {
+ uint64_t maxToSend) noexcept override {
LOG(INFO) << "socket is write ready with maxToSend=" << maxToSend;
echo(id, input_[id]);
}

diff:
@@ -15,7 +15,7 @@ quic_add_test(TARGET QuicServerTest
Folly::folly
mvfst_codec
mvfst_codec_types
- mvfst_echohandler
+ mvfst_mock_socket
mvfst_server
mvfst_test_utils
mvfst_transport

original_message:
remove targets built from headers only (part II)

Summary:
Some versions of compilers, linkers and cmake doesn't support. Required to
support OSX build

Reviewed By: afrind

Differential Revision: D15204709

fbshipit-source-id: a9cbb5a59a0df0fa82838eb38a78a22e619db4ec


diff:
@@ -58,10 +58,15 @@ else()
endif()
list(APPEND
- _QUIC_COMMON_COMPILE_OPTIONS
+ _QUIC_BASE_COMPILE_OPTIONS
-std=c++14
-Wall
-Wextra
+)
+
+list(APPEND
+ _QUIC_COMMON_COMPILE_OPTIONS
+ ${_QUIC_BASE_COMPILE_OPTIONS}
# more strict options
-Werror=sign-compare
-Werror=bool-compare
@@ -70,16 +75,13 @@ list(APPEND
-Wnon-virtual-dtor
)
-include(QuicTest)
-
-add_subdirectory(quic)
-
if(BUILD_TESTS)
enable_testing()
- find_package(GTest REQUIRED)
- find_package(GMock REQUIRED)
+ include(QuicTest)
endif()
+add_subdirectory(quic)
+
install(
EXPORT mvfst-exports
FILE mvfst-targets.cmake

diff:
@@ -164,32 +164,6 @@ function setup_fizz() {
cd "$BWD" || exit
}
-function setup_googletest() {
- GTEST_DIR=$DEPS_DIR/googletest-release-1.8.0
- GTEST_BUILD_DIR=$GTEST_DIR/build
- # requires googletest-1.8
- if [ ! -d "$GTEST_DIR" ] ; then
- echo -e "${COLOR_GREEN}[ INFO ] Downloading gtest-1.8 ${COLOR_OFF}"
- TMP_DIR=$(mktemp -d)
- pushd .
- cd "$TMP_DIR"
- wget https://github.com/google/googletest/archive/release-1.8.0.zip -O "googletest.zip"
- unzip "googletest.zip" -d "$DEPS_DIR"
- popd
- fi
- echo -e "${COLOR_GREEN}Building Googletest ${COLOR_OFF}"
- mkdir -p "$GTEST_BUILD_DIR"
- cd "$GTEST_BUILD_DIR" || exit
- cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo \
- -DCMAKE_PREFIX_PATH="$GTEST_INSTALL_DIR" \
- -DCMAKE_INSTALL_PREFIX="$GTEST_INSTALL_DIR" \
- ..
- make -j "$(nproc)"
- make install
- echo -e "${COLOR_GREEN}Googletest is installed ${COLOR_OFF}"
- cd "$BWD" || exit
-}
-
function detect_platform() {
unameOut="$(uname -s)"
case "${unameOut}" in
@@ -201,7 +175,6 @@ function detect_platform() {
}
detect_platform
-setup_googletest
setup_folly
setup_fizz

diff:
include(CTest)
if(BUILD_TESTS)
include(GoogleTest)
- find_package(GMock MODULE REQUIRED)
+ find_package(GMock)
+ if(NOT LIBGMOCK_FOUND)
+ include(ExternalProject)
+
+ # Download and install GoogleMock
+ ExternalProject_Add(
+ googletest
+ GIT_REPOSITORY https://github.com/google/googletest.git
+ GIT_TAG release-1.8.0
+ PREFIX googletest
+ # Disable install step
+ INSTALL_COMMAND ""
+ LOG_DOWNLOAD ON
+ LOG_UPDATE 1
+ LOG_CONFIGURE ON
+ LOG_BUILD ON
+ LOG_TEST 1
+ LOG_INSTALL 1
+ CMAKE_CACHE_ARGS
+ -DCMAKE_BUILD_TYPE:STRING=Release
+ -DBUILD_GMOCK:BOOL=ON
+ -DBUILD_GTEST:BOOL=ON
+ -Dgtest_force_shared_crt:BOOL=OFF
+ )
+
+ ExternalProject_Get_Property(googletest source_dir)
+ set(GTEST_SOURCE_DIR ${source_dir})
+ ExternalProject_Get_Property(googletest binary_dir)
+ set(GTEST_BINARY_DIR ${binary_dir})
+
+ # Setup gtest / gmock libraries and include dirs
+ set(LIBGTEST_LIBRARIES
+ "${GTEST_BINARY_DIR}/${CMAKE_CFG_INTDIR}/googlemock/gtest/${CMAKE_STATIC_LIBRARY_PREFIX}gtest${CMAKE_STATIC_LIBRARY_SUFFIX}"
+ "${GTEST_BINARY_DIR}/${CMAKE_CFG_INTDIR}/googlemock/gtest/${CMAKE_STATIC_LIBRARY_PREFIX}gtest_main${CMAKE_STATIC_LIBRARY_SUFFIX}"
+)
+ set(LIBGMOCK_LIBRARIES
+ "${GTEST_BINARY_DIR}/${CMAKE_CFG_INTDIR}/googlemock/${CMAKE_STATIC_LIBRARY_PREFIX}gmock${CMAKE_STATIC_LIBRARY_SUFFIX}"
+ "${GTEST_BINARY_DIR}/${CMAKE_CFG_INTDIR}/googlemock/${CMAKE_STATIC_LIBRARY_PREFIX}gmock_main${CMAKE_STATIC_LIBRARY_SUFFIX}"
+)
+ set(LIBGMOCK_INCLUDE_DIR "${source_dir}/googlemock/include")
+ set(LIBGTEST_INCLUDE_DIR "${source_dir}/googletest/include")
+ endif()
endif()
function(quic_add_test)
@@ -32,9 +73,10 @@ function(quic_add_test)
# implementation of 'main()' that calls folly::init
"${QUIC_FBCODE_ROOT}/quic/common/test/TestMain.cpp"
)
+ add_dependencies(${QUIC_TEST_TARGET} googletest) # make sure googletest is built first
target_compile_options(
${QUIC_TEST_TARGET} PRIVATE
- ${_QUIC_COMMON_COMPILE_OPTIONS}
+ ${_QUIC_BASE_COMPILE_OPTIONS}
)
target_link_libraries(${QUIC_TEST_TARGET} PRIVATE
"${QUIC_TEST_DEPENDS}"
@@ -51,9 +93,11 @@ function(quic_add_test)
target_link_libraries(${QUIC_TEST_TARGET} PRIVATE
${LIBGMOCK_LIBRARIES}
+ ${LIBGTEST_LIBRARIES}
)
target_include_directories(${QUIC_TEST_TARGET} PRIVATE
${LIBGMOCK_INCLUDE_DIR}
+ ${LIBGTEST_INCLUDE_DIR}
${QUIC_EXTRA_INCLUDE_DIRECTORIES}
)
target_compile_definitions(${QUIC_TEST_TARGET} PRIVATE ${LIBGMOCK_DEFINES})

diff:
@@ -16,7 +16,6 @@ quic_add_test(TARGET QuicTransportTest
mvfst_server
mvfst_state_stream_functions
mvfst_test_utils
- ${LIBGTEST_LIBRARY}
)
quic_add_test(TARGET QuicTransportBaseTest
@@ -29,7 +28,6 @@ quic_add_test(TARGET QuicTransportBaseTest
mvfst_test_utils
mvfst_state_stream_functions
mvfst_server
- ${LIBGTEST_LIBRARY}
)
quic_add_test(TARGET QuicTransportFunctionsTest
@@ -40,7 +38,6 @@ quic_add_test(TARGET QuicTransportFunctionsTest
mvfst_transport
mvfst_test_utils
mvfst_server
- ${LIBGTEST_LIBRARY}
)
quic_add_test(TARGET QuicPacketSchedulerTest
@@ -53,7 +50,6 @@ quic_add_test(TARGET QuicPacketSchedulerTest
mvfst_transport
mvfst_test_utils
mvfst_server
- ${LIBGTEST_LIBRARY}
)
quic_add_test(TARGET IoBufQuicBatchTest

diff:
@@ -15,7 +15,6 @@ quic_add_test(TARGET QuicHeaderCodecTest
mvfst_exception
mvfst_codec
mvfst_test_utils
- ${LIBGTEST_LIBRARY}
)
quic_add_test(TARGET QuicReadCodecTest
@@ -26,7 +25,6 @@ quic_add_test(TARGET QuicReadCodecTest
mvfst_codec
mvfst_exception
mvfst_test_utils
- ${LIBGTEST_LIBRARY}
)
quic_add_test(TARGET QuicWriteCodecTest
@@ -39,7 +37,6 @@ quic_add_test(TARGET QuicWriteCodecTest
mvfst_codec_types
mvfst_exception
mvfst_test_utils
- ${LIBGTEST_LIBRARY}
)
quic_add_test(TARGET QuicTypesTest
@@ -51,7 +48,6 @@ quic_add_test(TARGET QuicTypesTest
mvfst_codec_types
mvfst_exception
mvfst_test_utils
- ${LIBGTEST_LIBRARY}
)
quic_add_test(TARGET PacketNumberTest
@@ -60,7 +56,6 @@ quic_add_test(TARGET PacketNumberTest
DEPENDS
Folly::folly
mvfst_codec_types
- ${LIBGTEST_LIBRARY}
)
quic_add_test(TARGET PacketNumberCipherTest
@@ -69,7 +64,6 @@ quic_add_test(TARGET PacketNumberCipherTest
DEPENDS
Folly::folly
mvfst_codec_packet_number_cipher
- ${LIBGTEST_LIBRARY}
)
quic_add_test(TARGET DecodeTest
@@ -82,7 +76,6 @@ quic_add_test(TARGET DecodeTest
mvfst_codec_types
mvfst_exception
mvfst_test_utils
- ${LIBGTEST_LIBRARY}
)
quic_add_test(TARGET QuicConnectionIdTest
@@ -91,7 +84,6 @@ quic_add_test(TARGET QuicConnectionIdTest
DEPENDS
Folly::folly
mvfst_codec_types
- ${LIBGTEST_LIBRARY}
)
quic_add_test(TARGET QuicPacketBuilderTest
@@ -110,7 +102,6 @@ quic_add_test(TARGET QuicPacketBuilderTest
mvfst_state_machine
mvfst_state_stream_functions
mvfst_test_utils
- ${LIBGTEST_LIBRARY}
)
@@ -121,5 +112,4 @@ quic_add_test(TARGET QuicIntegerTest
Folly::folly
mvfst_codec_types
mvfst_exception
- ${LIBGTEST_LIBRARY}
)

diff:
@@ -17,6 +17,8 @@ target_include_directories(
mvfst_test_utils PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
$<BUILD_INTERFACE:${FIZZ_PROJECT}>
+ ${LIBGMOCK_INCLUDE_DIR}
+ ${LIBGTEST_INCLUDE_DIR}
)
target_compile_options(
@@ -40,6 +42,8 @@ target_link_libraries(
mvfst_test_utils PUBLIC
Folly::folly
fizz::fizz
+ ${LIBGMOCK_LIBRARIES}
+ ${LIBGTEST_LIBRARIES}
mvfst_client
mvfst_codec_pktbuilder
mvfst_codec_types

diff:
@@ -21,5 +21,4 @@ quic_add_test(TARGET CongestionControllerTests
Folly::folly
mvfst_cc_algo
mvfst_test_utils
- ${LIBGTEST_LIBRARY}
)

diff:
@@ -15,5 +15,4 @@ quic_add_test(TARGET QuicFlowControlTest
mvfst_client
mvfst_flowcontrol
mvfst_test_utils
- ${LIBGTEST_LIBRARY}
)

diff:
@@ -14,7 +14,6 @@ quic_add_test(TARGET TransportParametersTest
Folly::folly
mvfst_handshake
mvfst_test_utils
- ${LIBGTEST_LIBRARY}
)
quic_add_test(TARGET HandshakeLayerTest
@@ -25,5 +24,4 @@ quic_add_test(TARGET HandshakeLayerTest
mvfst_codec_types
mvfst_handshake
mvfst_test_utils
- ${LIBGTEST_LIBRARY}
)

diff:
@@ -12,6 +12,5 @@ quic_add_test(TARGET MacroTest
QuicLoggingMacroTest.cpp
DEPENDS
Folly::folly
- ${LIBGTEST_LIBRARY}
mvfst_state_functions
)

diff:
@@ -18,5 +18,4 @@ quic_add_test(TARGET QuicLossFunctionsTest
mvfst_server
mvfst_test_utils
mvfst_transport
- ${LIBGTEST_LIBRARY}
)

diff:
@@ -31,5 +31,5 @@ target_link_libraries(
mvfst_test_utils
${GFLAGS_LIBRARIES}
${LIBGMOCK_LIBRARIES}
- ${LIBGTEST_LIBRARY}
+ ${LIBGTEST_LIBRARIES}
)

diff:
@@ -24,6 +24,4 @@ quic_add_test(TARGET ServerHandshakeTest
mvfst_server
mvfst_state_machine
mvfst_test_utils
- ${LIBGTEST_LIBRARY}
- ${LIBGTEST_LIBRARY}
)

diff:
@@ -18,7 +18,6 @@ quic_add_test(TARGET QuicServerTest
mvfst_server
mvfst_test_utils
mvfst_transport
- ${LIBGTEST_LIBRARY}
)
quic_add_test(TARGET QuicServerTransportTest
@@ -33,5 +32,4 @@ quic_add_test(TARGET QuicServerTransportTest
mvfst_state_stream_functions
mvfst_test_utils
mvfst_transport
- ${LIBGTEST_LIBRARY}
)

diff:
@@ -19,6 +19,4 @@ quic_add_test(TARGET StreamStateMachineTest
mvfst_state_stream_functions
mvfst_test_utils
mvfst_transport
- ${LIBGTEST_LIBRARIES}
- ${LIBGTEST_LIBRARY}
)

diff:
@@ -15,7 +15,6 @@ quic_add_test(TARGET StateMachineTest
Folly::folly
mvfst_state_machine
mvfst_test_utils
- ${LIBGTEST_LIBRARY}
)
quic_add_test(TARGET QuicStreamFunctionsTest
@@ -26,7 +25,6 @@ quic_add_test(TARGET QuicStreamFunctionsTest
mvfst_server
mvfst_state_stream_functions
mvfst_test_utils
- ${LIBGTEST_LIBRARY}
)
quic_add_test(TARGET AckHandlersTest
@@ -37,7 +35,6 @@ quic_add_test(TARGET AckHandlersTest
mvfst_state_machine
mvfst_state_ack_handler
mvfst_test_utils
- ${LIBGTEST_LIBRARY}
)
quic_add_test(TARGET QuicStateFunctionsTest
@@ -47,7 +44,6 @@ quic_add_test(TARGET QuicStateFunctionsTest
mvfst_server
mvfst_test_utils
mvfst_state_functions
- ${LIBGTEST_LIBRARY}
)
quic_add_test(TARGET QuicPacingFunctionsTest
@@ -55,7 +51,6 @@ quic_add_test(TARGET QuicPacingFunctionsTest
QuicPacingFunctionsTest.cpp
DEPENDS
mvfst_state_pacing_functions
- ${LIBGTEST_LIBRARY}
)
quic_add_test(TARGET QPRFunctionsTest
@@ -64,5 +59,4 @@ quic_add_test(TARGET QPRFunctionsTest
DEPENDS
mvfst_server
mvfst_state_qpr_functions
- ${LIBGTEST_LIBRARY}
)

original_message:
pull in appropriate googletest via cmake ExternalProject

Summary: Do not rely on downloading it via wget in `build_helper.sh`

Reviewed By: siyengar

Differential Revision: D15215226

fbshipit-source-id: aeef31b30964674d80346aa6a1480ce03fdf478d


diff:
include(CTest)
if(BUILD_TESTS)
include(GoogleTest)
- find_package(GMock)
- if(NOT LIBGMOCK_FOUND)
include(ExternalProject)
# Download and install GoogleMock
@@ -48,7 +46,6 @@ if(BUILD_TESTS)
set(LIBGMOCK_INCLUDE_DIR "${source_dir}/googlemock/include")
set(LIBGTEST_INCLUDE_DIR "${source_dir}/googletest/include")
endif()
-endif()
function(quic_add_test)
if(NOT BUILD_TESTS)

original_message:
always pull in googletest-1.8 as external project

Summary:
Relying on the default find for gtest / gmock (via LIBGMOCK_FOUND) is set to
true if another version of gmock is already installed and can be incompatible

Reviewed By: siyengar

Differential Revision: D15216828

fbshipit-source-id: 94d6e1a14914181842e34bd262b1a46c59155435