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 #pragma once
25 
26 #include <string_view>
27 #include <string>
28 
29 #include "tscore/ink_platform.h"
30 #include "tscore/List.h"
31 #include "tscore/TsBuffer.h"
32 #include "LogFieldAliasMap.h"
33 #include "Milestones.h"
34 
35 class LogAccess;
36 
37 struct LogSlice {
38   bool m_enable;
39   int m_start;
40   int m_end;
41 
LogSliceLogSlice42   LogSlice()
43   {
44     m_enable = false;
45     m_start  = 0;
46     m_end    = INT_MAX;
47   }
48 
49   //
50   // Initialize LogSlice by slice notation,
51   // the str looks like: "xxx[0:30]".
52   //
53   explicit LogSlice(char *str);
54 
55   //
56   // Convert slice notation to target string's offset,
57   // return the available length belongs to this slice.
58   //
59   // Use the offset and return value, we can locate the
60   // string content indicated by this slice.
61   //
62   int toStrOffset(int strlen, int *offset);
63 };
64 
65 /*-------------------------------------------------------------------------
66   LogField
67 
68   This class represents a field that can be logged.  To construct a new
69   field, we need to know its name, its symbol, its datatype, and the
70   pointer to its LogAccess marshalling routine.  Example:
71 
72       LogField ("client_host_ip", "chi", LogField::INT,
73                 &LogAccess::marshal_client_host_ip);
74   -------------------------------------------------------------------------*/
75 
76 class LogField
77 {
78 public:
79   typedef int (LogAccess::*MarshalFunc)(char *buf);
80   typedef int (*UnmarshalFunc)(char **buf, char *dest, int len);
81   typedef int (*UnmarshalFuncWithSlice)(char **buf, char *dest, int len, LogSlice *slice);
82   typedef int (*UnmarshalFuncWithMap)(char **buf, char *dest, int len, const Ptr<LogFieldAliasMap> &map);
83   typedef void (LogAccess::*SetFunc)(char *buf, int len);
84 
85   enum Type {
86     sINT = 0,
87     dINT,
88     STRING,
89     IP, ///< IP Address.
90     N_TYPES
91   };
92 
93   enum Container {
94     NO_CONTAINER = 0,
95     CQH,
96     PSH,
97     PQH,
98     SSH,
99     CSSH,
100     ECQH,
101     EPSH,
102     EPQH,
103     ESSH,
104     ECSSH,
105     ICFG,
106     SCFG,
107     RECORD,
108     MS,
109     MSDMS,
110     N_CONTAINERS,
111   };
112 
113   enum Aggregate {
114     NO_AGGREGATE = 0,
115     eCOUNT,
116     eSUM,
117     eAVG,
118     eFIRST,
119     eLAST,
120     N_AGGREGATES,
121   };
122 
123   LogField(const char *name, const char *symbol, Type type, MarshalFunc marshal, UnmarshalFunc unmarshal,
124            SetFunc _setFunc = nullptr);
125 
126   LogField(const char *name, const char *symbol, Type type, MarshalFunc marshal, UnmarshalFuncWithMap unmarshal,
127            const Ptr<LogFieldAliasMap> &map, SetFunc _setFunc = nullptr);
128 
129   LogField(const char *field, Container container, SetFunc _setFunc = nullptr);
130   LogField(const LogField &rhs);
131   ~LogField();
132 
133   unsigned marshal_len(LogAccess *lad);
134   unsigned marshal(LogAccess *lad, char *buf);
135   unsigned marshal_agg(char *buf);
136   unsigned unmarshal(char **buf, char *dest, int len);
137   void display(FILE *fd = stdout);
138   bool operator==(LogField &rhs);
139   void updateField(LogAccess *lad, char *val, int len);
140 
141   const char *
name()142   name() const
143   {
144     return m_name;
145   }
146 
147   const char *
symbol()148   symbol() const
149   {
150     return m_symbol;
151   }
152 
153   Type
type()154   type() const
155   {
156     return m_type;
157   }
158 
159   Ptr<LogFieldAliasMap>
map()160   map()
161   {
162     return m_alias_map;
163   }
164 
165   Aggregate
aggregate()166   aggregate() const
167   {
168     return m_agg_op;
169   }
170 
171   bool
is_time_field()172   is_time_field() const
173   {
174     return m_time_field;
175   }
176 
177   inkcoreapi void set_http_header_field(LogAccess *lad, LogField::Container container, char *field, char *buf, int len);
178   void set_aggregate_op(Aggregate agg_op);
179   void update_aggregate(int64_t val);
180 
181   static void init_milestone_container();
182   static Container valid_container_name(char *name);
183   static Aggregate valid_aggregate_name(char *name);
184   static bool fieldlist_contains_aggregates(const char *fieldlist);
185   static bool isContainerUpdateFieldSupported(Container container);
186 
187 private:
188   char *m_name;
189   char *m_symbol;
190   Type m_type;
191   Container m_container;
192   MarshalFunc m_marshal_func;     // place data into buffer
193   UnmarshalFunc m_unmarshal_func; // create a string of the data
194   UnmarshalFuncWithMap m_unmarshal_func_map;
195   Aggregate m_agg_op;
196   int64_t m_agg_cnt;
197   int64_t m_agg_val;
198   TSMilestonesType m_milestone1; ///< Used for MS and MSDMS as the first (or only) milestone.
199   TSMilestonesType m_milestone2; ///< Second milestone for MSDMS
200   bool m_time_field;
201   Ptr<LogFieldAliasMap> m_alias_map; // map sINT <--> string
202   SetFunc m_set_func;
203   TSMilestonesType milestone_from_m_name();
204   int milestones_from_m_name(TSMilestonesType *m1, TSMilestonesType *m2);
205 
206 public:
207   LINK(LogField, link);
208   LogSlice m_slice;
209 
210   // noncopyable
211   // -- member functions that are not allowed --
212   LogField &operator=(const LogField &rhs) = delete;
213 
214 private:
215   LogField();
216 };
217 
218 /*-------------------------------------------------------------------------
219   LogFieldList
220 
221   This class maintains a list of LogField objects (tah-dah).
222   -------------------------------------------------------------------------*/
223 
224 class LogFieldList
225 {
226 public:
227   LogFieldList();
228   ~LogFieldList();
229 
230   void clear();
231   void add(LogField *field, bool copy = true);
232   LogField *find_by_name(const char *name) const;
233   LogField *find_by_symbol(const char *symbol) const;
234   unsigned marshal_len(LogAccess *lad);
235   unsigned marshal(LogAccess *lad, char *buf);
236   unsigned marshal_agg(char *buf);
237 
238   LogField *
first()239   first() const
240   {
241     return m_field_list.head;
242   }
243   LogField *
next(LogField * here)244   next(LogField *here) const
245   {
246     return (here->link).next;
247   }
248   unsigned count();
249   void display(FILE *fd = stdout);
250 
251   // Add a bad symbol seen in the log format to the list of bad symbols.
252   //
253   void addBadSymbol(std::string_view badSymbol);
254 
255   // Return blank-separated list of added bad symbols.
256   //
257   std::string_view
badSymbols()258   badSymbols() const
259   {
260     return _badSymbols;
261   }
262 
263   // noncopyable
264   // -- member functions that are not allowed --
265   LogFieldList(const LogFieldList &rhs) = delete;
266   LogFieldList &operator=(const LogFieldList &rhs) = delete;
267 
268 private:
269   unsigned m_marshal_len = 0;
270   Queue<LogField> m_field_list;
271   std::string _badSymbols;
272 };
273 
274 /** Base IP address data.
275     To unpack an IP address, the generic memory is first cast to
276     this type to get the family. That pointer can then be static_cast
277     to the appropriate subtype to get the actual address data.
278 
279     @note We don't use our own enum for the family. Instead we use
280     @c AF_INET and @c AF_INET6.
281 */
282 struct LogFieldIp {
283   uint16_t _family; ///< IP address family.
284 };
285 /// IPv4 address as log field.
286 struct LogFieldIp4 : public LogFieldIp {
287   in_addr_t _addr; ///< IPv4 address.
288 };
289 /// IPv6 address as log field.
290 struct LogFieldIp6 : public LogFieldIp {
291   in6_addr _addr; ///< IPv6 address.
292 };
293 /// Something big enough to hold any of the IP field types.
294 union LogFieldIpStorage {
295   LogFieldIp _ip;
296   LogFieldIp4 _ip4;
297   LogFieldIp6 _ip6;
298 };
299