Annotation of ntddk/src/network/tdi/rcveng.c, revision 1.1.1.1

1.1       root        1: /*++
                      2: 
                      3: Copyright (c) 1989-1993 Microsoft Corporation
                      4: 
                      5: Module Name:
                      6: 
                      7:     rcveng.c
                      8: 
                      9: Abstract:
                     10: 
                     11:     This module contains code that implements the receive engine for the
                     12:     Sample transport provider.
                     13: 
                     14: Environment:
                     15: 
                     16:     Kernel mode
                     17: 
                     18: Revision History:
                     19: 
                     20: --*/
                     21: 
                     22: #include "st.h"
                     23: 
                     24: 
                     25: VOID
                     26: ActivateReceive(
                     27:     PTP_CONNECTION Connection
                     28:     )
                     29: 
                     30: /*++
                     31: 
                     32: Routine Description:
                     33: 
                     34:     This routine activates the next TdiReceive request on the specified
                     35:     connection object if there is no active request on that connection
                     36:     already.  This allows the request to accept data on the connection.
                     37: 
                     38: Arguments:
                     39: 
                     40:     Connection - Pointer to a TP_CONNECTION object.
                     41: 
                     42: Return Value:
                     43: 
                     44:     none.
                     45: 
                     46: --*/
                     47: 
                     48: {
                     49:     KIRQL oldirql;
                     50:     PTP_REQUEST Request;
                     51: 
                     52:     //
                     53:     // The ACTIVE_RECEIVE bitflag will be set on the connection if
                     54:     // the receive-fields in the CONNECTION object are valid.  If
                     55:     // this flag is cleared, then we try to make the next TdiReceive
                     56:     // request in the ReceiveQueue the active request.
                     57:     //
                     58: 
                     59:     ACQUIRE_SPIN_LOCK (&Connection->SpinLock, &oldirql);
                     60:     if (!(Connection->Flags & CONNECTION_FLAGS_ACTIVE_RECEIVE)) {
                     61:         if (!IsListEmpty (&Connection->ReceiveQueue)) {
                     62: 
                     63:             //
                     64:             // Found a receive, so make it the active one.
                     65:             //
                     66: 
                     67:             Connection->Flags |= CONNECTION_FLAGS_ACTIVE_RECEIVE;
                     68: 
                     69:             Request = CONTAINING_RECORD (
                     70:                           Connection->ReceiveQueue.Flink,
                     71:                           TP_REQUEST,
                     72:                           Linkage);
                     73:             Connection->MessageBytesReceived = 0;
                     74:             Connection->MessageBytesAcked = 0;
                     75:             Connection->CurrentReceiveRequest = Request;
                     76:             Connection->CurrentReceiveMdl = Request->Buffer2;
                     77:             Connection->ReceiveLength = Request->Buffer2Length;
                     78:             Connection->ReceiveByteOffset = 0;
                     79:         }
                     80:     }
                     81: 
                     82:     RELEASE_SPIN_LOCK (&Connection->SpinLock, oldirql);
                     83: 
                     84: } /* ActivateReceive */
                     85: 
                     86: 
                     87: VOID
                     88: AwakenReceive(
                     89:     PTP_CONNECTION Connection
                     90:     )
                     91: 
                     92: /*++
                     93: 
                     94: Routine Description:
                     95: 
                     96:     This routine is called to reactivate a sleeping connection with the
                     97:     RECEIVE_WAKEUP bitflag set because data arrived for which no receive
                     98:     was available.  The caller has made a receive available at the connection,
                     99:     so here we activate the next receive, and send the appropriate protocol
                    100:     to restart the message at the first byte offset past the one received
                    101:     by the last receive.
                    102: 
                    103: Arguments:
                    104: 
                    105:     Connection - Pointer to a TP_CONNECTION object.
                    106: 
                    107: Return Value:
                    108: 
                    109:     none.
                    110: 
                    111: --*/
                    112: 
                    113: {
                    114:     KIRQL oldirql;
                    115: 
                    116:     //
                    117:     // If the RECEIVE_WAKEUP bitflag is set, then awaken the connection.
                    118:     //
                    119: 
                    120:     ACQUIRE_SPIN_LOCK (&Connection->SpinLock, &oldirql);
                    121:     if (Connection->Flags & CONNECTION_FLAGS_RECEIVE_WAKEUP) {
                    122:         if (Connection->ReceiveQueue.Flink != &Connection->ReceiveQueue) {
                    123:             Connection->Flags &= ~CONNECTION_FLAGS_RECEIVE_WAKEUP;
                    124: 
                    125:             //
                    126:             // Found a receive, so turn off the wakeup flag, and activate
                    127:             // the next receive.
                    128:             //
                    129: 
                    130:             RELEASE_SPIN_LOCK (&Connection->SpinLock, oldirql);
                    131:             ActivateReceive (Connection);
                    132: 
                    133:             return;
                    134:         }
                    135:     }
                    136:     RELEASE_SPIN_LOCK (&Connection->SpinLock, oldirql);
                    137: } /* AwakenReceive */
                    138: 
                    139: 
                    140: VOID
                    141: CompleteReceive(
                    142:     PTP_CONNECTION Connection,
                    143:     BOOLEAN EndOfRecord,
                    144:     KIRQL ConnectionIrql,
                    145:     KIRQL CancelIrql
                    146:     )
                    147: 
                    148: /*++
                    149: 
                    150: Routine Description:
                    151: 
                    152:     This routine is called by ProcessIncomingData when the current receive
                    153:     must be completed.  Depending on whether the current frame being
                    154:     processed is a DATA_FIRST_MIDDLE or DATA_ONLY_LAST, and also whether
                    155:     all of the data was processed, the EndOfRecord flag will be set accordingly
                    156:     by the caller to indicate that a message boundary was received.
                    157: 
                    158:     NOTE: This function is called with the connection and cancel
                    159:     IRQLs held, and returns with them released.
                    160: 
                    161: Arguments:
                    162: 
                    163:     Connection - Pointer to a TP_CONNECTION object.
                    164: 
                    165:     EndOfRecord - BOOLEAN set to true if TDI_END_OF_RECORD should be reported.
                    166: 
                    167:     ConnectionIrql - The IRQL at which the connection spinlock was acquired.
                    168: 
                    169:     CancelIrql - The IRQL at which the cancel spinlock was acquired.
                    170: 
                    171: Return Value:
                    172: 
                    173:     none.
                    174: 
                    175: --*/
                    176: 
                    177: {
                    178:     PLIST_ENTRY p;
                    179:     PTP_REQUEST Request;
                    180:     KIRQL oldirql = ConnectionIrql;
                    181:     KIRQL cancelirql = CancelIrql;
                    182:     ULONG BytesReceived;
                    183: 
                    184: 
                    185:     if (IsListEmpty (&Connection->ReceiveQueue)) {
                    186: 
                    187:         ASSERT ((Connection->Flags & CONNECTION_FLAGS_STOPPING) != 0);
                    188: 
                    189:         RELEASE_SPIN_LOCK (&Connection->SpinLock, oldirql);
                    190:         IoReleaseCancelSpinLock(cancelirql);
                    191:         return;
                    192:     }
                    193: 
                    194:     Connection->Flags &= ~CONNECTION_FLAGS_ACTIVE_RECEIVE;
                    195:     BytesReceived = Connection->MessageBytesReceived;
                    196: 
                    197: 
                    198:     //
                    199:     // Complete the TdiReceive request at the head of the
                    200:     // connection's ReceiveQueue.
                    201:     //
                    202: 
                    203:     p = RemoveHeadList (&Connection->ReceiveQueue);
                    204:     Request = CONTAINING_RECORD (p, TP_REQUEST, Linkage);
                    205: 
                    206:     Request->IoRequestPacket->CancelRoutine = (PDRIVER_CANCEL)NULL;
                    207: 
                    208:     RELEASE_SPIN_LOCK (&Connection->SpinLock, oldirql);
                    209:     IoReleaseCancelSpinLock(cancelirql);
                    210: 
                    211: 
                    212:     Request->Flags |= REQUEST_FLAGS_DELAY;
                    213: 
                    214:     StCompleteRequest(
                    215:         Request,
                    216:         EndOfRecord ? STATUS_SUCCESS : STATUS_BUFFER_OVERFLOW,
                    217:         BytesReceived);
                    218: 
                    219: } /* CompleteReceive */
                    220: 
                    221: 
                    222: VOID
                    223: StCancelReceive(
                    224:     IN PDEVICE_OBJECT DeviceObject,
                    225:     IN PIRP Irp
                    226:     )
                    227: 
                    228: /*++
                    229: 
                    230: Routine Description:
                    231: 
                    232:     This routine is called by the I/O system to cancel a receive.
                    233:     The receive is found on the connection's receive queue; if it
                    234:     is the current request it is cancelled and the connection
                    235:     goes into "cancelled receive" mode, otherwise it is cancelled
                    236:     silently.
                    237: 
                    238:     In "cancelled receive" mode the connection makes it appear to
                    239:     the remote the data is being received, but in fact it is not
                    240:     indicated to the transport or buffered on our end
                    241: 
                    242:     NOTE: This routine is called with the CancelSpinLock held and
                    243:     is responsible for releasing it.
                    244: 
                    245: Arguments:
                    246: 
                    247:     DeviceObject - Pointer to the device object for this driver.
                    248: 
                    249:     Irp - Pointer to the request packet representing the I/O request.
                    250: 
                    251: Return Value:
                    252: 
                    253:     none.
                    254: 
                    255: --*/
                    256: 
                    257: {
                    258:     KIRQL oldirql;
                    259:     PIO_STACK_LOCATION IrpSp;
                    260:     PTP_CONNECTION Connection;
                    261:     PTP_REQUEST Request;
                    262:     PLIST_ENTRY p;
                    263:     ULONG BytesReceived;
                    264:     BOOLEAN Found;
                    265: 
                    266:     UNREFERENCED_PARAMETER (DeviceObject);
                    267: 
                    268:     //
                    269:     // Get a pointer to the current stack location in the IRP.  This is where
                    270:     // the function codes and parameters are stored.
                    271:     //
                    272: 
                    273:     IrpSp = IoGetCurrentIrpStackLocation (Irp);
                    274: 
                    275:     ASSERT ((IrpSp->MajorFunction == IRP_MJ_INTERNAL_DEVICE_CONTROL) &&
                    276:             (IrpSp->MinorFunction == TDI_RECEIVE));
                    277: 
                    278:     Connection = IrpSp->FileObject->FsContext;
                    279: 
                    280:     //
                    281:     // Since this IRP is still in the cancellable state, we know
                    282:     // that the connection is still around (although it may be in
                    283:     // the process of being torn down).
                    284:     //
                    285: 
                    286:     //
                    287:     // See if this is the IRP for the current receive request.
                    288:     //
                    289: 
                    290:     ACQUIRE_SPIN_LOCK (&Connection->SpinLock, &oldirql);
                    291: 
                    292:     BytesReceived = Connection->MessageBytesReceived;
                    293: 
                    294:     p = Connection->ReceiveQueue.Flink;
                    295: 
                    296:     //
                    297:     // If there is a receive active, then see if this is it.
                    298:     //
                    299: 
                    300:     if ((Connection->Flags & CONNECTION_FLAGS_ACTIVE_RECEIVE) != 0) {
                    301: 
                    302:         Request = CONTAINING_RECORD (p, TP_REQUEST, Linkage);
                    303: 
                    304:         if (Request->IoRequestPacket == Irp) {
                    305: 
                    306:             //
                    307:             // yes, it is the active receive. Turn on the RCV_CANCELLED
                    308:             // bit instructing the connection to drop the rest of the
                    309:             // data received (until the DOL comes in).
                    310:             //
                    311: 
                    312:             Connection->Flags2 |= CONNECTION_FLAGS2_RCV_CANCELLED;
                    313:             Connection->Flags &= ~CONNECTION_FLAGS_ACTIVE_RECEIVE;
                    314: 
                    315:             (VOID)RemoveHeadList (&Connection->ReceiveQueue);
                    316: 
                    317:             RELEASE_SPIN_LOCK (&Connection->SpinLock, oldirql);
                    318:             IoReleaseCancelSpinLock (Irp->CancelIrql);
                    319: 
                    320:             //
                    321:             // The following dereference will complete the I/O, provided removes
                    322:             // the last reference on the request object.  The I/O will complete
                    323:             // with the status and information stored in the Irp.  Therefore,
                    324:             // we set those values here before the dereference.
                    325:             //
                    326: 
                    327:             StCompleteRequest (Request, STATUS_CANCELLED, 0);
                    328:             return;
                    329: 
                    330:         }
                    331: 
                    332:     }
                    333: 
                    334: 
                    335:     //
                    336:     // If we fall through to here, the IRP was not the active receive.
                    337:     // Scan through the list, looking for this IRP.
                    338:     //
                    339: 
                    340:     Found = FALSE;
                    341: 
                    342:     while (p != &Connection->ReceiveQueue) {
                    343: 
                    344:         Request = CONTAINING_RECORD (p, TP_REQUEST, Linkage);
                    345:         if (Request->IoRequestPacket == Irp) {
                    346: 
                    347:             //
                    348:             // Found it, remove it from the list here.
                    349:             //
                    350: 
                    351:             RemoveEntryList (p);
                    352:             Found = TRUE;
                    353: 
                    354:             RELEASE_SPIN_LOCK (&Connection->SpinLock, oldirql);
                    355:             IoReleaseCancelSpinLock (Irp->CancelIrql);
                    356: 
                    357:             //
                    358:             // The following dereference will complete the I/O, provided removes
                    359:             // the last reference on the request object.  The I/O will complete
                    360:             // with the status and information stored in the Irp.  Therefore,
                    361:             // we set those values here before the dereference.
                    362:             //
                    363: 
                    364:             StCompleteRequest (Request, STATUS_CANCELLED, 0);
                    365:             break;
                    366: 
                    367:         }
                    368: 
                    369:         p = p->Flink;
                    370: 
                    371:     }
                    372: 
                    373:     if (!Found) {
                    374: 
                    375:         //
                    376:         // We didn't find it!
                    377:         //
                    378: 
                    379:         RELEASE_SPIN_LOCK (&Connection->SpinLock, oldirql);
                    380:         IoReleaseCancelSpinLock (Irp->CancelIrql);
                    381:     }
                    382: 
                    383: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.