source: azure_iot_hub_f767zi/trunk/asp_baseplatform/lwip/contrib-2.1.0/apps/LwipMibCompiler/LwipSnmpCodeGeneration/SnmpTableNode.cs@ 457

Last change on this file since 457 was 457, checked in by coas-nagasima, 4 years ago

ファイルを追加

  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/x-csharp;charset=UTF-8
File size: 13.7 KB
Line 
1/*
2 * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without modification,
6 * are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright notice,
11 * this list of conditions and the following disclaimer in the documentation
12 * and/or other materials provided with the distribution.
13 * 3. The name of the author may not be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
19 * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
20 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
21 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
24 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
25 * OF SUCH DAMAGE.
26 *
27 * This file is part of the lwIP TCP/IP stack.
28 *
29 * Author: Martin Hentschel <info@cl-soft.de>
30 *
31 */
32
33using System;
34using System.Collections.Generic;
35using System.Text;
36using CCodeGeneration;
37
38namespace LwipSnmpCodeGeneration
39{
40 public class SnmpTableNode: SnmpScalarAggregationNode
41 {
42 private readonly List<SnmpScalarNode> cellNodes = new List<SnmpScalarNode>();
43 private readonly List<SnmpScalarNode> indexNodes = new List<SnmpScalarNode>();
44 private string augmentedTableRow = null;
45
46
47 public SnmpTableNode(SnmpTreeNode parentNode)
48 : base(parentNode)
49 {
50 }
51
52 public List<SnmpScalarNode> CellNodes
53 {
54 get { return cellNodes; }
55 }
56
57 public List<SnmpScalarNode> IndexNodes
58 {
59 get { return indexNodes; }
60 }
61
62 public string AugmentedTableRow
63 {
64 get { return this.augmentedTableRow; }
65 set { this.augmentedTableRow = value; }
66 }
67
68 public override string FullNodeName
69 {
70 get
71 {
72 string result = this.Name.ToLowerInvariant();
73 if (!result.Contains("table"))
74 {
75 result += "_table";
76 }
77
78 return result;
79 }
80 }
81
82 protected override IEnumerable<SnmpScalarNode> AggregatedScalarNodes
83 {
84 get { return this.cellNodes; }
85 }
86
87 public override void GenerateCode(MibCFile mibFile)
88 {
89 FunctionDeclaration getInstanceMethodDecl = new FunctionDeclaration(this.FullNodeName + LwipDefs.FnctSuffix_GetInstance, isStatic: true);
90 getInstanceMethodDecl.Parameter.Add(new VariableType("column", LwipDefs.Vt_U32, "*", ConstType.Value));
91 getInstanceMethodDecl.Parameter.Add(new VariableType("row_oid", LwipDefs.Vt_U32, "*", ConstType.Value));
92 getInstanceMethodDecl.Parameter.Add(new VariableType("row_oid_len", LwipDefs.Vt_U8, ""));
93 getInstanceMethodDecl.Parameter.Add(new VariableType("cell_instance", LwipDefs.Vt_StNodeInstance, "*"));
94 getInstanceMethodDecl.ReturnType = new VariableType(null, LwipDefs.Vt_Snmp_err);
95 mibFile.Declarations.Add(getInstanceMethodDecl);
96
97 Function getInstanceMethod = Function.FromDeclaration(getInstanceMethodDecl);
98 GenerateGetInstanceMethodCode(getInstanceMethod);
99 mibFile.Implementation.Add(getInstanceMethod);
100
101
102 FunctionDeclaration getNextInstanceMethodDecl = new FunctionDeclaration(this.FullNodeName + LwipDefs.FnctSuffix_GetNextInstance, isStatic: true);
103 getNextInstanceMethodDecl.Parameter.Add(new VariableType("column", LwipDefs.Vt_U32, "*", ConstType.Value));
104 getNextInstanceMethodDecl.Parameter.Add(new VariableType("row_oid", LwipDefs.Vt_StObjectId, "*"));
105 getNextInstanceMethodDecl.Parameter.Add(new VariableType("cell_instance", LwipDefs.Vt_StNodeInstance, "*"));
106 getNextInstanceMethodDecl.ReturnType = new VariableType(null, LwipDefs.Vt_Snmp_err);
107 mibFile.Declarations.Add(getNextInstanceMethodDecl);
108
109 Function getNextInstanceMethod = Function.FromDeclaration(getNextInstanceMethodDecl);
110 GenerateGetNextInstanceMethodCode(getNextInstanceMethod);
111 mibFile.Implementation.Add(getNextInstanceMethod);
112
113
114 VariableType instanceType = new VariableType("cell_instance", LwipDefs.Vt_StNodeInstance, "*");
115 GenerateAggregatedCode(
116 mibFile,
117 instanceType,
118 String.Format("SNMP_TABLE_GET_COLUMN_FROM_OID({0}->instance_oid.id)", instanceType.Name));
119
120
121 #region create and add column/table definitions
122
123 StringBuilder colDefs = new StringBuilder();
124 foreach (SnmpScalarNode colNode in this.cellNodes)
125 {
126 colDefs.AppendFormat(" {{{0}, {1}, {2}}}, /* {3} */ \n",
127 colNode.Oid,
128 LwipDefs.GetAsn1DefForSnmpDataType(colNode.DataType),
129 LwipDefs.GetLwipDefForSnmpAccessMode(colNode.AccessMode),
130 colNode.Name);
131 }
132 if (colDefs.Length > 0)
133 {
134 colDefs.Length--;
135 }
136
137 VariableDeclaration colDefsDecl = new VariableDeclaration(
138 new VariableType(this.FullNodeName + "_columns", LwipDefs.Vt_StTableColumnDef, null, ConstType.Value, String.Empty),
139 "{\n" + colDefs + "\n}",
140 isStatic: true);
141
142 mibFile.Declarations.Add(colDefsDecl);
143
144 string nodeInitialization = String.Format("SNMP_TABLE_CREATE({0}, {1}, {2}, {3}, {4}, {5}, {6})",
145 this.Oid,
146 colDefsDecl.Type.Name,
147 getInstanceMethodDecl.Name, getNextInstanceMethodDecl.Name,
148 (this.GetMethodRequired) ? this.GetMethodName : LwipDefs.Null,
149 (this.TestMethodRequired) ? this.TestMethodName : LwipDefs.Null,
150 (this.SetMethodRequired) ? this.SetMethodName : LwipDefs.Null
151 );
152
153 mibFile.Declarations.Add(new VariableDeclaration(
154 new VariableType(this.FullNodeName, LwipDefs.Vt_StTableNode, null, ConstType.Value),
155 nodeInitialization,
156 isStatic: true));
157
158 #endregion
159 }
160
161 protected virtual void GenerateGetInstanceMethodCode(Function getInstanceMethod)
162 {
163 VariableDeclaration returnValue = new VariableDeclaration((VariableType)getInstanceMethod.ReturnType.Clone(), LwipDefs.Def_ErrorCode_NoSuchInstance);
164 returnValue.Type.Name = "err";
165 getInstanceMethod.Declarations.Add(returnValue);
166
167 int instanceOidLength = 0;
168 StringBuilder indexColumns = new StringBuilder();
169 foreach (SnmpScalarNode indexNode in this.indexNodes)
170 {
171 if (instanceOidLength >= 0)
172 {
173 if (indexNode.OidRepresentationLen >= 0)
174 {
175 instanceOidLength += indexNode.OidRepresentationLen;
176 }
177 else
178 {
179 // at least one index column has a variable length -> we cannot perform a static check
180 instanceOidLength = -1;
181 }
182 }
183
184 indexColumns.AppendFormat(
185 " {0} ({1}, OID length = {2})\n",
186 indexNode.Name,
187 indexNode.DataType,
188 (indexNode.OidRepresentationLen >= 0) ? indexNode.OidRepresentationLen.ToString() : "variable");
189 }
190 if (indexColumns.Length > 0)
191 {
192 indexColumns.Length--;
193
194 getInstanceMethod.Declarations.Insert(0, new Comment(String.Format(
195 "The instance OID of this table consists of following (index) column(s):\n{0}",
196 indexColumns)));
197 }
198
199 string augmentsHint = "";
200 if (!String.IsNullOrWhiteSpace(this.augmentedTableRow))
201 {
202 augmentsHint = String.Format(
203 "This table augments table '{0}'! Index columns therefore belong to table '{0}'!\n" +
204 "You may simply call the '*{1}' method of this table.\n\n",
205 (this.augmentedTableRow.ToLowerInvariant().EndsWith("entry")) ? this.augmentedTableRow.Substring(0, this.augmentedTableRow.Length-5) : this.augmentedTableRow,
206 LwipDefs.FnctSuffix_GetInstance);
207 }
208
209 CodeContainerBase ccb = getInstanceMethod;
210 if (instanceOidLength > 0)
211 {
212 IfThenElse ite = new IfThenElse(String.Format("{0} == {1}", getInstanceMethod.Parameter[2].Name, instanceOidLength));
213 getInstanceMethod.AddElement(ite);
214 ccb = ite;
215 }
216
217 ccb.AddCodeFormat("LWIP_UNUSED_ARG({0});", getInstanceMethod.Parameter[0].Name);
218 ccb.AddCodeFormat("LWIP_UNUSED_ARG({0});", getInstanceMethod.Parameter[1].Name);
219 if (instanceOidLength <= 0)
220 {
221 ccb.AddCodeFormat("LWIP_UNUSED_ARG({0});", getInstanceMethod.Parameter[2].Name);
222 }
223 ccb.AddCodeFormat("LWIP_UNUSED_ARG({0});", getInstanceMethod.Parameter[3].Name);
224
225 ccb.AddElement(new Comment(String.Format(
226 "TODO: check if '{0}'/'{1}' params contain a valid instance oid for a row\n" +
227 "If so, set '{2} = {3};'\n\n" +
228 "snmp_oid_* methods may be used for easier processing of oid\n\n" +
229 "{4}" +
230 "In order to avoid decoding OID a second time in subsequent get_value/set_test/set_value methods,\n" +
231 "you may store an arbitrary value (like a pointer to target value object) in '{5}->reference'/'{5}->reference_len'.\n" +
232 "But be aware that not always a subsequent method is called -> Do NOT allocate memory here and try to release it in subsequent methods!\n\n" +
233 "You also may replace function pointers in '{5}' param for get/test/set methods which contain the default values from table definition,\n" +
234 "in order to provide special methods, for the currently processed cell. Changed pointers are only valid for current request.",
235 getInstanceMethod.Parameter[1].Name,
236 getInstanceMethod.Parameter[2].Name,
237 returnValue.Type.Name,
238 LwipDefs.Def_ErrorCode_Ok,
239 augmentsHint,
240 getInstanceMethod.Parameter[3].Name
241 )));
242
243 getInstanceMethod.AddCodeFormat("return {0};", returnValue.Type.Name);
244 }
245
246 protected virtual void GenerateGetNextInstanceMethodCode(Function getNextInstanceMethod)
247 {
248 getNextInstanceMethod.AddCodeFormat("LWIP_UNUSED_ARG({0});", getNextInstanceMethod.Parameter[0].Name);
249 getNextInstanceMethod.AddCodeFormat("LWIP_UNUSED_ARG({0});", getNextInstanceMethod.Parameter[1].Name);
250 getNextInstanceMethod.AddCodeFormat("LWIP_UNUSED_ARG({0});", getNextInstanceMethod.Parameter[2].Name);
251
252 VariableDeclaration returnValue = new VariableDeclaration((VariableType)getNextInstanceMethod.ReturnType.Clone(), LwipDefs.Def_ErrorCode_NoSuchInstance);
253 returnValue.Type.Name = "err";
254 getNextInstanceMethod.Declarations.Add(returnValue);
255
256 StringBuilder indexColumns = new StringBuilder();
257 foreach (SnmpScalarNode indexNode in this.indexNodes)
258 {
259 indexColumns.AppendFormat(
260 " {0} ({1}, OID length = {2})\n",
261 indexNode.Name,
262 indexNode.DataType,
263 (indexNode.OidRepresentationLen >= 0) ? indexNode.OidRepresentationLen.ToString() : "variable");
264 }
265 if (indexColumns.Length > 0)
266 {
267 indexColumns.Length--;
268
269 getNextInstanceMethod.Declarations.Insert(0, new Comment(String.Format(
270 "The instance OID of this table consists of following (index) column(s):\n{0}",
271 indexColumns)));
272 }
273
274 string augmentsHint = "";
275 if (!String.IsNullOrWhiteSpace(this.augmentedTableRow))
276 {
277 augmentsHint = String.Format(
278 "This table augments table '{0}'! Index columns therefore belong to table '{0}'!\n" +
279 "You may simply call the '*{1}' method of this table.\n\n",
280 (this.augmentedTableRow.ToLowerInvariant().EndsWith("entry")) ? this.augmentedTableRow.Substring(0, this.augmentedTableRow.Length-5) : this.augmentedTableRow,
281 LwipDefs.FnctSuffix_GetNextInstance);
282 }
283
284 getNextInstanceMethod.AddElement(new Comment(String.Format(
285 "TODO: analyze '{0}->id'/'{0}->len' and return the subsequent row instance\n" +
286 "Be aware that '{0}->id'/'{0}->len' must not point to a valid instance or have correct instance length.\n" +
287 "If '{0}->len' is 0, return the first instance. If '{0}->len' is longer than expected, cut superfluous OID parts.\n" +
288 "If a valid next instance is found, store it in '{0}->id'/'{0}->len' and set '{1} = {2};'\n\n" +
289 "snmp_oid_* methods may be used for easier processing of oid\n\n" +
290 "{3}" +
291 "In order to avoid decoding OID a second time in subsequent get_value/set_test/set_value methods,\n" +
292 "you may store an arbitrary value (like a pointer to target value object) in '{4}->reference'/'{4}->reference_len'.\n" +
293 "But be aware that not always a subsequent method is called -> Do NOT allocate memory here and try to release it in subsequent methods!\n\n" +
294 "You also may replace function pointers in '{4}' param for get/test/set methods which contain the default values from table definition,\n" +
295 "in order to provide special methods, for the currently processed cell. Changed pointers are only valid for current request.",
296 getNextInstanceMethod.Parameter[1].Name,
297 returnValue.Type.Name,
298 LwipDefs.Def_ErrorCode_Ok,
299 augmentsHint,
300 getNextInstanceMethod.Parameter[2].Name
301 )));
302
303 getNextInstanceMethod.AddElement(new Comment(String.Format(
304 "For easier processing and getting the next instance, you may use the 'snmp_next_oid_*' enumerator.\n" +
305 "Simply pass all known instance OID's to it and it returns the next valid one:\n\n" +
306 "{0} state;\n" +
307 "{1} result_buf;\n" +
308 "snmp_next_oid_init(&state, {2}->id, {2}->len, result_buf.id, SNMP_MAX_OBJ_ID_LEN);\n" +
309 "while ({{not all instances passed}}) {{\n" +
310 " {1} test_oid;\n" +
311 " {{fill test_oid to create instance oid for next instance}}\n" +
312 " snmp_next_oid_check(&state, test_oid.id, test_oid.len, {{target_data_ptr}});\n" +
313 "}}\n" +
314 "if(state.status == SNMP_NEXT_OID_STATUS_SUCCESS) {{\n" +
315 " snmp_oid_assign(row_oid, state.next_oid, state.next_oid_len);\n" +
316 " {3}->reference.ptr = state.reference; //==target_data_ptr, for usage in subsequent get/test/set\n" +
317 " {4} = {5};\n" +
318 "}}"
319 ,
320 LwipDefs.Vt_StNextOidState,
321 LwipDefs.Vt_StObjectId,
322 getNextInstanceMethod.Parameter[1].Name,
323 getNextInstanceMethod.Parameter[2].Name,
324 returnValue.Type.Name,
325 LwipDefs.Def_ErrorCode_Ok
326 )));
327
328 getNextInstanceMethod.AddCodeFormat("return {0};", returnValue.Type.Name);
329 }
330
331 }
332}
Note: See TracBrowser for help on using the repository browser.