2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS TCP/IP protocol driver
4 * FILE: transport/datagram/datagram.c
5 * PURPOSE: Routines for sending and receiving datagrams
6 * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
8 * CSH 01/08-2000 Created
14 PADDRESS_FILE AddrFile
,
15 PIP_ADDRESS SrcAddress
,
16 PIP_ADDRESS DstAddress
,
22 * FUNCTION: Delivers datagram data to a user
24 * AddrFile = Address file to deliver data to
25 * Address = Remote address the packet came from
26 * IPPacket = Pointer to IP packet to deliver
27 * DataSize = Number of bytes in data area
28 * (incl. IP header for raw IP file objects)
30 * If there is a receive request, then we copy the data to the
31 * buffer supplied by the user and complete the receive request.
32 * If no suitable receive request exists, then we call the event
33 * handler if it exists, otherwise we drop the packet.
37 PTDI_IND_RECEIVE_DATAGRAM ReceiveHandler
;
45 TI_DbgPrint(MAX_TRACE
, ("Called.\n"));
47 TcpipAcquireSpinLock(&AddrFile
->Lock
, &OldIrql
);
49 if (AddrFile
->Protocol
== IPPROTO_UDP
)
51 DataBuffer
= IPPacket
->Data
;
55 /* Give client the IP header too if it is a raw IP file object */
56 DataBuffer
= IPPacket
->Header
;
59 if (!IsListEmpty(&AddrFile
->ReceiveQueue
))
61 PLIST_ENTRY CurrentEntry
;
62 PDATAGRAM_RECEIVE_REQUEST Current
= NULL
;
64 PTA_IP_ADDRESS RTAIPAddress
;
66 TI_DbgPrint(MAX_TRACE
, ("There is a receive request.\n"));
68 /* Search receive request list to find a match */
70 CurrentEntry
= AddrFile
->ReceiveQueue
.Flink
;
71 while((CurrentEntry
!= &AddrFile
->ReceiveQueue
) && (!Found
)) {
72 Current
= CONTAINING_RECORD(CurrentEntry
, DATAGRAM_RECEIVE_REQUEST
, ListEntry
);
74 if( DstPort
== AddrFile
->Port
) {
76 /* Remove the request from the queue */
77 RemoveEntryList(&Current
->ListEntry
);
80 CurrentEntry
= CurrentEntry
->Flink
;
84 TcpipReleaseSpinLock(&AddrFile
->Lock
, OldIrql
);
88 TI_DbgPrint(MAX_TRACE
, ("Suitable receive request found.\n"));
90 TI_DbgPrint(MAX_TRACE
,
91 ("Target Buffer: %x, Source Buffer: %x, Size %d\n",
92 Current
->Buffer
, DataBuffer
, DataSize
));
94 /* Copy the data into buffer provided by the user */
95 RtlCopyMemory( Current
->Buffer
,
99 RTAIPAddress
= (PTA_IP_ADDRESS
)Current
->ReturnInfo
->RemoteAddress
;
100 RTAIPAddress
->TAAddressCount
= 1;
101 RTAIPAddress
->Address
->AddressType
= TDI_ADDRESS_TYPE_IP
;
102 RTAIPAddress
->Address
->Address
->sin_port
= SrcPort
;
104 TI_DbgPrint(MAX_TRACE
, ("(A: %08x) Addr %08x Port %04x\n",
106 SrcAddress
->Address
.IPv4Address
, SrcPort
));
108 RtlCopyMemory( &RTAIPAddress
->Address
->Address
->in_addr
,
109 &SrcAddress
->Address
.IPv4Address
,
110 sizeof(SrcAddress
->Address
.IPv4Address
) );
112 /* Complete the receive request */
113 Current
->Complete(Current
->Context
, STATUS_SUCCESS
, DataSize
);
116 else if (AddrFile
->RegisteredReceiveDatagramHandler
)
118 TI_DbgPrint(MAX_TRACE
, ("Calling receive event handler.\n"));
120 ReceiveHandler
= AddrFile
->ReceiveDatagramHandler
;
121 HandlerContext
= AddrFile
->ReceiveDatagramHandlerContext
;
123 TcpipReleaseSpinLock(&AddrFile
->Lock
, OldIrql
);
125 if (SrcAddress
->Type
== IP_ADDRESS_V4
)
127 AddressLength
= sizeof(IPv4_RAW_ADDRESS
);
128 SourceAddress
= &SrcAddress
->Address
.IPv4Address
;
130 else /* (Address->Type == IP_ADDRESS_V6) */
132 AddressLength
= sizeof(IPv6_RAW_ADDRESS
);
133 SourceAddress
= SrcAddress
->Address
.IPv6Address
;
136 Status
= (*ReceiveHandler
)(HandlerContext
,
141 TDI_RECEIVE_ENTIRE_MESSAGE
,
150 TI_DbgPrint(MAX_TRACE
, ("Discarding datagram.\n"));
153 TI_DbgPrint(MAX_TRACE
, ("Leaving.\n"));