Quiche เป็นการดำเนินการตามโปรโตคอลการขนส่ง QUIC และ HTTP/3 ตามที่ระบุโดย IETF มันมี API ระดับต่ำสำหรับการประมวลผลแพ็คเก็ต quic และการจัดการสถานะการเชื่อมต่อ แอปพลิเคชันมีหน้าที่รับผิดชอบในการจัดหา I/O (เช่นการจัดการซ็อกเก็ต) รวมถึงลูปเหตุการณ์ที่มีการสนับสนุนสำหรับตัวจับเวลา
สำหรับข้อมูลเพิ่มเติมเกี่ยวกับวิธีการที่ควิชและข้อมูลเชิงลึกเกี่ยวกับการออกแบบคุณสามารถอ่านโพสต์ในบล็อกของ Cloudflare ที่มีรายละเอียดเพิ่มเติม
การสนับสนุน HTTP/3 ของ Quiche Powers เครือข่าย HTTP/3 เว็บไซต์ CloudFlare-Quic.com สามารถใช้สำหรับการทดสอบและการทดลอง
DNS Resolver ของ Android ใช้ quiche เพื่อใช้ DNS ผ่าน HTTP/3
Quiche สามารถรวมเข้ากับ Curl เพื่อให้การสนับสนุนสำหรับ HTTP/3
Quiche สามารถรวมเข้ากับ NGINX โดยใช้แพตช์ที่ไม่เป็นทางการเพื่อให้การสนับสนุนสำหรับ HTTP/3
ก่อนที่จะดำน้ำเข้าไปใน Quiche API นี่คือตัวอย่างบางส่วนเกี่ยวกับวิธีการใช้เครื่องมือ quiche ที่ให้ไว้เป็นส่วนหนึ่งของลัง quiche-Apps
หลังจากโคลนนิ่งโครงการตามคำสั่งที่กล่าวถึงในส่วนอาคารลูกค้าสามารถทำงานได้ดังนี้:
$ cargo run-bin quiche-client-https://cloudflare-quic.com/
ในขณะที่เซิร์ฟเวอร์สามารถทำงานได้ดังนี้:
$ cargo run-bin quiche-server--แอพ Cert/src/bin/cert.crt-Apps/src/bin/cert.key
(โปรดทราบว่าใบรับรองที่ให้ไว้นั้นลงนามด้วยตนเองและไม่ควรใช้ในการผลิต)
ใช้ธงบรรทัดคำสั่ง --help
เพื่อรับรายละเอียดเพิ่มเติมเกี่ยวกับตัวเลือกของเครื่องมือแต่ละตัว
ขั้นตอนแรกในการสร้างการเชื่อมต่อ quic โดยใช้ quiche กำลังสร้างวัตถุ Config
:
ปล่อยให้ mut config = quiche :: config :: new (quiche :: protocol_version)?; config.set_application_protos (& [b "ตัวอย่าง-proto"]); // การกำหนดค่าเพิ่มเติมเฉพาะสำหรับแอปพลิเคชันและกรณีใช้ ...
วัตถุ Config
ควบคุมแง่มุมที่สำคัญของการเชื่อมต่อ quic เช่นเวอร์ชัน QUIC, ID ALPN, การควบคุมการไหล, การควบคุมความแออัด, การหมดเวลาไม่ได้ใช้งานและคุณสมบัติหรือคุณสมบัติอื่น ๆ
QUIC เป็นโปรโตคอลการขนส่งวัตถุประสงค์ทั่วไปและมีคุณสมบัติการกำหนดค่าหลายอย่างที่ไม่มีค่าเริ่มต้นที่สมเหตุสมผล ตัวอย่างเช่นจำนวนสตรีมที่เกิดขึ้นพร้อมกันทุกประเภทนั้นขึ้นอยู่กับแอปพลิเคชันที่ทำงานผ่าน QUIC และข้อกังวลเฉพาะกรณีการใช้งานอื่น ๆ
Quiche เริ่มต้นคุณสมบัติหลายอย่างเป็นศูนย์แอปพลิเคชันน่าจะต้องตั้งค่าสิ่งเหล่านี้เป็นอย่างอื่นเพื่อตอบสนองความต้องการของพวกเขาโดยใช้สิ่งต่อไปนี้:
set_initial_max_streams_bidi()
set_initial_max_streams_uni()
set_initial_max_data()
set_initial_max_stream_data_bidi_local()
set_initial_max_stream_data_bidi_remote()
set_initial_max_stream_data_uni()
Config
ยังถือการกำหนดค่า TLS สิ่งนี้สามารถเปลี่ยนแปลงได้โดย mutators บนวัตถุที่มีอยู่หรือโดยการสร้างบริบท TLS ด้วยตนเองและสร้างการกำหนดค่าโดยใช้ with_boring_ssl_ctx_builder()
วัตถุการกำหนดค่าสามารถใช้ร่วมกันระหว่างการเชื่อมต่อหลายครั้ง
ในฝั่งไคลเอ็นต์ฟังก์ชั่นยูทิลิตี้ connect()
สามารถใช้เพื่อสร้างการเชื่อมต่อใหม่ในขณะที่ accept()
สำหรับเซิร์ฟเวอร์:
// การเชื่อมต่อไคลเอ็นต์ let conn = quiche :: เชื่อมต่อ (บาง (& server_name), & scid, local, peer, & mut config)?; // server connection.let conn = quiche :: accept (& scid, none, local, peer, peer, & mut config)?;
การใช้เมธอด recv()
การเชื่อมต่อแอปพลิเคชันสามารถประมวลผลแพ็กเก็ตที่เข้ามาซึ่งเป็นของการเชื่อมต่อนั้นจากเครือข่าย:
ให้ไปที่ = socket.local_addr (). unwrap (); loop {let (อ่าน, จาก) = socket.recv_from (& mut buf) .unwrap (); ให้ recv_info = quiche :: recvinfo {จาก, ถึง}; ให้อ่าน = ให้อ่าน = จับคู่ conn.recv (& mut buf [.. อ่าน], recv_info) {ตกลง (v) => v, err (e) => {// เกิดข้อผิดพลาด, จัดการกับมัน.},};}
แพ็คเก็ตขาออกถูกสร้างขึ้นโดยใช้วิธี send()
การเชื่อมต่อแทน:
ลูป {ปล่อยให้ (เขียน, send_info) = จับคู่ conn.send (& mut out) {ตกลง (v) => v, err (quiche :: error :: เสร็จแล้ว) => {// เสร็จสิ้นการเขียน. break;}, err ( e) => {// เกิดข้อผิดพลาดจัดการกับมัน break;},}; socket.send_to (& out [.. เขียน], & send_info.to) .unwrap ();}
เมื่อมีการส่งแพ็คเก็ตแอปพลิเคชันจะรับผิดชอบในการรักษาตัวจับเวลาเพื่อตอบสนองต่อเหตุการณ์การเชื่อมต่อตามเวลา การหมดอายุการจับเวลาสามารถรับได้โดยใช้วิธี timeout()
ปล่อยให้หมดเวลา = conn.timeout ();
แอปพลิเคชันมีหน้าที่รับผิดชอบในการจัดเตรียมการจับเวลาซึ่งอาจเฉพาะเจาะจงกับระบบปฏิบัติการหรือเฟรมเวิร์กเครือข่ายที่ใช้ เมื่อตัวจับเวลาหมดอายุควรมีการเรียกวิธีการเชื่อมต่อของ on_timeout()
หลังจากนั้นอาจต้องส่งแพ็กเก็ตเพิ่มเติมบนเครือข่าย:
// หมดเวลาหมดอายุจัดการ it.conn.on_timeout (); // ส่งแพ็กเก็ตเพิ่มเติมตามต้องการหลังหมดเวลา loop {let (เขียน, send_info) = match conn.send (& mut out) {ok (v) => v, err (quiche :: error :: done) => {// doing writing.break;}, err (e) => {// เกิดข้อผิดพลาด, จัดการ It.break;},}; socket.send_to (& out [.. เขียน], & send_info.to) .unwrap ();}
ขอแนะนำว่าแอปพลิเคชันจะส่งแพ็คเก็ตขาออกเพื่อหลีกเลี่ยงการสร้างการระเบิดของแพ็กเก็ตที่อาจทำให้เกิดความแออัดในระยะสั้นและการสูญเสียในเครือข่าย
Quiche เปิดเผยคำแนะนำการเว้นจังหวะสำหรับแพ็คเก็ตขาออกผ่านฟิลด์ [ at
] ของโครงสร้าง [ SendInfo
] ที่ส่งคืนโดยวิธี send()
ฟิลด์นี้แสดงถึงเวลาที่ควรส่งแพ็คเก็ตเฉพาะเข้าสู่เครือข่าย
แอปพลิเคชันสามารถใช้คำแนะนำเหล่านี้โดยการชะลอการส่งแพ็คเก็ตผ่านกลไกเฉพาะแพลตฟอร์ม (เช่นตัวเลือกซ็อกเก็ต SO_TXTIME
บน Linux) หรือวิธีการที่กำหนดเอง (เช่นโดยใช้ตัวจับเวลาพื้นที่ผู้ใช้)
หลังจากกลับไปกลับมาการเชื่อมต่อจะเสร็จสิ้นการจับมือกันและจะพร้อมสำหรับการส่งหรือรับข้อมูลแอปพลิเคชัน
ข้อมูลสามารถส่งบนสตรีมได้โดยใช้เมธอด stream_send()
:
หาก conn.is_estervished () {// handshake เสร็จสมบูรณ์ให้ส่งข้อมูลบางอย่างเกี่ยวกับสตรีม 0.conn.stream_send (0, b "สวัสดี", จริง)?;}
แอปพลิเคชันสามารถตรวจสอบว่ามีสตรีมที่อ่านได้หรือไม่โดยใช้วิธีการ readable()
ของการเชื่อมต่อซึ่งส่งคืนตัววนซ้ำผ่านสตรีมทั้งหมดที่มีข้อมูลที่โดดเด่นในการอ่าน
สามารถใช้เมธอด stream_recv()
เพื่อดึงข้อมูลแอปพลิเคชันจากสตรีมที่อ่านได้:
ถ้า conn.is_established () {// iterate readable streams.for stream_id ใน conn.readable () {// สตรีมสามารถอ่านได้อ่านจนกว่าจะไม่มีข้อมูลเพิ่มเติมในขณะที่ให้ตกลง ((อ่าน, fin)) = conn.stream_recv (stream_id, & mut buf) {println! ("Got {} bytes บน stream {}", read, stream_id);}}}
โมดูล Quiche HTTP/3 ให้ API ระดับสูงสำหรับการส่งและรับคำขอ HTTP และการตอบสนองที่ด้านบนของโปรโตคอลการขนส่ง QUIC
ดูไดเรกทอรี [quiche/ตัวอย่าง/] สำหรับตัวอย่างที่สมบูรณ์เพิ่มเติมเกี่ยวกับวิธีการใช้ quiche API รวมถึงตัวอย่างเกี่ยวกับวิธีการใช้ quiche ในแอปพลิเคชัน C/C ++ (ดูข้อมูลเพิ่มเติมด้านล่าง)
Quiche เปิดเผย C บาง ๆ C ที่ด้านบนของ Rust API ที่สามารถใช้เพื่อรวม quiche เข้ากับแอปพลิเคชัน C/C ++ ได้ง่ายขึ้น (เช่นเดียวกับในภาษาอื่น ๆ ที่อนุญาตให้โทร C APIs ผ่าน FFI บางรูปแบบ) C API เป็นไปตามการออกแบบที่เหมือนกันของ Rust One, Modulo ข้อ จำกัด ที่กำหนดโดยภาษา C เอง
เมื่อเรียกใช้ cargo build
ห้องสมุดคงที่ที่เรียกว่า libquiche.a
จะถูกสร้างขึ้นโดยอัตโนมัติพร้อมกับสนิม นี่เป็นแบบสแตนด์อโลนอย่างสมบูรณ์และสามารถเชื่อมโยงโดยตรงกับแอปพลิเคชัน C/C ++
โปรดทราบว่าเพื่อเปิดใช้งาน FFI API คุณลักษณะ ffi
จะต้องเปิดใช้งาน (ถูกปิดใช้งานโดยค่าเริ่มต้น) โดยผ่าน --features ffi
ไปยัง cargo
Quiche ต้องการสนิม 1.67 หรือใหม่กว่าในการสร้าง การปล่อยสนิมที่มีเสถียรภาพล่าสุดสามารถติดตั้งได้โดยใช้ Rustup
เมื่อตั้งค่าสภาพแวดล้อมการสร้างสนิมแล้วซอร์สโค้ด quiche สามารถดึงข้อมูลได้โดยใช้ Git:
$ git clone -recursive https://github.com/cloudflare/quiche
จากนั้นสร้างขึ้นโดยใช้สินค้า:
$ cargo build -ตัวอย่าง
สินค้าสามารถใช้ในการเรียกใช้การทดสอบ:
การทดสอบสินค้า $
โปรดทราบว่า Boringssl ซึ่งใช้ในการใช้งานการเข้ารหัสการเข้ารหัสของ Quic ตาม TLS จะต้องสร้างและเชื่อมโยงกับ Quiche สิ่งนี้จะทำโดยอัตโนมัติเมื่อสร้าง Quiche โดยใช้สินค้า แต่ต้องใช้คำสั่ง cmake
ในระหว่างกระบวนการสร้าง บน Windows คุณต้องใช้ NASM ด้วย เอกสาร Boringssl อย่างเป็นทางการมีรายละเอียดเพิ่มเติม
ในทางเลือกคุณสามารถใช้งานสร้าง Boringssl ที่กำหนดเองของคุณเองโดยการกำหนดค่าไดเรกทอรี BoringsSL ด้วยตัวแปรสภาพแวดล้อม QUICHE_BSSL_PATH
: ตัวแปร:
$ quiche_bssl_path = "/path/to/boringssl" การสร้างสินค้า -ตัวอย่าง
หรือคุณสามารถใช้ openssl/quictls เพื่อให้ quiche ใช้ผู้ขายรายนี้คุณลักษณะ openssl
สามารถเพิ่มลงในรายการ --feature
โปรดทราบว่าไม่รองรับ 0-RTT
หากใช้ผู้ขายรายนี้
การสร้าง Quiche สำหรับ Android (NDK เวอร์ชัน 19 หรือสูงกว่า 21 แนะนำ) สามารถทำได้โดยใช้ Cargo-NDK (v2.0 หรือใหม่กว่า)
ก่อนอื่นต้องติดตั้ง Android NDK ไม่ว่าจะใช้ Android Studio หรือโดยตรงและตัวแปรสภาพแวดล้อม ANDROID_NDK_HOME
จำเป็นต้องตั้งค่าเป็นเส้นทางการติดตั้ง NDK เช่น:
$ ส่งออก Android_ndk_home =/usr/local/share/Android-ndk
จากนั้นเครื่องมือ Rust Toolchain สำหรับสถาปัตยกรรม Android ที่จำเป็นสามารถติดตั้งได้ดังนี้:
$ Rustup เป้าหมายเพิ่ม Aarch64-Linux-Android Armv7-Linux-Androideabi i686-Linux-Android x86_64-Linux-Android
โปรดทราบว่าระดับ API ขั้นต่ำคือ 21 สำหรับสถาปัตยกรรมเป้าหมายทั้งหมด
ต้องติดตั้ง Cargo-NDK (v2.0 หรือใหม่กว่า) ด้วย:
$ cargo ติดตั้ง cargo-ndk
ในที่สุดห้องสมุด Quiche สามารถสร้างได้โดยใช้ขั้นตอนต่อไปนี้ โปรดทราบว่าตัวเลือก -t <architecture>
และ -p <NDK version>
เป็นตัวเลือก
$ cargo ndk -t arm64 -v8a -p 21 -build -คุณสมบัติ ffi
ดู build_android_ndk19.sh สำหรับข้อมูลเพิ่มเติม
ในการสร้าง quiche สำหรับ iOS คุณต้องมีสิ่งต่อไปนี้:
ติดตั้งเครื่องมือบรรทัดคำสั่ง xcode คุณสามารถติดตั้งด้วย xcode หรือด้วยคำสั่งต่อไปนี้:
$ xcode-select-install
ติดตั้ง Rust Toolchain สำหรับสถาปัตยกรรม iOS:
$ Rustup เป้าหมายเพิ่ม Aarch64-Apple-Eios x86_64-Apple-osi
ติดตั้ง cargo-lipo
:
$ cargo ติดตั้งค่าขนส่งสินค้า Lipo
ในการสร้าง libquiche ให้เรียกใช้คำสั่งต่อไปนี้:
$ cargo lipo -คุณสมบัติ ffi
หรือ
$ cargo lipo -คุณสมบัติ ffi -รีลีส
iOS build ได้รับการทดสอบใน XCODE 10.1 และ XCODE 11.2
ในการสร้างภาพนักเทียบท่าเพียงเรียกใช้คำสั่งต่อไปนี้:
$ สร้าง Docker-Build
คุณสามารถค้นหาภาพ Quiche Docker บนที่เก็บ Hub Docker Hub ต่อไปนี้:
Cloudflare/quiche
Cloudflare/quiche-qns
แท็ก latest
จะได้รับการอัปเดตเมื่อมีการอัปเดตสาขา Quiche Master
Cloudflare/quiche
จัดเตรียมเซิร์ฟเวอร์และไคลเอนต์ที่ติดตั้งใน/usr/local/bin
Cloudflare/quiche-qns
ให้สคริปต์เพื่อทดสอบ quiche ภายใน quic-interop-runner
ลิขสิทธิ์ (C) 2018-2019, CloudFlare, Inc.
ดูการคัดลอกใบอนุญาต