Tftpd.exe源代码分析----TftpdIoPostReceiveBuffer函数分析
第一部分:
TftpdIoAssignSocket函数调用了TftpdIoInitializeSocketContext函数
TftpdIoInitializeSocketContext函数注册了回调函数TftpdIoReadNotification
void
TftpdIoInitializeSocketContext(PTFTPD_SOCKET socket, PSOCKADDR_IN addr, PTFTPD_CONTEXT context) {
......
// Register for FD_READ notification on the socket.
if (!RegisterWaitForSingleObject(&socket->wSelectWait,
socket->hSelect,
(WAITORTIMERCALLBACK)TftpdIoReadNotification,
socket,
INFINITE,
WT_EXECUTEINWAITTHREAD)) {
TFTPD_DEBUG((TFTPD_DBG_IO,
"TftpdIoInitializeSocketContext: "
"RegisterWaitForSingleObject() failed, error 0x%08X.\n",
GetLastError()));
goto fail_create_context;
}
第二部分:回调函数的主要功能
TftpdIoReadNotification函数循环调用TftpdIoPostReceiveBuffer函数
void CALLBACK
TftpdIoReadNotification(PTFTPD_SOCKET socket, BOOLEAN timeout) {
TFTPD_DEBUG((TFTPD_TRACE_IO,
"TftpdIoReadNotification(socket = %s).\n",
((socket == &globals.io.master) ? "master" :
((socket == &globals.io.def) ? "def" :
((socket == &globals.io.mtu) ? "mtu" :
((socket == &globals.io.max) ? "max" :
"private")))) ));
// If this fails, the event triggering this callback will stop signalling
// due to a lack of a successful WSARecvFrom() ... this will likely occur
// during low-memory/stress conditions. When the system returns to normal,
// the low water-mark buffers will be reposted, thus receiving data and
// re-enabling the event which triggers this callback.
while (!globals.service.shutdown)
if (TftpdIoPostReceiveBuffer(socket, NULL) >= socket->lowWaterMark)
break;
} // TftpdIoReadNotification()
第三部分:TftpdIoPostReceiveBuffer函数打印了那些调试信息
第一条信息:TftpdIoPostReceiveBuffer函数一上来打印跟踪信息
[0728] TftpdIoPostReceiveBuffer(buffer = 00000000, socket = def)
第二条信息:TftpdIoPostReceiveBuffer函数再调用TftpdIoAllocateBuffer函数分配内存
[0728] TftpdIoAllocateBuffer(socket = def).
第三条信息:TftpdIoPostReceiveBuffer函数再打印跟踪信息打印buffer地址
[0728] TftpdIoPostReceiveBuffer(buffer = 00455598).
DWORD
TftpdIoPostReceiveBuffer(PTFTPD_SOCKET socket, PTFTPD_BUFFER buffer) {
DWORD postedBuffers = 0, successfulPosts = 0;
int error;
TFTPD_DEBUG((TFTPD_TRACE_IO,
"TftpdIoPostReceiveBuffer(buffer = %p, socket = %s).\n",
buffer,
((socket == &globals.io.master) ? "master" :
((socket == &globals.io.def) ? "def" :
((socket == &globals.io.mtu) ? "mtu" :
((socket == &globals.io.max) ? "max" :
"private")))) ));
postedBuffers = InterlockedIncrement((PLONG)&socket->postedBuffers);
//
// Attempt to post a buffer:
//
while (TRUE) {
WSABUF buf;
if (globals.service.shutdown ||
(postedBuffers > globals.parameters.highWaterMark))
goto exit_post_buffer;
// Allocate the buffer if we're not reusing one.
if (buffer == NULL) {
buffer = TftpdIoAllocateBuffer(socket);
if (buffer == NULL) {
TFTPD_DEBUG((TFTPD_DBG_IO,
"TftpdIoPostReceiveBuffer(buffer = %p): "
"TftpdIoAllocateBuffer() failed.\n",
buffer));
goto exit_post_buffer;
}
TFTPD_DEBUG((TFTPD_TRACE_IO,
"TftpdIoPostReceiveBuffer(buffer = %p).\n",
buffer));
} else {
......
第四部分:返回到read.c文件中的TftpdReadRequest函数中
的TftpdIoAssignSocket函数后面继续进行,直到TftpdContextAdd函数
PTFTPD_BUFFER
TftpdReadRequest(PTFTPD_BUFFER buffer) {
......
// Figure out which socket to use for this request (based on blksize).
if (!TftpdIoAssignSocket(context, buffer)) {
TFTPD_DEBUG((TFTPD_DBG_PROCESS,
"TftpdReadRequest(buffer = %p): "
"TftpdIoAssignSocket() failed.\n",
buffer));
goto exit_read_request;
}
// Check whether access is permitted.
if (!TftpdUtilMatch(globals.parameters.validClients, inet_ntoa(context->peer.sin_addr)) ||
!TftpdUtilMatch(globals.parameters.validReadFiles, context->filename)) {
TFTPD_DEBUG((TFTPD_DBG_PROCESS,
"TftpdReadRequest(buffer = %p): Access denied.\n",
buffer));
TftpdIoSendErrorPacket(buffer, TFTPD_ERROR_ACCESS_VIOLATION,
"Access violation");
goto exit_read_request;
}
// Open the file.
context->hFile = CreateFile(context->filename, GENERIC_READ,
FILE_SHARE_READ, NULL, OPEN_EXISTING,
FILE_FLAG_SEQUENTIAL_SCAN | FILE_FLAG_OVERLAPPED, NULL);
if (context->hFile == INVALID_HANDLE_VALUE) {
TFTPD_DEBUG((TFTPD_DBG_PROCESS,
"TftpdReadRequest(buffer = %p): "
"CreateFile() for filename = %s not found, error 0x%08X.\n",
buffer, context->filename, GetLastError()));
TftpdIoSendErrorPacket(buffer, TFTPD_ERROR_FILE_NOT_FOUND,
"File not found");
context->hFile = NULL;
goto exit_read_request;
}
if (!GetFileSizeEx(context->hFile, &context->filesize)) {
TFTPD_DEBUG((TFTPD_DBG_PROCESS,
"TftpdReadRequest(buffer = %p): "
"Invalid file size for file name = %s.\n",
buffer, context->filename));
TftpdIoSendErrorPacket(buffer, TFTPD_ERROR_ACCESS_VIOLATION,
"Access violation");
goto exit_read_request;
}
// Create the ReadFile() wait event.
if ((context->hWait = CreateEvent(NULL, FALSE, FALSE, NULL)) == NULL) {
TFTPD_DEBUG((TFTPD_DBG_PROCESS,
"TftpdReadRequest(buffer = %p): "
"CreateEvent() failed, error = %d.\n",
buffer, GetLastError()));
TftpdIoSendErrorPacket(buffer, TFTPD_ERROR_UNDEFINED, "Out of memory");
goto exit_read_request;
}
// Insert the context into the hash-table.
if (!TftpdContextAdd(context)) {
TFTPD_DEBUG((TFTPD_TRACE_PROCESS,
"TftpdReadRequest(buffer = %p): "
"Dropping request as we're already servicing it.\n",
buffer));
TftpdIoSendErrorPacket(buffer, TFTPD_ERROR_UNDEFINED,
"Illegal TFTP operation");
goto exit_read_request;
}