Skip to content
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/core/api.c
Original file line number Diff line number Diff line change
Expand Up @@ -450,6 +450,7 @@ MsQuicConnectionStart(
Oper->API_CALL.Context->CONN_START.ServerName = ServerNameCopy;
Oper->API_CALL.Context->CONN_START.ServerPort = ServerPort;
Oper->API_CALL.Context->CONN_START.Family = Family;
Oper->API_CALL.Context->CONN_START.Flags = QUIC_CONN_START_FLAG_NONE;
ServerNameCopy = NULL;

//
Expand Down
12 changes: 11 additions & 1 deletion src/core/connection.c
Original file line number Diff line number Diff line change
Expand Up @@ -1988,6 +1988,16 @@ QuicConnStart(
}

if (QUIC_FAILED(Status)) {
if (StartFlags & QUIC_CONN_START_FLAG_FAIL_SILENTLY) {
//
// This connection was created internally (e.g. by the connection
// pool) and was never returned to the application. Suppress the
// shutdown-complete notification by clearing the callback handler.
// The connection stays externally owned; the creating context is
// responsible for closing it and releasing the owner reference.
//
Connection->ClientCallbackHandler = NULL;
}
QuicConnCloseLocally(
Connection,
StartFlags & QUIC_CONN_START_FLAG_FAIL_SILENTLY ?
Expand Down Expand Up @@ -7783,7 +7793,7 @@ QuicConnProcessApiOperation(
ApiCtx->CONN_START.Family,
ApiCtx->CONN_START.ServerName,
ApiCtx->CONN_START.ServerPort,
QUIC_CONN_START_FLAG_NONE);
ApiCtx->CONN_START.Flags);
ApiCtx->CONN_START.ServerName = NULL;
break;

Expand Down
5 changes: 0 additions & 5 deletions src/core/connection.h
Original file line number Diff line number Diff line change
Expand Up @@ -1219,11 +1219,6 @@ QuicConnQueueHighestPriorityOper(
_In_ QUIC_OPERATION* Oper
);

typedef enum QUIC_CONN_START_FLAGS {
QUIC_CONN_START_FLAG_NONE = 0x00000000U,
QUIC_CONN_START_FLAG_FAIL_SILENTLY = 0x00000001U // Don't send notification to API client
} QUIC_CONN_START_FLAGS;

//
// Starts the connection. Shouldn't be called directly in most instances.
//
Expand Down
60 changes: 53 additions & 7 deletions src/core/connection_pool.c
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,51 @@ QuicConnPoolQueueConnectionClose(
}
}

//
// Start the connection on its worker thread and wait for completion.
//
static
_IRQL_requires_max_(PASSIVE_LEVEL)
QUIC_STATUS
QuicConnPoolStartConnection(
_In_ QUIC_CONNECTION* Connection,
_In_ QUIC_CONFIGURATION* Configuration,
_In_ QUIC_ADDRESS_FAMILY Family,
_In_z_ const char* ServerName,
_In_ uint16_t ServerPort
)
{
QUIC_STATUS StartStatus = QUIC_STATUS_INTERNAL_ERROR;
CXPLAT_EVENT CompletionEvent;
QUIC_OPERATION Oper = { 0 };
QUIC_API_CONTEXT ApiCtx;

Oper.Type = QUIC_OPER_TYPE_API_CALL;
Oper.FreeAfterProcess = FALSE; // Stack-allocated; worker must not free it.
Oper.API_CALL.Context = &ApiCtx;

CxPlatEventInitialize(&CompletionEvent, TRUE, FALSE);
ApiCtx.Type = QUIC_API_TYPE_CONN_START;
ApiCtx.Status = &StartStatus;
ApiCtx.Completed = &CompletionEvent;
ApiCtx.CONN_START.Configuration = Configuration;
ApiCtx.CONN_START.ServerName = ServerName; // Ownership passes to QuicConnStart.
ApiCtx.CONN_START.ServerPort = ServerPort;
ApiCtx.CONN_START.Family = Family;
ApiCtx.CONN_START.Flags = QUIC_CONN_START_FLAG_FAIL_SILENTLY;

//
// No op-level Configuration ref is needed: we block until the op completes
// and the caller keeps the Configuration alive; QuicConnSetConfiguration
// takes its own QUIC_CONF_REF_CONNECTION ref.
//
Comment thread
guhetier marked this conversation as resolved.
Outdated
QuicConnQueueOper(Connection, &Oper);
CxPlatEventWaitForever(CompletionEvent);
CxPlatEventUninitialize(CompletionEvent);

return StartStatus;
}


static
_IRQL_requires_max_(PASSIVE_LEVEL)
Expand Down Expand Up @@ -372,13 +417,12 @@ QuicConnPoolTryCreateConnection(
}
}

Status = QuicConnStart(
Status = QuicConnPoolStartConnection(
*Connection,
Configuration,
Family,
ServerName,
ServerPort,
QUIC_CONN_START_FLAG_FAIL_SILENTLY);
ServerPort);

ServerName = NULL; // The connection now owns the ServerName.

Expand All @@ -393,12 +437,14 @@ QuicConnPoolTryCreateConnection(

if (QUIC_FAILED(Status) && *Connection != NULL) {
//
// This connection has never left MsQuic back to the application.
// Mark it as internally owned so no notification is sent to the app,
// the closing logic will handle the final deref.
// This connection was never returned to the application. Close it (its
// callback handler was already cleared by QuicConnStart, so no shutdown
// notification is raised) and release our owner reference so it is
// freed. This matches the cleanup path for successfully created pool
// connections below.
Comment thread
guhetier marked this conversation as resolved.
Outdated
//
(*Connection)->State.ExternalOwner = FALSE;
QuicConnPoolQueueConnectionClose(*Connection, FALSE);
QuicConnRelease(*Connection, QUIC_CONN_REF_HANDLE_OWNER);
*Connection = NULL;
}

Expand Down
6 changes: 6 additions & 0 deletions src/core/operation.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,11 @@ typedef enum QUIC_API_TYPE {

} QUIC_API_TYPE;

typedef enum QUIC_CONN_START_FLAGS {
Comment thread
guhetier marked this conversation as resolved.
QUIC_CONN_START_FLAG_NONE = 0x00000000U,
QUIC_CONN_START_FLAG_FAIL_SILENTLY = 0x00000001U // Don't send notification to API client
} QUIC_CONN_START_FLAGS;

//
// Context for an API call. This is allocated separately from QUIC_OPERATION
// so that non-API-call operations will take less space.
Expand Down Expand Up @@ -108,6 +113,7 @@ typedef struct QUIC_API_CONTEXT {
const char* ServerName;
uint16_t ServerPort;
QUIC_ADDRESS_FAMILY Family;
QUIC_CONN_START_FLAGS Flags;
} CONN_START;
struct {
QUIC_CONFIGURATION* Configuration;
Expand Down
Loading