Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygendatagram.c
Go to the documentation of this file.
00001 /* 00002 * COPYRIGHT: See COPYING in the top level directory 00003 * PROJECT: ReactOS TCP/IP protocol driver 00004 * FILE: transport/datagram/datagram.c 00005 * PURPOSE: Routines for sending and receiving datagrams 00006 * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net) 00007 * REVISIONS: 00008 * CSH 01/08-2000 Created 00009 */ 00010 00011 #include "precomp.h" 00012 00013 BOOLEAN DGRemoveIRP( 00014 PADDRESS_FILE AddrFile, 00015 PIRP Irp) 00016 { 00017 PLIST_ENTRY ListEntry; 00018 PDATAGRAM_RECEIVE_REQUEST ReceiveRequest; 00019 KIRQL OldIrql; 00020 BOOLEAN Found = FALSE; 00021 00022 TI_DbgPrint(MAX_TRACE, ("Called (Cancel IRP %08x for file %08x).\n", 00023 Irp, AddrFile)); 00024 00025 LockObject(AddrFile, &OldIrql); 00026 00027 for( ListEntry = AddrFile->ReceiveQueue.Flink; 00028 ListEntry != &AddrFile->ReceiveQueue; 00029 ListEntry = ListEntry->Flink ) 00030 { 00031 ReceiveRequest = CONTAINING_RECORD 00032 (ListEntry, DATAGRAM_RECEIVE_REQUEST, ListEntry); 00033 00034 TI_DbgPrint(MAX_TRACE, ("Request: %08x?\n", ReceiveRequest)); 00035 00036 if (ReceiveRequest->Irp == Irp) 00037 { 00038 RemoveEntryList(&ReceiveRequest->ListEntry); 00039 ExFreePoolWithTag(ReceiveRequest, DATAGRAM_RECV_TAG); 00040 Found = TRUE; 00041 break; 00042 } 00043 } 00044 00045 UnlockObject(AddrFile, OldIrql); 00046 00047 TI_DbgPrint(MAX_TRACE, ("Done.\n")); 00048 00049 return Found; 00050 } 00051 00052 VOID DGDeliverData( 00053 PADDRESS_FILE AddrFile, 00054 PIP_ADDRESS SrcAddress, 00055 PIP_ADDRESS DstAddress, 00056 USHORT SrcPort, 00057 USHORT DstPort, 00058 PIP_PACKET IPPacket, 00059 UINT DataSize) 00060 /* 00061 * FUNCTION: Delivers datagram data to a user 00062 * ARGUMENTS: 00063 * AddrFile = Address file to deliver data to 00064 * Address = Remote address the packet came from 00065 * IPPacket = Pointer to IP packet to deliver 00066 * DataSize = Number of bytes in data area 00067 * (incl. IP header for raw IP file objects) 00068 * NOTES: 00069 * If there is a receive request, then we copy the data to the 00070 * buffer supplied by the user and complete the receive request. 00071 * If no suitable receive request exists, then we call the event 00072 * handler if it exists, otherwise we drop the packet. 00073 */ 00074 { 00075 KIRQL OldIrql; 00076 PTDI_IND_RECEIVE_DATAGRAM ReceiveHandler; 00077 PVOID HandlerContext; 00078 LONG AddressLength; 00079 PVOID SourceAddress; 00080 ULONG BytesTaken; 00081 NTSTATUS Status; 00082 PVOID DataBuffer; 00083 00084 TI_DbgPrint(MAX_TRACE, ("Called.\n")); 00085 00086 LockObject(AddrFile, &OldIrql); 00087 00088 if (AddrFile->Protocol == IPPROTO_UDP) 00089 { 00090 DataBuffer = IPPacket->Data; 00091 } 00092 else 00093 { 00094 if (AddrFile->HeaderIncl) 00095 DataBuffer = IPPacket->Header; 00096 else 00097 { 00098 DataBuffer = IPPacket->Data; 00099 DataSize -= IPPacket->HeaderSize; 00100 } 00101 } 00102 00103 if (!IsListEmpty(&AddrFile->ReceiveQueue)) 00104 { 00105 PLIST_ENTRY CurrentEntry; 00106 PDATAGRAM_RECEIVE_REQUEST Current = NULL; 00107 PTA_IP_ADDRESS RTAIPAddress; 00108 00109 TI_DbgPrint(MAX_TRACE, ("There is a receive request.\n")); 00110 00111 /* Search receive request list to find a match */ 00112 CurrentEntry = AddrFile->ReceiveQueue.Flink; 00113 while(CurrentEntry != &AddrFile->ReceiveQueue) { 00114 Current = CONTAINING_RECORD(CurrentEntry, DATAGRAM_RECEIVE_REQUEST, ListEntry); 00115 CurrentEntry = CurrentEntry->Flink; 00116 if( DstPort == AddrFile->Port && 00117 (AddrIsEqual(DstAddress, &AddrFile->Address) || 00118 AddrIsUnspecified(&AddrFile->Address) || 00119 AddrIsUnspecified(DstAddress))) { 00120 00121 /* Remove the request from the queue */ 00122 RemoveEntryList(&Current->ListEntry); 00123 00124 TI_DbgPrint(MAX_TRACE, ("Suitable receive request found.\n")); 00125 00126 TI_DbgPrint(MAX_TRACE, 00127 ("Target Buffer: %x, Source Buffer: %x, Size %d\n", 00128 Current->Buffer, DataBuffer, DataSize)); 00129 00130 /* Copy the data into buffer provided by the user */ 00131 RtlCopyMemory( Current->Buffer, 00132 DataBuffer, 00133 MIN(Current->BufferSize, DataSize) ); 00134 00135 RTAIPAddress = (PTA_IP_ADDRESS)Current->ReturnInfo->RemoteAddress; 00136 RTAIPAddress->TAAddressCount = 1; 00137 RTAIPAddress->Address->AddressType = TDI_ADDRESS_TYPE_IP; 00138 RTAIPAddress->Address->AddressLength = TDI_ADDRESS_LENGTH_IP; 00139 RTAIPAddress->Address->Address->sin_port = SrcPort; 00140 RTAIPAddress->Address->Address->in_addr = SrcAddress->Address.IPv4Address; 00141 RtlZeroMemory(RTAIPAddress->Address->Address->sin_zero, 8); 00142 00143 TI_DbgPrint(MAX_TRACE, ("(A: %08x) Addr %08x Port %04x\n", 00144 RTAIPAddress, 00145 SrcAddress->Address.IPv4Address, SrcPort)); 00146 00147 ReferenceObject(AddrFile); 00148 UnlockObject(AddrFile, OldIrql); 00149 00150 /* Complete the receive request */ 00151 if (Current->BufferSize < DataSize) 00152 Current->Complete(Current->Context, STATUS_BUFFER_OVERFLOW, Current->BufferSize); 00153 else 00154 Current->Complete(Current->Context, STATUS_SUCCESS, DataSize); 00155 00156 LockObject(AddrFile, &OldIrql); 00157 DereferenceObject(AddrFile); 00158 } 00159 } 00160 00161 UnlockObject(AddrFile, OldIrql); 00162 } 00163 else if (AddrFile->RegisteredReceiveDatagramHandler) 00164 { 00165 TI_DbgPrint(MAX_TRACE, ("Calling receive event handler.\n")); 00166 00167 ReceiveHandler = AddrFile->ReceiveDatagramHandler; 00168 HandlerContext = AddrFile->ReceiveDatagramHandlerContext; 00169 00170 if (SrcAddress->Type == IP_ADDRESS_V4) 00171 { 00172 AddressLength = sizeof(IPv4_RAW_ADDRESS); 00173 SourceAddress = &SrcAddress->Address.IPv4Address; 00174 } 00175 else /* (Address->Type == IP_ADDRESS_V6) */ 00176 { 00177 AddressLength = sizeof(IPv6_RAW_ADDRESS); 00178 SourceAddress = SrcAddress->Address.IPv6Address; 00179 } 00180 00181 ReferenceObject(AddrFile); 00182 UnlockObject(AddrFile, OldIrql); 00183 00184 Status = (*ReceiveHandler)(HandlerContext, 00185 AddressLength, 00186 SourceAddress, 00187 0, 00188 NULL, 00189 TDI_RECEIVE_ENTIRE_MESSAGE, 00190 DataSize, 00191 DataSize, 00192 &BytesTaken, 00193 DataBuffer, 00194 NULL); 00195 00196 if (STATUS_SUCCESS != Status) 00197 TI_DbgPrint(MAX_TRACE, ("receive handler signaled failure with Status 0x%x\n", Status)); 00198 00199 DereferenceObject(AddrFile); 00200 } 00201 else 00202 { 00203 UnlockObject(AddrFile, OldIrql); 00204 TI_DbgPrint(MAX_TRACE, ("Discarding datagram.\n")); 00205 } 00206 00207 TI_DbgPrint(MAX_TRACE, ("Leaving.\n")); 00208 } 00209 00210 00211 VOID DGReceiveComplete(PVOID Context, NTSTATUS Status, ULONG Count) { 00212 PDATAGRAM_RECEIVE_REQUEST ReceiveRequest = 00213 (PDATAGRAM_RECEIVE_REQUEST)Context; 00214 TI_DbgPrint(MAX_TRACE,("Called (%08x:%08x)\n", Status, Count)); 00215 ReceiveRequest->UserComplete( ReceiveRequest->UserContext, Status, Count ); 00216 ExFreePoolWithTag( ReceiveRequest, DATAGRAM_RECV_TAG ); 00217 TI_DbgPrint(MAX_TRACE,("Done\n")); 00218 } 00219 00220 NTSTATUS DGReceiveDatagram( 00221 PADDRESS_FILE AddrFile, 00222 PTDI_CONNECTION_INFORMATION ConnInfo, 00223 PCHAR BufferData, 00224 ULONG ReceiveLength, 00225 ULONG ReceiveFlags, 00226 PTDI_CONNECTION_INFORMATION ReturnInfo, 00227 PULONG BytesReceived, 00228 PDATAGRAM_COMPLETION_ROUTINE Complete, 00229 PVOID Context, 00230 PIRP Irp) 00231 /* 00232 * FUNCTION: Attempts to receive an DG datagram from a remote address 00233 * ARGUMENTS: 00234 * Request = Pointer to TDI request 00235 * ConnInfo = Pointer to connection information 00236 * Buffer = Pointer to NDIS buffer chain to store received data 00237 * ReceiveLength = Maximum size to use of buffer, 0 if all can be used 00238 * ReceiveFlags = Receive flags (None, Normal, Peek) 00239 * ReturnInfo = Pointer to structure for return information 00240 * BytesReceive = Pointer to structure for number of bytes received 00241 * RETURNS: 00242 * Status of operation 00243 * NOTES: 00244 * This is the high level interface for receiving DG datagrams 00245 */ 00246 { 00247 NTSTATUS Status; 00248 PDATAGRAM_RECEIVE_REQUEST ReceiveRequest; 00249 KIRQL OldIrql; 00250 00251 TI_DbgPrint(MAX_TRACE, ("Called.\n")); 00252 00253 LockObject(AddrFile, &OldIrql); 00254 00255 ReceiveRequest = ExAllocatePoolWithTag(NonPagedPool, sizeof(DATAGRAM_RECEIVE_REQUEST), 00256 DATAGRAM_RECV_TAG); 00257 if (ReceiveRequest) 00258 { 00259 /* Initialize a receive request */ 00260 00261 /* Extract the remote address filter from the request (if any) */ 00262 if ((ConnInfo->RemoteAddressLength != 0) && 00263 (ConnInfo->RemoteAddress)) 00264 { 00265 Status = AddrGetAddress(ConnInfo->RemoteAddress, 00266 &ReceiveRequest->RemoteAddress, 00267 &ReceiveRequest->RemotePort); 00268 if (!NT_SUCCESS(Status)) 00269 { 00270 ExFreePoolWithTag(ReceiveRequest, DATAGRAM_RECV_TAG); 00271 UnlockObject(AddrFile, OldIrql); 00272 return Status; 00273 } 00274 } 00275 else 00276 { 00277 ReceiveRequest->RemotePort = 0; 00278 AddrInitIPv4(&ReceiveRequest->RemoteAddress, 0); 00279 } 00280 00281 IoMarkIrpPending(Irp); 00282 00283 ReceiveRequest->ReturnInfo = ReturnInfo; 00284 ReceiveRequest->Buffer = BufferData; 00285 ReceiveRequest->BufferSize = ReceiveLength; 00286 ReceiveRequest->UserComplete = Complete; 00287 ReceiveRequest->UserContext = Context; 00288 ReceiveRequest->Complete = 00289 (PDATAGRAM_COMPLETION_ROUTINE)DGReceiveComplete; 00290 ReceiveRequest->Context = ReceiveRequest; 00291 ReceiveRequest->AddressFile = AddrFile; 00292 ReceiveRequest->Irp = Irp; 00293 00294 /* Queue receive request */ 00295 InsertTailList(&AddrFile->ReceiveQueue, &ReceiveRequest->ListEntry); 00296 00297 TI_DbgPrint(MAX_TRACE, ("Leaving (pending %08x).\n", ReceiveRequest)); 00298 00299 UnlockObject(AddrFile, OldIrql); 00300 00301 return STATUS_PENDING; 00302 } 00303 else 00304 { 00305 UnlockObject(AddrFile, OldIrql); 00306 Status = STATUS_INSUFFICIENT_RESOURCES; 00307 } 00308 00309 TI_DbgPrint(MAX_TRACE, ("Leaving with errors (0x%X).\n", Status)); 00310 00311 return Status; 00312 } Generated on Sat May 26 2012 04:34:54 for ReactOS by
1.7.6.1
|