Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
53 changes: 46 additions & 7 deletions src/core/connection_pool.c
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,46 @@ 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;

QuicConnQueueOper(Connection, &Oper);
CxPlatEventWaitForever(CompletionEvent);
CxPlatEventUninitialize(CompletionEvent);

return StartStatus;
}


static
_IRQL_requires_max_(PASSIVE_LEVEL)
Expand Down Expand Up @@ -372,13 +412,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 +432,12 @@ 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. QuicConnStart
// cleared the callback handler and closed it on the worker, so we just
// need to release our owner reference to free it.
//
(*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