一. 哈希表

定义文件路径:quic_hashtable.h
QUIC_STREAM_SET哈希表指针:CXPLAT_HASHTABLE* StreamTable;
QUIC_STREAM定义元素:CXPLAT_HASHTABLE_ENTRY TableEntry;

1. initialize

  1. if (StreamSet->StreamTable == NULL) {
  2. //
  3. // Lazily initialize the hash table.
  4. //
  5. if (!CxPlatHashtableInitialize(&StreamSet->StreamTable, CXPLAT_HASH_MIN_SIZE)) {
  6. QuicTraceEvent(
  7. AllocFailure,
  8. "Allocation of '%s' failed. (%llu bytes)",
  9. "streamset hash table",
  10. 0);
  11. return FALSE;
  12. }
  13. }

2. uninitialize

  1. if (StreamSet->StreamTable != NULL) {
  2. CxPlatHashtableUninitialize(StreamSet->StreamTable);
  3. }

3. insert

  1. CxPlatHashtableInsert(StreamSet->StreamTable, &Stream->TableEntry, (uint32_t)Stream->ID, NULL);

4. remove

  1. CxPlatHashtableRemove(StreamSet->StreamTable, &Stream->TableEntry, NULL);

5. lookup

  1. if (StreamSet->StreamTable == NULL) {
  2. return NULL; // No streams have been created yet.
  3. }
  4. CXPLAT_HASHTABLE_LOOKUP_CONTEXT Context;
  5. CXPLAT_HASHTABLE_ENTRY* Entry =
  6. CxPlatHashtableLookup(StreamSet->StreamTable, (uint32_t)ID, &Context);
  7. while (Entry != NULL) {
  8. QUIC_STREAM* Stream =
  9. CXPLAT_CONTAINING_RECORD(Entry, QUIC_STREAM, TableEntry);
  10. if (Stream->ID == ID) {
  11. return Stream;
  12. }
  13. Entry = CxPlatHashtableLookupNext(StreamSet->StreamTable, &Context);
  14. }
  15. return NULL;

6. for_each

  1. if (StreamSet->StreamTable == NULL) {
  2. return; // No streams have been created yet.
  3. }
  4. CXPLAT_HASHTABLE_ENUMERATOR Enumerator;
  5. CXPLAT_HASHTABLE_ENTRY* Entry;
  6. CxPlatHashtableEnumerateBegin(StreamSet->StreamTable, &Enumerator);
  7. while ((Entry = CxPlatHashtableEnumerateNext(StreamSet->StreamTable, &Enumerator)) != NULL) {
  8. QuicStreamTraceRundown(
  9. CXPLAT_CONTAINING_RECORD(Entry, QUIC_STREAM, TableEntry));
  10. }
  11. CxPlatHashtableEnumerateEnd(StreamSet->StreamTable, &Enumerator);

二. 链表

定义文件路径:quic_platform.h
QUIC_SEND定义链表:CXPLAT_LIST_ENTRY SendStreams;
QUIC_STREAM元素指针:CXPLAT_LIST_ENTRY SendLink;

1. insert/for

  1. CxPlatListInsertTail(&Connection->DestCids, &Path->DestCid->Link);
  2. for (CXPLAT_LIST_ENTRY* Entry = Connection->DestCids.Flink;
  3. Entry != &Connection->DestCids;
  4. Entry = Entry->Flink) {
  5. const QUIC_CID_LIST_ENTRY* DestCid =
  6. CXPLAT_CONTAINING_RECORD(
  7. Entry,
  8. QUIC_CID_LIST_ENTRY,
  9. Link);
  10. UNREFERENCED_PARAMETER(DestCid);
  11. QuicTraceEvent(
  12. ConnDestCidAdded,
  13. "[conn][%p] (SeqNum=%llu) New Destination CID: %!CID!",
  14. Connection,
  15. DestCid->CID.SequenceNumber,
  16. CASTED_CLOG_BYTEARRAY(DestCid->CID.Length, DestCid->CID.Data));
  17. }
  1. CXPLAT_DBG_ASSERT(Stream->SendLink.Flink == NULL);
  2. CXPLAT_LIST_ENTRY* Entry = Send->SendStreams.Blink;
  3. while (Entry != &Send->SendStreams) {
  4. //
  5. // Search back to front for the right place (based on priority) to
  6. // insert the stream.
  7. //
  8. if (Stream->SendPriority <=
  9. CXPLAT_CONTAINING_RECORD(Entry, QUIC_STREAM, SendLink)->SendPriority) {
  10. break;
  11. }
  12. Entry = Entry->Blink;
  13. }
  14. CxPlatListInsertHead(Entry, &Stream->SendLink); // Insert after current Entry

