Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

210 lines
5.4 KiB

  1. /*++
  2. Copyright (c) 2001 Microsoft Corporation
  3. Module Name:
  4. process.c
  5. Abstract:
  6. This module contains functions to handle processing of
  7. incoming datagrams and route them to the appropriate
  8. handlers.
  9. Author:
  10. Jeffrey C. Venable, Sr. (jeffv) 01-Jun-2001
  11. Revision History:
  12. --*/
  13. #include "precomp.h"
  14. BOOL
  15. TftpdProcessComplete(PTFTPD_BUFFER buffer) {
  16. PTFTPD_CONTEXT context = buffer->internal.context;
  17. DWORD state;
  18. TFTPD_DEBUG((TFTPD_TRACE_PROCESS,
  19. "TftpdProcessComplete(context = %p).\n",
  20. context));
  21. ASSERT(context->state & TFTPD_STATE_BUSY);
  22. // Reset the timer.
  23. if (!TftpdContextUpdateTimer(context)) {
  24. TftpdContextKill(context);
  25. TftpdIoSendErrorPacket(buffer, TFTPD_ERROR_UNDEFINED, "Out of memory");
  26. return (FALSE);
  27. } // if (!TftpdContextUpdateTimer(context, buffer))
  28. // Clear the busy state.
  29. do {
  30. state = context->state;
  31. if (state & TFTPD_STATE_DEAD) {
  32. if (context->type == TFTPD_WRQ)
  33. return (TRUE);
  34. return (FALSE);
  35. }
  36. } while (InterlockedCompareExchange(&context->state,
  37. (state & ~TFTPD_STATE_BUSY),
  38. state) != state);
  39. return (TRUE);
  40. } // TftpdProcessComplete()
  41. void CALLBACK
  42. TftpdProcessTimeout(PTFTPD_CONTEXT context, BOOLEAN timedOut) {
  43. PTFTPD_BUFFER buffer = NULL;
  44. LONG reference;
  45. //
  46. // The timer's reference to the context is a special case becase
  47. // the context cannot cleanup until the timer is successfully
  48. // cancelled; if we're running here, that means cleanup must wait
  49. // for us. However, if cleanup is active (TFTPD_STATE_DEAD), the
  50. // reference count might be zero; if so we just want to bail
  51. // because decrementing it back to zero causes double-delete.
  52. //
  53. do {
  54. if ((reference = context->reference) == 0)
  55. return;
  56. } while (InterlockedCompareExchange(&context->reference,
  57. reference + 1,
  58. reference) != reference);
  59. // Aquire busy-sending state.
  60. if (InterlockedCompareExchange(&context->state, TFTPD_STATE_BUSY, 0) != 0)
  61. goto exit_timer_callback;
  62. TFTPD_DEBUG((TFTPD_TRACE_PROCESS,
  63. "TftpdProcessTimeout(context = %p).\n",
  64. context));
  65. #if defined(DBG)
  66. InterlockedIncrement((PLONG)&globals.performance.timeouts);
  67. #endif // defined(DBG)
  68. // Allocate a buffer to either retry the previous DATA/ACK we last sent,
  69. // or to send an ERROR packet if we've reached max-retries.
  70. buffer = TftpdIoAllocateBuffer(context->socket);
  71. if (buffer == NULL)
  72. goto exit_timer_callback;
  73. CopyMemory(&buffer->internal.io.peer, &context->peer,
  74. sizeof(buffer->internal.io.peer));
  75. if (++context->retransmissions >= globals.parameters.maxRetries) {
  76. #if defined(DBG)
  77. InterlockedIncrement((PLONG)&globals.performance.drops);
  78. #endif // defined(DBG)
  79. TftpdContextKill(context);
  80. TftpdIoSendErrorPacket(buffer, TFTPD_ERROR_UNDEFINED, "Timeout");
  81. goto exit_timer_callback;
  82. }
  83. buffer->internal.context = context;
  84. if (context->type == TFTPD_RRQ)
  85. buffer = TftpdReadResume(buffer);
  86. else
  87. buffer = TftpdWriteSendAck(buffer);
  88. exit_timer_callback :
  89. if (buffer != NULL)
  90. TftpdIoPostReceiveBuffer(buffer->internal.socket, buffer);
  91. TftpdContextRelease(context);
  92. } // TftpdProcessTimeout()
  93. void
  94. TftpdProcessError(PTFTPD_BUFFER buffer) {
  95. PTFTPD_CONTEXT context = NULL;
  96. context = TftpdContextAquire(&buffer->internal.io.peer);
  97. if (context == NULL)
  98. return;
  99. TFTPD_DEBUG((TFTPD_TRACE_PROCESS,
  100. "TftpdProcessError(buffer = %p, context = %p).\n",
  101. buffer, context));
  102. TftpdContextKill(context);
  103. TftpdContextRelease(context);
  104. } // TftpdProcessError()
  105. PTFTPD_BUFFER
  106. TftpdProcessReceivedBuffer(PTFTPD_BUFFER buffer) {
  107. TFTPD_DEBUG((TFTPD_TRACE_PROCESS,
  108. "TftpdProcessReceivedBuffer(buffer = %p).\n",
  109. buffer));
  110. buffer->message.opcode = ntohs(buffer->message.opcode);
  111. switch (buffer->message.opcode) {
  112. //
  113. // Sending files to a client:
  114. //
  115. case TFTPD_RRQ :
  116. buffer = TftpdReadRequest(buffer);
  117. break;
  118. case TFTPD_ACK :
  119. buffer->message.ack.block = ntohs(buffer->message.ack.block);
  120. buffer = TftpdReadAck(buffer);
  121. break;
  122. //
  123. // Receiving files from a client:
  124. //
  125. case TFTPD_WRQ :
  126. buffer = TftpdWriteRequest(buffer);
  127. break;
  128. case TFTPD_DATA :
  129. buffer->message.data.block = ntohs(buffer->message.data.block);
  130. buffer = TftpdWriteData(buffer);
  131. break;
  132. //
  133. // Other:
  134. //
  135. case TFTPD_ERROR :
  136. TftpdProcessError(buffer);
  137. break;
  138. default :
  139. // Just drop the packet. Somehow we received a bogus datagram
  140. // that's not TFTP protocol (possibly a broadcast).
  141. break;
  142. } // switch (buffer->message.opcode)
  143. return (buffer);
  144. } // TftpdProcessReceivedBuffer()