/naquid

WIP: quic but not spdy. fully customizable, performant QUIC client/server library with C linkage

Primary LanguageC++

status

  • now basic client/server communication done. more test for ensure stability and performance improvement is required

build

# meta-builder/builder only required for first build or tools/builder/Dockerfile changes
$ make meta-builder builder 
# it may stalled for 1st run, quit and rerun test in that case
$ make test

tasks for 0.1.0

  • rpc: reduce frame number (unify length header/msgid/type to one frame)
  • rpc: add header byte to indicate msgid/type size
  • conn: client side proof verification (import ProofVerifierChromium)
  • conn: study is there a way to send stream name without sending it over wire (cmsghdr can do this somehow?)
    • seems cannot, we stick to send stream kind over stream for a while.
  • conn: changing to batch send by default, with preparing new API to flush batch buffer
  • conn: make user able to read property of NqSession::Delegate via nq_conn_t from all thread
  • conn: check [1122/035845.066728:WARNING:rtt_stats.cc(44)] Ignoring measured send_delta log is valid
  • conn: enable MMSG_MORE for linux
  • conn: loop up ip address by using c-ares
  • conn: able to use custom dns
  • conn: handle connectivity change (if not handled)
  • stream: nq_[stream|rpc]_task to access its internal property (name/ctx) safely. because these property does not assure to be access from other thread.
  • API: use direct pointer to access conn/stream
  • API: consider the good way to integrate nq_error_t and user defined error code, as the value of nq_result_t of nq_rpc_reply.
  • API: more API to thread safe
  • API: delegate chromium log output to our callback (now LogMessage output logs by itself)
  • API: more detail control of rpc timeout (we providing nq_rpc_call_ex)
  • API: raw connection (do not use stream name to select stream protocol to be used)
  • API: nq_(conn|rpc|stream)_is_valid returns optional error detail msg
  • API: actually obsolute APIs which are decided to obsolute (hide header declaration)
  • API: ack callback for nq_stream_send
  • API: provide different type for each closure (now unified as nq_closure_t)
  • server: QuicAlarm should be more efficient
    • maybe better to more generalize NqLoop's alarm system and enable to directly call delegate object
  • server: graceful shutdown
    • stop accepting connection and wait until all request in the worker queue consumed
  • test: high frequent reconnection test
  • test: server side stream initiation
  • test: stream disconnection using on open callback
  • test: client conn reconnection or finalization using on open callback
  • test: stream handle send/recv test
  • test: timeout test for handshake / rpc call
  • test: ensure robustness for connectivity change
  • test: server long run test (more than a day) and check memory and fd leak
  • test: travis or something (introduce auto test execution)
  • bench: higher concurrency test (around 10k client connection)
  • bench: ensure scalability with number of thread (need to find proper workload)
  • bench: comparing latency and throughput with mrs, which contains ENet based gaming specific udp network library
    • throughput ~10% faster than mrs, with 100ccu/5000 request (roughly 350k req/sec) almost batched (mrs does not allow 100+ ccu, so more comparision is not possible)

tasks for 1.0.0

  • stream/rpc: unreliable packet sending (based on https://tools.ietf.org/html/draft-tiesel-quic-unreliable-streams-00)
  • stream/rpc: support tcp transport for QUIC fallback and internal datacenter usage
  • API: http2 plugin (nqh2): extra library to make nq_client_t http2 compatible (nq_httpize(nq_client_t))
  • API: grpc support: because some important backend services (eg. google cloud services or cockroachDB) expose API via grpc
  • conn: optional faster network stack by by-passing kernel (like dpdk)

YAGNI

  • stream/rpc: unencrypted packet sending ()
  • conn: more cert check. eg. optinally enable certificate transparency verification
    • maybe better just expose certificate data to user
  • conn: try to use let's encrypt cert (with corresponding host name) by default

WIP: docs

  • connection establishment
    • unified rule: connection is only active between first open callback and close callback. but object life cycle is a bit different.
      • mainly because of the nature of mobile connection, that is, greedy reconnection is required to keep MMO-ish connectivity to the server.
    • connection object life cycle
      • client: active
        • client connection object retained over reconnection. so its possible client connection object alive but connection is not active (eg. during reconnection wait)
      • server: passive
        • server connection object is the exactly same life cycle with connection itself
        • disconnect == every resouce related with the connection is deleted.
      • caution about connection close (public reset) for multi-threading server
        • because packet order may not keep between client and server, its possible that connection close frame "overtake" unreceived stream frame.
        • we cannot assure that all sent stream frame received before trailing close frame.
        • if some packet "must" received before closing connection, need to confirm with reply (nq_rpc_t) or stream ack (nq_stream_t).
  • stream type
    • rpc
    • stream
    • raw stream
  • stream establishment
    • client
    • server
  • thread safety
  • setup
    • create cert if you don't have the one
      • run ./tools/certs/generate_certs.sh with modifying leaf.cnf. test.qrpc.io can be used by default