2. remove

  1. CxPlatListEntryRemove(&Stream->SendLink);
  2. Stream->SendLink.Flink = NULL;
  3. QuicStreamRelease(Stream, QUIC_STREAM_REF_SEND);
  4. Stream = NULL;

三. 锁

定义文件路径:quic_platform_posix.h (实际实现是pthread_mutex_t)
QUIC_LIBRARY链表指针:CXPLAT_LOCK Lock;

  1. 1. init
  2. CxPlatLockInitialize(&MsQuicLib.Lock);
  3. 2. uninit
  4. CxPlatLockUninitialize(&MsQuicLib.Lock);
  5. 3. lock
  6. CxPlatLockAcquire(&MsQuicLib.Lock);
  7. 4. unlock
  8. CxPlatLockRelease(&MsQuicLib.Lock);

四. 线程

  1. # 当前线程 (9993423)
  2. CXPLAT_THREAD_ID ThreadID = CxPlatCurThreadID();
  3. # 线程索引 (0、1、2、3)
  4. uint32_t CurProcIndex = CxPlatProcCurrentNumber();
  5. 实现方式:
  6. (uint32_t)sched_getcpu() % CxPlatProcessorCount;
  7. # 所有worker线程数 (cpu核心数)
  8. MsQuicLib.ProcessorCount = (uint16_t)CxPlatProcActiveCount();
  9. MsQuicLib.ProcessorCount = (uint16_t)sysconf(_SC_NPROCESSORS_ONLN);

五. 时间

  1. # 毫秒ms
  2. int64_t Now = CxPlatTimeEpochMs64();

六. 内存池

  • 接口

定义文件路径:quic_platform_posix.h
QUIC_WORKER指针:CXPLAT_POOL StreamPool;

  1. 1. init
  2. inline
  3. void
  4. CxPlatPoolInitialize(
  5. _In_ BOOLEAN IsPaged,
  6. _In_ uint32_t Size,
  7. _In_ uint32_t Tag,
  8. _Inout_ CXPLAT_POOL* Pool
  9. )
  10. #define QUIC_POOL_STREAM '30cQ' // Qc03 - QUIC stream
  11. CxPlatPoolInitialize(FALSE, sizeof(QUIC_STREAM), QUIC_POOL_STREAM, &Worker->StreamPool);
  12. 2. uninit
  13. CxPlatPoolUninitialize(&Worker->StreamPool);
  14. 3. alloc
  15. Stream = CxPlatPoolAlloc(&Worker->StreamPool);
  16. if (Stream == NULL) {
  17. Status = QUIC_STATUS_OUT_OF_MEMORY;
  18. goto Exit;
  19. }
  20. CxPlatZeroMemory(Stream, sizeof(QUIC_STREAM));
  21. 4. free
  22. CxPlatPoolFree(&Worker->StreamPool, Stream);
  • 示例 ```c

    从ConnectionPool中获取conn

    QuicConnAlloc QuicConnFree

从StreamPool中获取stream

QuicStreamInitialize QuicStreamFree

  1. <a name="semW4"></a>
  2. # 七. 引用计数
  3. 定义文件路径:quic_platform_posix.h<br />QUIC_STREAM定义:CXPLAT_REF_COUNT RefCount;
  4. ```c
  5. # init
  6. Stream->RefCount = 1;
  7. CxPlatRefInitialize(&Stream->RefCount);
  8. # uninit
  9. CxPlatRefUninitialize(&Stream->RefCount);
  10. # inc
  11. CxPlatRefIncrement(&Stream->RefCount);
  12. # dec
  13. if (CxPlatRefDecrement(&Stream->RefCount)) {
  14. QuicStreamFree(Stream);
  15. return TRUE;
  16. }
  17. return FALSE;

八. 随机数

  1. CxPlatRandom(sizeof(uint32_t), &Binding->RandomReservedVersion);

九. 宏定义

在frame.h、connection.c(QuicErrorCodeToStatus)、msquic_posix.h、/usr/include/asm-generic/error.h

十. 信号

定义文件路径:quic_platform_posix.h,实现是 pthread_cond_wait 和 pthread_cond_broadcast

  1. #define CxPlatEventWaitForever(Event) CxPlatInternalEventWaitForever(&Event)
  2. #define CxPlatEventSet(Event) CxPlatInternalEventSet(&Event)