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

1.1       root        1: /*++
                      2: 
                      3: Copyright (c) 1989-1993  Microsoft Corporation
                      4: 
                      5: Module Name:
                      6: 
                      7:     send.c
                      8: 
                      9: Abstract:
                     10: 
                     11:     This module contains code which performs the following TDI services:
                     12: 
                     13:         o   TdiSend
                     14:         o   TdiSendDatagram
                     15: 
                     16: Environment:
                     17: 
                     18:     Kernel mode
                     19: 
                     20: Revision History:
                     21: 
                     22: --*/
                     23: 
                     24: #include "st.h"
                     25: 
                     26: 
                     27: NTSTATUS
                     28: StTdiSend(
                     29:     IN PIRP Irp
                     30:     )
                     31: 
                     32: /*++
                     33: 
                     34: Routine Description:
                     35: 
                     36:     This routine performs the TdiSend request for the transport provider.
                     37: 
                     38: Arguments:
                     39: 
                     40:     Irp - Pointer to the I/O Request Packet for this request.
                     41: 
                     42: Return Value:
                     43: 
                     44:     NTSTATUS - status of operation.
                     45: 
                     46: --*/
                     47: 
                     48: {
                     49:     KIRQL oldirql, cancelirql;
                     50:     NTSTATUS status;
                     51:     PTP_CONNECTION connection;
                     52:     PMDL SendBuffer;
                     53:     ULONG SendBufferLength;
                     54:     PIO_STACK_LOCATION irpSp;
                     55:     PTDI_REQUEST_KERNEL_SEND parameters;
                     56:     PIRP TempIrp;
                     57: 
                     58:     //
                     59:     // Determine which connection this send belongs on.
                     60:     //
                     61: 
                     62:     irpSp = IoGetCurrentIrpStackLocation (Irp);
                     63:     connection  = irpSp->FileObject->FsContext;
                     64: 
                     65:     //
                     66:     // Check that this is really a connection.
                     67:     //
                     68: 
                     69:     if ((connection->Size != sizeof (TP_CONNECTION)) ||
                     70:         (connection->Type != ST_CONNECTION_SIGNATURE)) {
                     71:         return STATUS_INVALID_CONNECTION;
                     72:     }
                     73: 
                     74:     //
                     75:     // Now map the data in to SVA space.
                     76:     //
                     77: 
                     78:     parameters = (PTDI_REQUEST_KERNEL_SEND)(&irpSp->Parameters);
                     79:     SendBuffer = Irp->MdlAddress;
                     80:     SendBufferLength = parameters->SendLength;
                     81: 
                     82:     //
                     83:     // Interpret send options.
                     84:     //
                     85: 
                     86:     //
                     87:     // Now we have a reference on the connection object.  Queue up this
                     88:     // send to the connection object.
                     89:     //
                     90: 
                     91: 
                     92:     // This reference is removed by TdiDestroyRequest
                     93: 
                     94:     StReferenceConnection("TdiSend", connection);
                     95: 
                     96:     IRP_CONNECTION(irpSp) = connection;
                     97:     IRP_REFCOUNT(irpSp) = 1;
                     98: 
                     99:     IoAcquireCancelSpinLock(&cancelirql);
                    100:     ACQUIRE_SPIN_LOCK (&connection->SpinLock,&oldirql);
                    101: 
                    102:     if ((connection->Flags & CONNECTION_FLAGS_STOPPING) != 0) {
                    103:         RELEASE_SPIN_LOCK (&connection->SpinLock,oldirql);
                    104:         IoReleaseCancelSpinLock(cancelirql);
                    105:         StCompleteSendIrp(
                    106:             Irp,
                    107:             connection->Status,
                    108:             0);
                    109:         status = STATUS_PENDING;
                    110:     } else {
                    111: 
                    112:         StReferenceConnection ("Verify Temp Use", connection);
                    113: 
                    114:         //
                    115:         // Insert onto the send queue, and make the IRP
                    116:         // cancellable.
                    117:         //
                    118: 
                    119:         InsertTailList (&connection->SendQueue,&Irp->Tail.Overlay.ListEntry);
                    120: 
                    121: 
                    122:         //
                    123:         // If this IRP has been cancelled, then call the
                    124:         // cancel routine.
                    125:         //
                    126: 
                    127:         if (Irp->Cancel) {
                    128:             RELEASE_SPIN_LOCK (&connection->SpinLock,oldirql);
                    129:             Irp->CancelIrql = cancelirql;
                    130:             StCancelSend((PDEVICE_OBJECT)(connection->Provider), Irp);
                    131:             StDereferenceConnection ("IRP cancelled", connection);   // release lookup hold.
                    132:             return STATUS_PENDING;
                    133:         }
                    134: 
                    135:         Irp->CancelRoutine = StCancelSend;
                    136: 
                    137:         //
                    138:         // If this connection is waiting for an EOR to appear because a non-EOR
                    139:         // send failed at some point in the past, fail this send. Clear the
                    140:         // flag that causes this if this request has the EOR set.
                    141:         //
                    142:         // BUGBUG: Should the FailSend status be clearer here?
                    143:         //
                    144: 
                    145:         if ((connection->Flags & CONNECTION_FLAGS_FAILING_TO_EOR) != 0) {
                    146: 
                    147:             RELEASE_SPIN_LOCK (&connection->SpinLock,oldirql);
                    148:             IoReleaseCancelSpinLock(cancelirql);
                    149: 
                    150:             //
                    151:             // BUGBUG: Should we save status from real failure?
                    152:             //
                    153: 
                    154:             FailSend (connection, STATUS_LINK_FAILED, TRUE);
                    155: 
                    156:             if ( (parameters->SendFlags & TDI_SEND_PARTIAL) == 0) {
                    157:                 connection->Flags &= ~CONNECTION_FLAGS_FAILING_TO_EOR;
                    158:             }
                    159: 
                    160:             StDereferenceConnection ("Failing to EOR", connection);   // release lookup hold.
                    161:             return STATUS_PENDING;
                    162:         }
                    163: 
                    164: 
                    165:         //
                    166:         // If the send state is either IDLE or W_EOR, then we should
                    167:         // begin packetizing this send.  Otherwise, some other event
                    168:         // will cause it to be packetized.
                    169:         //
                    170: 
                    171:         //
                    172:         // NOTE: If we call StartPacketizingConnection, we make
                    173:         // sure that it is the last operation we do on this
                    174:         // connection. This allows us to "hand off" the reference
                    175:         // we have to that function, which converts it into
                    176:         // a reference for being on the packetize queue.
                    177:         //
                    178: 
                    179:         switch (connection->SendState) {
                    180: 
                    181:         case CONNECTION_SENDSTATE_IDLE:
                    182: 
                    183:             InitializeSend (connection);   // sets state to PACKETIZE
                    184: 
                    185:             //
                    186:             // If we can, packetize right now.
                    187:             //
                    188: 
                    189:             if ((!(connection->Flags & CONNECTION_FLAGS_PACKETIZE)) &&
                    190:                 (!(connection->Flags & CONNECTION_FLAGS_STOPPING))) {
                    191: 
                    192:                 connection->Flags |= CONNECTION_FLAGS_PACKETIZE;
                    193: 
                    194:                 RELEASE_SPIN_LOCK (&connection->SpinLock, oldirql);
                    195:                 IoReleaseCancelSpinLock(cancelirql);
                    196: 
                    197:                 PacketizeSend (connection);
                    198: 
                    199:             } else {
                    200: 
                    201:                 RELEASE_SPIN_LOCK (&connection->SpinLock, oldirql);
                    202:                 IoReleaseCancelSpinLock(cancelirql);
                    203: 
                    204:                 StDereferenceConnection ("Stopping or already packetizing", connection);   // release lookup hold.
                    205: 
                    206:             }
                    207: 
                    208:             break;
                    209: 
                    210:         case CONNECTION_SENDSTATE_W_EOR:
                    211:             connection->SendState = CONNECTION_SENDSTATE_PACKETIZE;
                    212: 
                    213:             //
                    214:             // Adjust the send variables on the connection so that
                    215:             // they correctly point to this new send.  We can't call
                    216:             // InitializeSend to do that, because we need to keep
                    217:             // track of the other outstanding sends on this connection
                    218:             // which have been sent but are a part of this message.
                    219:             //
                    220: 
                    221:             TempIrp = CONTAINING_RECORD(
                    222:                 connection->SendQueue.Flink,
                    223:                 IRP,
                    224:                 Tail.Overlay.ListEntry);
                    225: 
                    226:             connection->sp.CurrentSendIrp = TempIrp;
                    227:             connection->sp.CurrentSendMdl = TempIrp->MdlAddress;
                    228:             connection->sp.SendByteOffset = 0;
                    229:             connection->CurrentSendLength +=
                    230:                 IRP_SEND_LENGTH(IoGetCurrentIrpStackLocation(TempIrp));
                    231: 
                    232:             StartPacketizingConnection (connection, TRUE, oldirql, cancelirql);
                    233:             break;
                    234: 
                    235:         default:
                    236: 
                    237:             //
                    238:             // The connection is in another state (such as
                    239:             // W_ACK or W_LINK), we just need to make sure
                    240:             // to call InitializeSend if the new one is
                    241:             // the first one on the list.
                    242:             //
                    243: 
                    244:             //
                    245:             // BUGBUG: Currently InitializeSend sets SendState,
                    246:             // we should fix this.
                    247:             //
                    248: 
                    249:             if (connection->SendQueue.Flink == &Irp->Tail.Overlay.ListEntry) {
                    250:                 ULONG SavedSendState;
                    251:                 SavedSendState = connection->SendState;
                    252:                 InitializeSend (connection);
                    253:                 connection->SendState = SavedSendState;
                    254:             }
                    255:             RELEASE_SPIN_LOCK (&connection->SpinLock, oldirql);
                    256:             IoReleaseCancelSpinLock(cancelirql);
                    257: 
                    258:             StDereferenceConnection("temp TdiSend", connection);
                    259: 
                    260:         }
                    261: 
                    262:     }
                    263: 
                    264:     status = STATUS_PENDING;
                    265: 
                    266: 
                    267:     return status;
                    268: } /* TdiSend */
                    269: 
                    270: 
                    271: NTSTATUS
                    272: StTdiSendDatagram(
                    273:     IN PIRP Irp
                    274:     )
                    275: 
                    276: /*++
                    277: 
                    278: Routine Description:
                    279: 
                    280:     This routine performs the TdiSendDatagram request for the transport
                    281:     provider.
                    282: 
                    283: Arguments:
                    284: 
                    285:     Irp - Pointer to the I/O Request Packet for this request.
                    286: 
                    287: Return Value:
                    288: 
                    289:     NTSTATUS - status of operation.
                    290: 
                    291: --*/
                    292: 
                    293: {
                    294:     NTSTATUS status;
                    295:     KIRQL oldirql;
                    296:     PTP_REQUEST tpRequest;
                    297:     PTP_ADDRESS_FILE addressFile;
                    298:     PTP_ADDRESS address;
                    299:     PMDL SendBuffer;
                    300:     ULONG SendBufferLength;
                    301:     PIO_STACK_LOCATION irpSp;
                    302:     PTDI_REQUEST_KERNEL_SENDDG parameters;
                    303:     LARGE_INTEGER timeout = {0,0};
                    304:     UINT MaxUserData;
                    305: 
                    306:     irpSp = IoGetCurrentIrpStackLocation (Irp);
                    307:     addressFile  = irpSp->FileObject->FsContext;
                    308: 
                    309:     status = StVerifyAddressObject (addressFile);
                    310:     if (!NT_SUCCESS (status)) {
                    311:         return status;
                    312:     }
                    313: 
                    314:     address = addressFile->Address;
                    315:     parameters = (PTDI_REQUEST_KERNEL_SENDDG)(&irpSp->Parameters);
                    316:     SendBuffer = Irp->MdlAddress;
                    317:     SendBufferLength = parameters->SendLength;
                    318: 
                    319:     //
                    320:     // Check that the length is short enough.
                    321:     //
                    322: 
                    323:     MacReturnMaxDataSize(
                    324:         &address->Provider->MacInfo,
                    325:         NULL,
                    326:         0,
                    327:         address->Provider->MaxSendPacketSize,
                    328:         &MaxUserData);
                    329: 
                    330:     if (SendBufferLength >
                    331:         (MaxUserData - sizeof(ST_HEADER))) {
                    332: 
                    333:         return STATUS_INVALID_PARAMETER;
                    334: 
                    335:     }
                    336: 
                    337:     //
                    338:     // We need a request object to keep track of this TDI request.
                    339:     // Attach this request to the address object.
                    340:     //
                    341: 
                    342:     status = StCreateRequest (
                    343:                  Irp,                           // IRP for this request.
                    344:                  address,                       // context.
                    345:                  REQUEST_FLAGS_ADDRESS,         // partial flags.
                    346:                  SendBuffer,                    // the data to be sent.
                    347:                  SendBufferLength,              // length of the data.
                    348:                  timeout,
                    349:                  &tpRequest);
                    350: 
                    351:     if (!NT_SUCCESS (status)) {
                    352:         StDereferenceAddress ("no send request", address);
                    353:         return status;                          // if we couldn't queue the request.
                    354:     }
                    355: 
                    356:     StReferenceAddress ("Send datagram", address);
                    357:     tpRequest->Owner = AddressType;
                    358: 
                    359:     ACQUIRE_SPIN_LOCK (&address->SpinLock,&oldirql);
                    360: 
                    361:     if ((address->Flags & ADDRESS_FLAGS_STOPPING) != 0) {
                    362:         RELEASE_SPIN_LOCK (&address->SpinLock,oldirql);
                    363:         StCompleteRequest (tpRequest, STATUS_NETWORK_NAME_DELETED, 0);
                    364:         return STATUS_PENDING;
                    365:     } else {
                    366:         InsertTailList (
                    367:             &address->SendDatagramQueue,
                    368:             &tpRequest->Linkage);
                    369:         RELEASE_SPIN_LOCK (&address->SpinLock,oldirql);
                    370:     }
                    371: 
                    372:     //
                    373:     // The request is queued.  Ship the next request at the head of the queue,
                    374:     // provided the completion handler is not active.  We serialize this so
                    375:     // that only one MDL and ST datagram header needs to be statically
                    376:     // allocated for reuse by all send datagram requests.
                    377:     //
                    378: 
                    379:     (VOID)StSendDatagramsOnAddress (address);
                    380: 
                    381:     StDereferenceAddress("tmp send datagram", address);
                    382: 
                    383:     return STATUS_PENDING;
                    384: 
                    385: } /* StTdiSendDatagram */

unix.superglobalmegacorp.com

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