Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

External Execution Interface #4616

Draft
wants to merge 16 commits into
base: main
Choose a base branch
from
25 changes: 25 additions & 0 deletions src/cs/lib/msquic_generated.cs
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,22 @@ internal unsafe partial struct QUIC_EXECUTION_CONFIG
internal fixed ushort ProcessorList[1];
}

internal unsafe partial struct QUIC_EXECUTION_CONTEXT_CONFIG
{
[NativeTypeName("uint32_t")]
internal uint IdealProcessor;

[NativeTypeName("uint32_t")]
internal uint PollingIdleTimeoutUs;

[NativeTypeName("QUIC_EVENTQ *")]
internal void** EventQ;
}

internal partial struct QUIC_EXECUTION_CONTEXT
{
}

internal unsafe partial struct QUIC_REGISTRATION_CONFIG
{
[NativeTypeName("const char *")]
Expand Down Expand Up @@ -3250,6 +3266,15 @@ internal unsafe partial struct QUIC_API_TABLE

[NativeTypeName("QUIC_CONNECTION_COMP_CERT_FN")]
internal delegate* unmanaged[Cdecl]<QUIC_HANDLE*, byte, QUIC_TLS_ALERT_CODES, int> ConnectionCertificateValidationComplete;

[NativeTypeName("QUIC_EXECUTION_CREATE_FN")]
internal delegate* unmanaged[Cdecl]<QUIC_EXECUTION_CONFIG_FLAGS, uint, QUIC_EXECUTION_CONTEXT_CONFIG*, QUIC_EXECUTION_CONTEXT**, int> ExecutionCreate;

[NativeTypeName("QUIC_EXECUTION_DELETE_FN")]
internal delegate* unmanaged[Cdecl]<uint, QUIC_EXECUTION_CONTEXT**, void> ExecutionDelete;

[NativeTypeName("QUIC_EXECUTION_POLL_FN")]
internal delegate* unmanaged[Cdecl]<QUIC_EXECUTION_CONTEXT*, uint> ExecutionPoll;
}

internal static unsafe partial class MsQuic
Expand Down
37 changes: 10 additions & 27 deletions src/inc/msquic.h
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,8 @@ typedef struct QUIC_EXECUTION_CONFIG {
#define QUIC_EXECUTION_CONFIG_MIN_SIZE \
(uint32_t)FIELD_OFFSET(QUIC_EXECUTION_CONFIG, ProcessorList)

#ifndef _KERNEL_MODE

//
// Execution Context abstraction, which allows the application layer to
// completely control execution of all MsQuic work.
Expand Down Expand Up @@ -343,31 +345,9 @@ uint32_t
_In_ QUIC_EXECUTION_CONTEXT* ExecutionContext
);

//
// This is called to allow MsQuic to process any completions that have occurred.
//
typedef
_IRQL_requires_max_(PASSIVE_LEVEL)
uint32_t
(QUIC_API * QUIC_EXECUTION_PROCESS_CQE_FN)(
_In_ QUIC_EXECUTION_CONTEXT* ExecutionContext,
_In_reads_(CqeCount) QUIC_CQE* Cqes,
_In_ uint32_t CqeCount
);
#endif // _KERNEL_MODE

//
// The table of execution functions.
//
typedef struct QUIC_EXECUTION_TABLE {

QUIC_EXECUTION_CREATE_FN ExecutionCreate;
QUIC_EXECUTION_DELETE_FN ExecutionDelete;
QUIC_EXECUTION_POLL_FN Poll;
QUIC_EXECUTION_PROCESS_CQE_FN ProcessCqe;

} QUIC_EXECUTION_TABLE;

#endif
#endif // QUIC_API_ENABLE_PREVIEW_FEATURES

