Skip to content

Commit 8ea8087

Browse files
committed
ExploreResponse: Objects are a list of objects, not a single one.
Before if it was a list of objects, the first was used as parent object, which was wrong. As a result if a list of objects was in the response (without a parent object), the first object was not processed correct (as a result, exploring the list of DBs, the first DB was missing. The change thus affects all other parts which use the explore function.
1 parent 0c28ebf commit 8ea8087

File tree

5 files changed

+66
-23
lines changed

5 files changed

+66
-23
lines changed

src/S7CommPlusDriver/Alarming/BrowseAlarms.cs

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
using System.Collections.Generic;
1818
using System.Diagnostics;
1919
using System.IO;
20+
using System.Linq;
2021

2122
namespace S7CommPlusDriver
2223
{
@@ -66,10 +67,13 @@ public int ExploreASAlarms(ref Dictionary<ulong, AlarmData> Alarms, int language
6667
{
6768
return res;
6869
}
69-
List<PObject> staiclass = exploreRes.ResponseObject.GetObjectsByClassId(Ids.MultipleSTAI_Class_Rid);
70-
if (staiclass != null && staiclass.Count > 0)
70+
71+
var alarmobjs = exploreRes.Objects.First(o => o.RelationId == 0x8a7e0000).GetObjects();
72+
var staiclass = alarmobjs.First(o => o.ClassId == Ids.MultipleSTAI_Class_Rid);
73+
74+
if (staiclass != null)
7175
{
72-
PValue stais = staiclass[0].GetAttribute(Ids.MultipleSTAI_STAIs);
76+
PValue stais = staiclass.GetAttribute(Ids.MultipleSTAI_STAIs);
7377
if (stais != null)
7478
{
7579
if (stais.GetType() == typeof(ValueBlobSparseArray))
@@ -133,14 +137,14 @@ public int ExploreASAlarms(ref Dictionary<ulong, AlarmData> Alarms, int language
133137
}
134138

135139
// All objects which have Alarm AP inside, have a sub-Object with ID 7854 = MultipleSTAI.Class_Rid
136-
List<PObject> objList = exploreRes.ResponseObject.GetObjects();
140+
var obj = exploreRes.Objects.First(o => o.ClassId == Ids.PLCProgram_Class_Rid);
137141

138-
foreach (var ob in objList)
142+
foreach (var ob in obj.GetObjects())
139143
{
140-
staiclass = ob.GetObjectsByClassId(Ids.MultipleSTAI_Class_Rid);
141-
if (staiclass != null && staiclass.Count > 0)
144+
var staiclasses = ob.GetObjectsByClassId(Ids.MultipleSTAI_Class_Rid);
145+
if (staiclasses != null && staiclasses.Count > 0)
142146
{
143-
PValue stais = staiclass[0].GetAttribute(Ids.MultipleSTAI_STAIs);
147+
PValue stais = staiclasses[0].GetAttribute(Ids.MultipleSTAI_STAIs);
144148
if (stais != null)
145149
{
146150
if (stais.GetType() == typeof(ValueBlobSparseArray))
@@ -200,9 +204,11 @@ public int ExploreASAlarms(ref Dictionary<ulong, AlarmData> Alarms, int language
200204
// [0] contains informations of how to get infos from [1], which has infos about offsets in [2].
201205
// [2] contains the resulting offsets for the strings in TextLibraryStringArea.
202206
// TODO: Check if all fields are present, or use try/catch?
203-
204-
var tloa = ((ValueBlobArray)exploreRes.ResponseObject.GetAttribute(Ids.TextLibraryOffsetArea)).GetValue();
205-
var tlsa = ((ValueBlob)exploreRes.ResponseObject.GetAttribute(Ids.TextLibraryStringArea)).GetValue();
207+
ValueBlob[] tloa = null;
208+
byte[] tlsa = null;
209+
var textlib = exploreRes.Objects.First(o => o.ClassId == Ids.TextLibraryClassRID);
210+
tloa = ((ValueBlobArray)textlib.GetAttribute(Ids.TextLibraryOffsetArea)).GetValue();
211+
tlsa = ((ValueBlob)textlib.GetAttribute(Ids.TextLibraryStringArea)).GetValue();
206212

207213
var tloa_1 = tloa[0].GetValue();
208214
var tloa_2 = tloa[1].GetValue();

src/S7CommPlusDriver/Core/ExploreResponse.cs

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515

1616
using System;
1717
using System.IO;
18+
using System.Collections.Generic;
1819

1920
namespace S7CommPlusDriver
2021
{
@@ -23,7 +24,7 @@ public class ExploreResponse : IS7pResponse
2324
public byte TransportFlags;
2425
public UInt64 ReturnValue;
2526
public UInt32 ExploreId;
26-
public PObject ResponseObject;
27+
public List<PObject> Objects;
2728

2829
public byte ProtocolVersion { get; set; }
2930
public ushort FunctionCode { get => Functioncode.Explore; }
@@ -53,8 +54,10 @@ public int Deserialize(Stream buffer)
5354
ret += S7p.DecodeUInt32Vlq(buffer, out uint iid);
5455
IntegrityId = iid;
5556
}
56-
// See comment in Wireshark dissector code
57-
ret += S7p.DecodeObject(buffer, ref ResponseObject);
57+
58+
// This is a List of objects
59+
Objects = new List<PObject>();
60+
ret += S7p.DecodeObjectList(buffer, ref Objects);
5861
return ret;
5962
}
6063

@@ -68,7 +71,12 @@ public override string ToString()
6871
s += "<ResponseSet>" + Environment.NewLine;
6972
s += "<ReturnValue>" + ReturnValue.ToString() + "</ReturnValue>" + Environment.NewLine;
7073
s += "<ExploreId>" + ExploreId.ToString() + "</ExploreId>" + Environment.NewLine;
71-
s += "<ResponseObject>" + ResponseObject.ToString() + "</ResponseObject>" + Environment.NewLine;
74+
s += "<Objects>";
75+
foreach (var obj in Objects)
76+
{
77+
s += obj.ToString();
78+
}
79+
s += "</Objects>" + Environment.NewLine;
7280
s += "</ResponseSet>" + Environment.NewLine;
7381
s += "</ExploreResponse>" + Environment.NewLine;
7482
return s;

src/S7CommPlusDriver/Core/Ids.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,9 @@ public static class Ids
3737
public const int ServerSessionClientRID = 300;
3838
public const int ServerSessionVersion = 306;
3939
public const int ClassTypeInfo = 511;
40+
public const int ClassOMSTypeInfoContainer = 534;
4041
public const int ObjectOMSTypeInfoContainer = 537;
42+
public const int TextLibraryClassRID = 606;
4143
public const int TextLibraryOffsetArea = 608;
4244
public const int TextLibraryStringArea = 609;
4345
public const int SystemLimits = 1037;
@@ -51,6 +53,7 @@ public static class Ids
5153
public const int CompositionAID = 1258;
5254
public const int KeyQualifier = 1259;
5355
public const int CPUexecUnit_operatingStateReq = 2167;
56+
public const int PLCProgram_Class_Rid = 2520;
5457
public const int Block_BlockNumber = 2521;
5558
public const int DB_ValueInitial = 2548;
5659
public const int DB_ValueActual = 2550;

src/S7CommPlusDriver/Core/S7p.cs

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515

1616
using System;
1717
using System.Text;
18+
using System.Collections.Generic;
1819

1920
namespace S7CommPlusDriver
2021
{
@@ -634,7 +635,26 @@ public static int DecodeOctets(System.IO.Stream buffer, int length, out byte[] v
634635
///////////////////////////////////////////////////////////////////////////////////////
635636
// High Level Decode/Encode methods
636637

637-
public static int DecodeObject(System.IO.Stream buffer, ref PObject obj)
638+
public static int DecodeObjectList(System.IO.Stream buffer, ref List<PObject> objList)
639+
{
640+
int ret = 0;
641+
byte tagId;
642+
objList = new List<PObject>();
643+
// Peek one byte and set buffer back
644+
S7p.DecodeByte(buffer, out tagId);
645+
buffer.Position -= 1;
646+
while (tagId == ElementID.StartOfObject)
647+
{
648+
PObject obj = null;
649+
ret += S7p.DecodeObject(buffer, ref obj, AsList: true);
650+
objList.Add(obj);
651+
S7p.DecodeByte(buffer, out tagId);
652+
buffer.Position -= 1;
653+
}
654+
return ret;
655+
}
656+
657+
public static int DecodeObject(System.IO.Stream buffer, ref PObject obj, bool AsList = false)
638658
{
639659
byte tagId;
640660
UInt32 id;
@@ -653,7 +673,12 @@ public static int DecodeObject(System.IO.Stream buffer, ref PObject obj)
653673
ret += DecodeUInt32Vlq(buffer, out obj.ClassId);
654674
ret += DecodeUInt32Vlq(buffer, out obj.ClassFlags);
655675
ret += DecodeUInt32Vlq(buffer, out obj.AttributeId);
656-
ret += DecodeObject(buffer, ref obj);
676+
// If a List is expected, don't add the objects coming next to the parent object
677+
// TODO: May be it's better to always expect a list? Adding the following objects to the first as children must always be wrong.
678+
if (AsList == false)
679+
{
680+
ret += DecodeObject(buffer, ref obj);
681+
}
657682
}
658683
else
659684
{

src/S7CommPlusDriver/S7CommPlusConnection.cs

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
using System.Text;
1919
using System.Threading;
2020
using System.IO;
21+
using System.Linq;
2122

2223
namespace S7CommPlusDriver
2324
{
@@ -717,9 +718,9 @@ public int Browse(out List<VarInfo> varInfoList)
717718

718719
#region Evaluate all data blocks that then need to be browsed
719720

720-
List<PObject> objList = exploreRes.ResponseObject.GetObjects();
721+
var obj = exploreRes.Objects.First(o => o.ClassId == Ids.PLCProgram_Class_Rid);
721722

722-
foreach (var ob in objList)
723+
foreach (var ob in obj.GetObjects())
723724
{
724725
switch (ob.ClassId)
725726
{
@@ -836,9 +837,9 @@ public int Browse(out List<VarInfo> varInfoList)
836837
{
837838
return res;
838839
}
839-
List<PObject> objs = exploreResponse.ResponseObject.GetObjectsByClassId(Ids.ClassTypeInfo);
840+
var objs = exploreResponse.Objects.First(o => o.ClassId == Ids.ClassOMSTypeInfoContainer);
840841

841-
vars.SetTypeInfoContainerObjects(objs);
842+
vars.SetTypeInfoContainerObjects(objs.GetObjects());
842843
vars.BuildTree();
843844
vars.BuildFlatList();
844845
varInfoList = vars.GetVarInfoList();
@@ -919,7 +920,7 @@ public int GetListOfDatablocks(out List<DatablockInfo> dbInfoList)
919920
}
920921

921922
// Get the datablock information we want further informations from.
922-
var objList = exploreRes.ResponseObject.GetObjects();
923+
var objList = exploreRes.Objects;
923924

924925
foreach (var ob in objList)
925926
{
@@ -1027,7 +1028,7 @@ public int GetTypeInformation(uint exploreId, out List<PObject> objList)
10271028
{
10281029
return res;
10291030
}
1030-
objList.Add(exploreRes.ResponseObject);
1031+
objList = exploreRes.Objects;
10311032

10321033
return 0;
10331034
}

0 commit comments

Comments
 (0)