Annotation of ntddk/src/network/tdi/rcveng.c, revision 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.