typedef struct QUIC_REGISTRATION_CONFIG { // All fields may be NULL/zero.
const char* AppName;
Expand Down Expand Up @@ -933,9 +913,6 @@ void
#endif
#define QUIC_PARAM_GLOBAL_TLS_PROVIDER 0x0100000A // QUIC_TLS_PROVIDER
#define QUIC_PARAM_GLOBAL_STATELESS_RESET_KEY 0x0100000B // uint8_t[] - Array size is QUIC_STATELESS_RESET_KEY_LENGTH
#ifdef QUIC_API_ENABLE_PREVIEW_FEATURES
#define QUIC_PARAM_GLOBAL_EXECUTION_TABLE 0x0100000C // QUIC_EXECUTION_TABLE
#endif

//
// Parameters for Registration.
Expand Down Expand Up @@ -1706,6 +1683,12 @@ typedef struct QUIC_API_TABLE {
QUIC_CONNECTION_COMP_RESUMPTION_FN ConnectionResumptionTicketValidationComplete; // Available from v2.2
QUIC_CONNECTION_COMP_CERT_FN ConnectionCertificateValidationComplete; // Available from v2.2

#ifndef _KERNEL_MODE
QUIC_EXECUTION_CREATE_FN ExecutionCreate; // Available from v2.5
QUIC_EXECUTION_DELETE_FN ExecutionDelete; // Available from v2.5
QUIC_EXECUTION_POLL_FN ExecutionPoll; // Available from v2.5
#endif

} QUIC_API_TABLE;

#define QUIC_API_VERSION_1 1 // Not supported any more
Expand Down
12 changes: 10 additions & 2 deletions src/inc/msquic_posix.h
Original file line number Diff line number Diff line change
Expand Up @@ -522,12 +522,20 @@ QuicAddrToString(
#if __linux__ // epoll

typedef int QUIC_EVENTQ;
typedef struct epoll_event QUIC_CQE;

typedef struct QUIC_CQE {
struct epoll_event Event;
void (*Completion)(struct QUIC_CQE *Cqe);
} QUIC_CQE;

#elif __APPLE__ || __FreeBSD__ // kqueue

typedef int QUIC_EVENTQ;
typedef struct kevent QUIC_CQE;

typedef struct QUIC_CQE {
struct kevent Event;
void (*Completion)(struct QUIC_CQE *Cqe);
} QUIC_CQE;

#else

Expand Down
6 changes: 5 additions & 1 deletion src/inc/msquic_winuser.h
Original file line number Diff line number Diff line change
Expand Up @@ -378,6 +378,10 @@ QuicAddrToString(
//

typedef HANDLE QUIC_EVENTQ;
typedef OVERLAPPED_ENTRY QUIC_CQE;

typedef struct QUIC_CQE {
OVERLAPPED_ENTRY Overlapped;
void (*Completion)(struct QUIC_CQE *Cqe);
} QUIC_CQE;

#endif // _MSQUIC_WINUSER_
5 changes: 5 additions & 0 deletions src/tools/execution/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT License.

add_quic_tool(quicexecution execution_windows.cpp)
quic_tool_warnings(quicexecution)
91 changes: 91 additions & 0 deletions src/tools/execution/execution_windows.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
/*++

Copyright (c) Microsoft Corporation.
Licensed under the MIT License.

Abstract:

Provides simple client MsQuic example that leverages custom execution.

--*/

#define QUIC_API_ENABLE_PREVIEW_FEATURES 1

#include "msquic.hpp"
#include <stdio.h>

void PrintUsage()
{
printf(
"\n"
"quicexec is a simple app that can connect to an HTTP/3 server.\n"
"\n"
"Usage:\n"
"\n"
" quicexec <host or ip>\n"
);
}

int
QUIC_MAIN_EXPORT
main(
_In_ int argc,
_In_reads_(argc) _Null_terminated_ char* argv[]
)
{
MsQuicApi _MsQuic;
if (!_MsQuic.IsValid()) { return 1; }
MsQuic = &_MsQuic;

QUIC_STATUS Status;
HANDLE IOCP = CreateIoCompletionPort(INVALID_HANDLE_VALUE, nullptr, 0, 1);
QUIC_EXECUTION_CONTEXT_CONFIG ExecConfig = { 0, 0, &IOCP };
QUIC_EXECUTION_CONTEXT* ExecContext = nullptr;
if (QUIC_FAILED(Status = MsQuic->ExecutionCreate(QUIC_EXECUTION_CONFIG_FLAG_NONE, 1, &ExecConfig, &ExecContext))) {
nibanks marked this conversation as resolved.
Show resolved Hide resolved
return 1;
}

do {
bool AllDone = false;
MsQuicRegistration Registration("quicexec");
MsQuicSettings Settings;
Settings.SetPeerUnidiStreamCount(3); // required for H3
MsQuicConfiguration Configuration(Registration, "h3", Settings, MsQuicCredentialConfig());
if (!Configuration.IsValid()) { break; }

struct ConnectionCallback {
static QUIC_STATUS MsQuicConnectionCallback(_In_ struct MsQuicConnection* Connection, _In_opt_ void* Context, _Inout_ QUIC_CONNECTION_EVENT* Event) {
if (Event->Type == QUIC_CONNECTION_EVENT_CONNECTED) {
Connection->Shutdown(0);
} else if (Event->Type == QUIC_CONNECTION_EVENT_SHUTDOWN_COMPLETE) {
*((bool*)Context) = true;
}
}
};

MsQuicConnection Connection(Registration, CleanUpManual, ConnectionCallback::MsQuicConnectionCallback, &AllDone);
if (QUIC_FAILED(
Status = Connection.Start(Configuration, argv[1], 443))) {
break;
}

while (!AllDone) {
uint32_t WaitTime = MsQuic->ExecutionPoll(ExecContext);

OVERLAPPED_ENTRY Overlapped[8];
ULONG OverlappedCount = 0;
if (GetQueuedCompletionStatusEx(IOCP, Overlapped, ARRAYSIZE(Overlapped), &OverlappedCount, WaitTime, FALSE)) {
for (ULONG i = 0; i < OverlappedCount; ++i) {
QUIC_CQE* Cqe = CONTAINING_RECORD(Overlapped[i].lpOverlapped, QUIC_CQE, Overlapped);
nibanks marked this conversation as resolved.
Show resolved Hide resolved
Cqe->Completion(Cqe);
}
}
}

} while (false);

MsQuic->ExecutionDelete(1, &ExecContext);
CloseHandle(IOCP);

return 0;
}
Loading