1 /** @file
2
3 A brief file description
4
5 @section license License
6
7 Licensed to the Apache Software Foundation (ASF) under one
8 or more contributor license agreements. See the NOTICE file
9 distributed with this work for additional information
10 regarding copyright ownership. The ASF licenses this file
11 to you under the Apache License, Version 2.0 (the
12 "License"); you may not use this file except in compliance
13 with the License. You may obtain a copy of the License at
14
15 http://www.apache.org/licenses/LICENSE-2.0
16
17 Unless required by applicable law or agreed to in writing, software
18 distributed under the License is distributed on an "AS IS" BASIS,
19 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20 See the License for the specific language governing permissions and
21 limitations under the License.
22 */
23
24 /****************************************************************************
25
26 P_UDPPacket.h
27 Implementation of UDPPacket
28
29 ****************************************************************************/
30
31 #pragma once
32
33 #include "I_UDPNet.h"
34
35 class UDPPacketInternal : public UDPPacket
36 {
37 public:
38 UDPPacketInternal();
39 ~UDPPacketInternal() override;
40
41 void free() override;
42
43 SLINK(UDPPacketInternal, alink); // atomic link
44 // packet scheduling stuff: keep it a doubly linked list
45 uint64_t pktLength = 0;
46
47 int reqGenerationNum = 0;
48 ink_hrtime delivery_time = 0; // when to deliver packet
49
50 Ptr<IOBufferBlock> chain;
51 Continuation *cont = nullptr; // callback on error
52 UDPConnectionInternal *conn = nullptr; // connection where packet should be sent to.
53
54 int in_the_priority_queue = 0;
55 int in_heap = 0;
56 };
57
58 inkcoreapi extern ClassAllocator<UDPPacketInternal> udpPacketAllocator;
59
60 TS_INLINE
UDPPacketInternal()61 UDPPacketInternal::UDPPacketInternal()
62
63 {
64 memset(&from, '\0', sizeof(from));
65 memset(&to, '\0', sizeof(to));
66 }
67
68 TS_INLINE
~UDPPacketInternal()69 UDPPacketInternal::~UDPPacketInternal()
70 {
71 chain = nullptr;
72 }
73
74 TS_INLINE void
free()75 UDPPacketInternal::free()
76 {
77 chain = nullptr;
78 if (conn)
79 conn->Release();
80 conn = nullptr;
81 udpPacketAllocator.free(this);
82 }
83
84 TS_INLINE void
append_block(IOBufferBlock * block)85 UDPPacket::append_block(IOBufferBlock *block)
86 {
87 UDPPacketInternal *p = static_cast<UDPPacketInternal *>(this);
88
89 if (block) {
90 if (p->chain) { // append to end
91 IOBufferBlock *last = p->chain.get();
92 while (last->next) {
93 last = last->next.get();
94 }
95 last->next = block;
96 } else {
97 p->chain = block;
98 }
99 }
100 }
101
102 TS_INLINE int64_t
getPktLength()103 UDPPacket::getPktLength() const
104 {
105 UDPPacketInternal *p = const_cast<UDPPacketInternal *>(static_cast<const UDPPacketInternal *>(this));
106 IOBufferBlock *b;
107
108 p->pktLength = 0;
109 b = p->chain.get();
110 while (b) {
111 p->pktLength += b->read_avail();
112 b = b->next.get();
113 }
114 return p->pktLength;
115 }
116
117 TS_INLINE void
free()118 UDPPacket::free()
119 {
120 static_cast<UDPPacketInternal *>(this)->free();
121 }
122
123 TS_INLINE void
setContinuation(Continuation * c)124 UDPPacket::setContinuation(Continuation *c)
125 {
126 static_cast<UDPPacketInternal *>(this)->cont = c;
127 }
128
129 TS_INLINE void
setConnection(UDPConnection * c)130 UDPPacket::setConnection(UDPConnection *c)
131 {
132 /*Code reviewed by Case Larsen. Previously, we just had
133 ink_assert(!conn). This prevents tunneling of packets
134 correctly---that is, you get packets from a server on a udp
135 conn. and want to send it to a player on another connection, the
136 assert will prevent that. The "if" clause enables correct
137 handling of the connection ref. counts in such a scenario. */
138
139 UDPConnectionInternal *&conn = static_cast<UDPPacketInternal *>(this)->conn;
140
141 if (conn) {
142 if (conn == c)
143 return;
144 conn->Release();
145 conn = nullptr;
146 }
147 conn = static_cast<UDPConnectionInternal *>(c);
148 conn->AddRef();
149 }
150
151 TS_INLINE IOBufferBlock *
getIOBlockChain()152 UDPPacket::getIOBlockChain()
153 {
154 ink_assert(dynamic_cast<UDPPacketInternal *>(this) != nullptr);
155 return static_cast<UDPPacketInternal *>(this)->chain.get();
156 }
157
158 TS_INLINE UDPConnection *
getConnection()159 UDPPacket::getConnection()
160 {
161 return static_cast<UDPPacketInternal *>(this)->conn;
162 }
163
164 TS_INLINE UDPPacket *
new_UDPPacket(struct sockaddr const * to,ink_hrtime when,Ptr<IOBufferBlock> & buf)165 new_UDPPacket(struct sockaddr const *to, ink_hrtime when, Ptr<IOBufferBlock> &buf)
166 {
167 UDPPacketInternal *p = udpPacketAllocator.alloc();
168
169 p->in_the_priority_queue = 0;
170 p->in_heap = 0;
171 p->delivery_time = when;
172 if (to)
173 ats_ip_copy(&p->to, to);
174 p->chain = buf;
175 return p;
176 }
177
178 TS_INLINE UDPPacket *
new_incoming_UDPPacket(struct sockaddr * from,struct sockaddr * to,Ptr<IOBufferBlock> & block)179 new_incoming_UDPPacket(struct sockaddr *from, struct sockaddr *to, Ptr<IOBufferBlock> &block)
180 {
181 UDPPacketInternal *p = udpPacketAllocator.alloc();
182
183 p->in_the_priority_queue = 0;
184 p->in_heap = 0;
185 p->delivery_time = 0;
186 ats_ip_copy(&p->from, from);
187 ats_ip_copy(&p->to, to);
188 p->chain = block;
189
190 return p;
191 }
192
193 TS_INLINE UDPPacket *
new_UDPPacket()194 new_UDPPacket()
195 {
196 UDPPacketInternal *p = udpPacketAllocator.alloc();
197 return p;
198 }
199