Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions src/S7CommPlusDriver/ClientApi/PlcTag.cs
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,26 @@ public virtual void ProcessWriteResult(UInt64 error)

internal abstract PValue GetWriteValue();

/// <summary>
/// Gets the tag's current typed value as a boxed <see cref="object"/> via its public <c>Value</c> property.
/// </summary>
/// <returns>The boxed value, or <see langword="null"/> when the concrete tag type has no public <c>Value</c> property.</returns>
public virtual object GetValue()
{
var valueProperty = GetType().GetProperty("Value", BindingFlags.Public | BindingFlags.Instance);
return valueProperty?.GetValue(this);
}

/// <summary>
/// Sets the tag's current typed value from a boxed <see cref="object"/> via its public <c>Value</c> property.
/// </summary>
/// <param name="value">The value to assign, which must be assignable to the concrete tag's <c>Value</c> property type.</param>
public virtual void SetValue(object value)
{
var valueProperty = GetType().GetProperty("Value", BindingFlags.Public | BindingFlags.Instance);
valueProperty?.SetValue(this, value);
}

internal void SetTraceAddressMetadata(VarInfo variable)
{
if (variable == null)
Expand Down
12 changes: 12 additions & 0 deletions src/S7CommPlusDriver/Core/POffsetInfoType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,12 @@ public enum OffsetInfoType
public abstract bool Is1Dim();
public abstract bool IsMDim();

/// <summary>
/// Gets the maximum string length for a String/WString offset info, or 0 when not applicable.
/// </summary>
/// <returns>The maximum length in characters, or 0 for non-string offset info types.</returns>
public virtual int MaxStringLength() { return 0; }

public static POffsetInfoType Deserialize(Stream buffer, int offsetinfotype, out int length)
{
switch ((OffsetInfoType)offsetinfotype)
Expand Down Expand Up @@ -455,6 +461,8 @@ public class POffsetInfoType_ArrayMDim : POffsetInfoType, IOffsetInfoType_MDim
public override bool HasRelation() { return false; }
public override bool Is1Dim() { return false; }
public override bool IsMDim() { return true; }
// For a string array, UnspecifiedOffsetinfo1 carries the maximum string length of the array elements.
public override int MaxStringLength() { return UnspecifiedOffsetinfo1; }

public static POffsetInfoType_ArrayMDim Deserialize(Stream buffer, out int length)
{
Expand Down Expand Up @@ -542,6 +550,8 @@ public class POffsetInfoType_Array1Dim : POffsetInfoType, IOffsetInfoType_1Dim
public override bool HasRelation() { return false; }
public override bool Is1Dim() { return true; }
public override bool IsMDim() { return false; }
// For a string array, UnspecifiedOffsetinfo1 carries the maximum string length of the array elements.
public override int MaxStringLength() { return UnspecifiedOffsetinfo1; }
Comment on lines +553 to +554

public static POffsetInfoType_Array1Dim Deserialize(Stream buffer, out int length)
{
Expand Down Expand Up @@ -599,6 +609,8 @@ public class POffsetInfoType_String: POffsetInfoType
public override bool HasRelation() { return false; }
public override bool Is1Dim() { return false; }
public override bool IsMDim() { return false; }
// Some firmware versions swap UnspecifiedOffsetinfo1/2, so take the smaller value as the max. string length.
public override int MaxStringLength() { return Math.Min(UnspecifiedOffsetinfo1, UnspecifiedOffsetinfo2); }

public static POffsetInfoType_String Deserialize(Stream buffer, out int length)
{
Expand Down
60 changes: 49 additions & 11 deletions src/S7CommPlusDriver/OpenSSL/OpenSSLConnector.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ public class OpenSSLConnector : IDisposable
private readonly byte[] m_buffer = new byte[4096];
private readonly DataBufferList m_pendingWriteList;
private readonly DataBufferList m_pendingReadList;
private readonly object m_readListLock = new object();
private readonly object m_writeListLock = new object();
Comment on lines +36 to +37
private bool m_fatalError;
private bool m_disposed;

Expand Down Expand Up @@ -277,8 +279,16 @@ protected void RunSSL()

while (!m_fatalError && ((!m_readRequired && dataToWrite) || dataToRead))
{
int pendingReadBefore = m_pendingReadList.Count;
int pendingWriteBefore = m_pendingWriteList.Count;
int pendingReadBefore;
int pendingWriteBefore;
lock (m_readListLock)
{
pendingReadBefore = m_pendingReadList.Count;
}
lock (m_writeListLock)
{
pendingWriteBefore = m_pendingWriteList.Count;
}
bool readRequiredBefore = m_readRequired;
var bioPendingBefore = Native.BIO_ctrl_pending(m_pBioOut);

Expand All @@ -304,8 +314,18 @@ protected void RunSSL()

GetPendingOperations(ref dataToRead, ref dataToWrite);
var bioPendingAfter = Native.BIO_ctrl_pending(m_pBioOut);
if (pendingReadBefore == m_pendingReadList.Count &&
pendingWriteBefore == m_pendingWriteList.Count &&
int pendingReadAfter;
int pendingWriteAfter;
lock (m_readListLock)
{
pendingReadAfter = m_pendingReadList.Count;
}
lock (m_writeListLock)
{
pendingWriteAfter = m_pendingWriteList.Count;
}
if (pendingReadBefore == pendingReadAfter &&
pendingWriteBefore == pendingWriteAfter &&
readRequiredBefore == m_readRequired &&
bioPendingBefore == bioPendingAfter)
{
Expand Down Expand Up @@ -341,8 +361,14 @@ public void ReadCompleted(byte[] pData, int dataLen)

private void GetPendingOperations(ref bool dataToRead, ref bool dataToWrite)
{
dataToRead = m_pendingReadList.Count > 0;
dataToWrite = m_pendingWriteList.Count > 0;
lock (m_readListLock)
{
dataToRead = m_pendingReadList.Count > 0;
}
lock (m_writeListLock)
{
dataToWrite = m_pendingWriteList.Count > 0;
}
}

private void PerformRead()
Expand Down Expand Up @@ -437,23 +463,35 @@ private void UseData(DataBufferList list, DataBuffer pBuffer, int result)

private void AppendBuffer(DataBufferList list, DataBuffer pBuffer)
{
list.AddLast(pBuffer);
object lockObject = (list == m_pendingReadList) ? m_readListLock : m_writeListLock;
lock (lockObject)
{
list.AddLast(pBuffer);
}
}

DataBuffer GetNextBuffer(DataBufferList list)
{
DataBuffer head = null;
if (list.Count > 0)
object lockObject = (list == m_pendingReadList) ? m_readListLock : m_writeListLock;
lock (lockObject)
{
head = list.First.Value;
list.RemoveFirst();
if (list.Count > 0)
{
head = list.First.Value;
list.RemoveFirst();
}
}
return head;
}

void PutbackBuffer(DataBufferList list, DataBuffer pBuffer)
{
list.AddFirst(pBuffer);
object lockObject = (list == m_pendingReadList) ? m_readListLock : m_writeListLock;
lock (lockObject)
{
list.AddFirst(pBuffer);
}
}

/// <summary>
Expand Down