当前位置: 首页 > article >正文

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;
    }


http://www.kler.cn/news/362076.html

相关文章:

  • 多级缓存-案例导入说明
  • LeetCode53:最大子数组和
  • 【UE5】将2D切片图渲染为体积纹理,最终实现使用RT实时绘制体积纹理【第六篇-阶段总结篇】
  • 软件质量管理体系,软件评审资料,资质认证资料,安全建设,数据安全及项目管理全套资料(原件参考)
  • 演示:基于WPF的DrawingVisual开发的高刷新率示波器
  • C语言数据结构之双向链表(LIST)的实现
  • 10月22日,每日信息差
  • 基础学习-centos修改本地语言
  • 【C++】vector(1)
  • Linux中文件的读写过程
  • 制造企业数字化转型顶层规划案例(55页满分PPT)
  • Vue学习笔记(四、v-bind指令)
  • 复旦大学全球供应链研究中心揭牌,合合信息共话大数据赋能
  • VMware通过Vcenter升级Esxi
  • 人工智能技术的应用与未来展望
  • 电子电气架构---中央/准中央+区域架构已成为OEM主机厂降本利器
  • 059_基于python智能文献管理系统
  • MySQL 创新版9.1.0有哪些功能?
  • 摩熵数科数据产品阵容BCPM
  • docker 微服务实践
  • springboot jackson 数据脱敏
  • json键值对组成的数组去重。
  • 13.3 Linux_网络编程_多路复用I/O接入多客户端
  • 【C语言】一维数组的定义与初始化
  • 设计模式:类与类之间关系的表示方式(聚合,组合,依赖,继承,实现)
  • 【编程语言】Kotlin快速入门 - 伴生对象与懒加载