Здраствуйте.
Не подскажете как реализовать listen, на tdi уровне. Есть драйвер и создаваемый им поток который должен работать с сетью.
while (workThread)
{
switch (KeWaitForMultipleObjects(1, events, WaitAny, Executive, KernelMode, FALSE, NULL, waitBlocks))
{
case EV_COMMAND_WORK_TO_DO:
{
command = pBRDGDevExt->packet.command;
switch(command)
{
case CONNECT:
{
Status = k_Connect(pTCPContext);
//...............................
break;
}
case BIND:
{
Status = k_Bind(pTCPContext);
//..........................
break;
}
case LISTEN:
{
Status = k_Listen(pTCPContext);
//........................
break;
}
case ACCEPT:
{
Status = k_Accept(pTCPContext);
//...............................
break;
}
//....................................
// и так далее
}
break;
}
}
pBRDGDevExt->packet.status = Status;
KeReleaseSemaphore(&pBRDGDevExt->KScommand, 0, 1, FALSE);
}
вот собственно сама ф-ия
k_listen:
SOCKET k_listen(SOCKET s, SOCK_ADDR* addr, int addrlen)
{
PSocketData sdata = (PSocketData)s;
PSocketData NewSocket = NULL;
NTSTATUS status;
PDEVICE_OBJECT pDeviceObject;
if (k_IsValidSocket(s))
{
NewSocket = ExAllocatePool(NonPagedPool, sizeof(TSocketData));
if (NewSocket)
{
RtlZeroMemory(NewSocket, sizeof(TSocketData)); //!
NewSocket->Type = sdata->Type;
NewSocket->Protocol = sdata->Protocol;
NewSocket->m_Point.m_hAddress = INVALID_HANDLE_VALUE;
NewSocket->m_endPoint.m_hContext = INVALID_HANDLE_VALUE;
status = k_OpenConnectionEndpoint(sdata, NewSocket, NewSocket);
if (!NT_SUCCESS(status))
{
k_CloseConnectionEndpoint( &NewSocket->m_endPoint );
ExFreePool(NewSocket);
return SOCKET_ERROR;
}
pDeviceObject = IoGetRelatedDeviceObject(NewSocket->m_endPoint.m_pFileObject);
NewSocket->m_pListenIrp = IoAllocateIrp(
pDeviceObject->StackSize,
FALSE
);
if( !NewSocket->m_pListenIrp )
{
k_CloseConnectionEndpoint( &NewSocket->m_endPoint );
return( STATUS_INSUFFICIENT_RESOURCES );
}
NewSocket->m_RemoteConnectionInfo.UserDataLength = 0;
NewSocket->m_RemoteConnectionInfo.UserData = NULL;
NewSocket->m_RemoteConnectionInfo.OptionsLength = 0;
NewSocket->m_RemoteConnectionInfo.Options = NULL;
NewSocket->m_RemoteConnectionInfo.RemoteAddressLength = sizeof( TA_IP_ADDRESS );
NewSocket->m_RemoteConnectionInfo.RemoteAddress = &NewSocket->m_RemoteAddress;
TdiBuildListen(
NewSocket->m_pListenIrp,
pDeviceObject,
NewSocket->m_endPoint.m_pFileObject,
k_ConnectedCallback, // Completion Routine
NewSocket, // Completion Context
0, // Flags
NULL, // Request Connection Info
&NewSocket->m_RemoteConnectionInfo
);
status = IoCallDriver( pDeviceObject, NewSocket->m_pListenIrp );
if (NT_SUCCESS(status)) return (SOCKET)NewSocket;
}
}
if (NewSocket) ExFreePool(NewSocket);
return SOCKET_ERROR;
}
Вроде все нормально.Только при конекте клиента, сразу же происходит диконект, без события на recive. А callback ф-ия k_ConnectedCallback должна опять вызват listen, но она возвращает статус 0xC000023b(STATUS_CONNECTION_ACTIVE). Вот пример ф-ии
NTSTATUS
k_ConnectedCallback(
IN PDEVICE_OBJECT pDeviceObject,
IN PIRP pIrp,
IN PVOID Context
)
{
PSocketData pSocket = (PSocketData)Context;
NTSTATUS Status = pIrp->IoStatus.Status;
KdPrint(( "k_ConnectedCallback: FinalStatus: 0x%8.8x\n", Status ));
if( NT_SUCCESS( Status ) )
{
pSocket->m_nBytesReceived = 0;
// (pSocket->m_pReceiveMdl)->Next = NULL;
Status = k_ReceiveOnEndpoint(
&pSocket->m_endPoint,
NULL, // User Completion Event
k_ReceiveCompletion,// User Completion Routine
pSocket, // User Completion Context
&pSocket->m_pReceiveIoStatus,
pSocket->m_pReceiveMdl,
0 // Flags
);
}
return( STATUS_MORE_PROCESSING_REQUIRED );
}
Т.е. "листена" больше не происходит, даже после переинециализации девайса(не драйвера).
Здравствуйте, TarasCo, Вы писали:
TC>Здравствуйте, Аноним, Вы писали:
TC>Попробуйте установить флаг TDI_QUERY_ACCEPT в запросе TDI_LISTEN. В функции обработчике окончания запроса TDI_LISTEN в случае успеха вызовете запрос TDI_ACCEPT, по успешному окончанию которого можно считать соединение успешно установленным.
Не подскажете какая последовательность действий по созданию kernel-socket, вчастности интересует создание именно серверной части. Много просмотрел примеров, и у всех алгоритмы создания сокета разные, в отличе от SDK сокета
Для чего в некоторых реализациях используется TdiBuildInternalDeviceControlIrp?
Здравствуйте, Аноним, Вы писали:
А>Не подскажете какая последовательность действий по созданию kernel-socket, вчастности интересует создание именно серверной части. Много просмотрел примеров, и у всех алгоритмы создания сокета разные, в отличе от SDK сокета
Ну нужно, конкретные моменты сранивать. Работая на низком уровне у Вас есть определенная гибкость и в результате появляются варианты. Кстати, реалтзация сервера в режиме приложения не так одназначна, как Вам кажется. Например, стандартные сервисы при приеме соединения не используют вызов accept/WSAAccept, а нечто другое

( это так, для возбуждения любопытства

).
А>Для чего в некоторых реализациях используется TdiBuildInternalDeviceControlIrp?
Это делает код компактнее — не нужно самостоятельно создавать IRP, не нужно его потом удалять. Короче — вопрос стиля
Вот еше ссылка здесь же по теме:
http://rsdn.ru/Forum/Message.aspx?mid=2042652Автор: TarasCo
Дата: 04.08.06
Здравствуйте, TarasCo, Вы писали:
TC>Ну нужно, конкретные моменты сранивать. Работая на низком уровне у Вас есть определенная гибкость и в результате появляются варианты. Кстати, реалтзация сервера в режиме приложения не так одназначна, как Вам кажется. Например, стандартные сервисы при приеме соединения не используют вызов accept/WSAAccept, а нечто другое
( это так, для возбуждения любопытства
).
Не могли бы Вы пояснить насчет "нечто другое" ? Есть подозрение что устанавливается просто событие на конект/прием. Только как привязаться к нужному порту? И как проще организовать соединение точка-точка?