diff --git a/dotnet/IEC61850forCSharp/IEC61850ClientAPI.cs b/dotnet/IEC61850forCSharp/IEC61850ClientAPI.cs index a417ab0a..3a561460 100644 --- a/dotnet/IEC61850forCSharp/IEC61850ClientAPI.cs +++ b/dotnet/IEC61850forCSharp/IEC61850ClientAPI.cs @@ -1681,8 +1681,8 @@ namespace IEC61850 [UnmanagedFunctionPointer(CallingConvention.Cdecl)] [return: MarshalAs(UnmanagedType.I1)] - private delegate bool IedConnection_GetFileAsyncHandler(UInt32 invokeId,IntPtr parameter,int err,UInt32 originalInvokeId, - IntPtr buffer,UInt32 bytesRead,bool moreFollows); + private delegate bool IedConnection_GetFileAsyncHandler(UInt32 invokeId, IntPtr parameter, int err, UInt32 originalInvokeId, + IntPtr buffer, UInt32 bytesRead, [MarshalAs(UnmanagedType.I1)] bool moreFollows); /// /// Callback handler for the asynchronous get file service. Will be invoked for each chunk of received data @@ -1693,7 +1693,8 @@ namespace IEC61850 /// the invokeId of the first (file open) request /// the file data received with the last response, or null if no file data available /// indicates that more file data follows - public delegate bool GetFileAsyncHandler(UInt32 invokeId,object parameter,IedClientError err,UInt32 originalInvokeId,byte[] buffer,bool moreFollows); + /// true, continue the file download when moreFollows is true, false, stop file download + public delegate bool GetFileAsyncHandler(UInt32 invokeId, object parameter, IedClientError err, UInt32 originalInvokeId, byte[] buffer, bool moreFollows); [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] static extern UInt32 @@ -1703,7 +1704,6 @@ namespace IEC61850 private bool nativeGetFileAsyncHandler(UInt32 invokeId, IntPtr parameter, int err, UInt32 originalInvokeId, IntPtr buffer, UInt32 bytesRead, bool moreFollows) { - GCHandle handle = GCHandle.FromIntPtr(parameter); Tuple callbackInfo = handle.Target as Tuple; @@ -1711,8 +1711,6 @@ namespace IEC61850 GetFileAsyncHandler handler = callbackInfo.Item1; object handlerParameter = callbackInfo.Item2; - handle.Free(); - IedClientError clientError = (IedClientError)err; byte[] bytes = null; @@ -1724,7 +1722,28 @@ namespace IEC61850 Marshal.Copy(buffer, bytes, 0, (int)bytesRead); } - return handler(invokeId, handlerParameter, clientError, originalInvokeId, bytes, moreFollows); + bool retVal = handler(invokeId, handlerParameter, clientError, originalInvokeId, bytes, moreFollows); + + if (clientError != IedClientError.IED_ERROR_OK) + { + handle.Free(); + } + else + { + if (moreFollows == false) + { + handle.Free(); + } + else + { + if (retVal == false) + { + handle.Free(); + } + } + } + + return retVal; } /// diff --git a/dotnet/client_example_async/client_example_async.csproj b/dotnet/client_example_async/client_example_async.csproj index 17879d2c..86340d04 100644 --- a/dotnet/client_example_async/client_example_async.csproj +++ b/dotnet/client_example_async/client_example_async.csproj @@ -1,4 +1,4 @@ - + Debug @@ -7,7 +7,8 @@ Exe client_example_async client_example_async - v4.5 + v4.0 + true @@ -18,6 +19,7 @@ prompt 4 true + false full @@ -41,4 +43,7 @@ IEC61850.NET + + + \ No newline at end of file diff --git a/dotnet/files/FileServicesExample.cs b/dotnet/files/FileServicesExample.cs index bdd02126..34cbb804 100644 --- a/dotnet/files/FileServicesExample.cs +++ b/dotnet/files/FileServicesExample.cs @@ -4,93 +4,131 @@ using System.Collections.Generic; using IEC61850.Client; using IEC61850.Common; using System.IO; +using System.Threading; namespace files { - /// - /// This example connects to an IEC 61850 device, list the available files, and then - /// tries to read the file "IEDSERVER.BIN" from the server. - /// - class MainClass - { - public static void printFiles (IedConnection con, string prefix, string parent) - { + /// + /// This example connects to an IEC 61850 device, list the available files, and then + /// tries to read the file "IEDSERVER.BIN" from the server. + /// + class MainClass + { + public static void printFiles(IedConnection con, string prefix, string parent) + { bool moreFollows = false; - List files = con.GetFileDirectoryEx (parent, null, out moreFollows); + List files = con.GetFileDirectoryEx(parent, null, out moreFollows); - foreach (FileDirectoryEntry file in files) { - Console.WriteLine (prefix + file.GetFileName () + "\t" + file.GetFileSize () + "\t" + - MmsValue.MsTimeToDateTimeOffset (file.GetLastModified ())); + foreach (FileDirectoryEntry file in files) + { + Console.WriteLine(prefix + file.GetFileName() + "\t" + file.GetFileSize() + "\t" + + MmsValue.MsTimeToDateTimeOffset(file.GetLastModified())); - if (file.GetFileName ().EndsWith ("/")) { - printFiles (con, prefix + " ", parent + file.GetFileName ()); - } - } + if (file.GetFileName().EndsWith("/")) + { + printFiles(con, prefix + " ", parent + file.GetFileName()); + } + } if (moreFollows) Console.WriteLine("-- MORE FILES AVAILABLE --"); - } + } - static bool getFileHandler (object parameter, byte[] data) - { - Console.WriteLine ("received " + data.Length + " bytes"); + static bool getFileHandler(object parameter, byte[] data) + { + Console.WriteLine("received " + data.Length + " bytes"); - BinaryWriter binWriter = (BinaryWriter)parameter; + BinaryWriter binWriter = (BinaryWriter)parameter; - binWriter.Write (data); + binWriter.Write(data); - return true; - } + return true; + } - public static void Main (string[] args) - { - IedConnection con = new IedConnection (); + public static void Main(string[] args) + { + IedConnection con = new IedConnection(); - string hostname; + string hostname; - if (args.Length > 0) - hostname = args [0]; - else - hostname = "127.0.0.1"; + if (args.Length > 0) + hostname = args[0]; + else + hostname = "127.0.0.1"; - Console.WriteLine ("Connect to " + hostname); + Console.WriteLine("Connect to " + hostname); - try { - con.Connect (hostname, 102); + try + { + con.Connect(hostname, 102); - Console.WriteLine ("Files in server root directory:"); - List serverDirectory = con.GetServerDirectory (true); + Console.WriteLine("Files in server root directory:"); + List serverDirectory = con.GetServerDirectory(true); - foreach (string entry in serverDirectory) { - Console.WriteLine (entry); - } + foreach (string entry in serverDirectory) + { + Console.WriteLine(entry); + } - Console.WriteLine (); + Console.WriteLine(); - Console.WriteLine ("File directory tree at server:"); - printFiles (con, "", ""); - Console.WriteLine (); + Console.WriteLine("File directory tree at server:"); + printFiles(con, "", ""); + Console.WriteLine(); - string filename = "IEDSERVER.BIN"; + string filename = "IEDSERVER.BIN"; - Console.WriteLine ("Download file " + filename); + Console.WriteLine("Download file " + filename); - /* Download file from server and write it to a new local file */ - FileStream fs = new FileStream (filename, FileMode.Create); - BinaryWriter w = new BinaryWriter (fs); + /* Download file from server and write it to a new local file */ + FileStream fs = new FileStream(filename, FileMode.Create); + BinaryWriter w = new BinaryWriter(fs); - con.GetFile (filename, new IedConnection.GetFileHandler (getFileHandler), w); + bool fileDownloadFinished = false; - fs.Close (); + //con.GetFile (filename, new IedConnection.GetFileHandler (getFileHandler), w); - con.Abort (); - } catch (IedConnectionException e) { - Console.WriteLine (e.Message); - } + /// COMMENT SECTION WHEN USING SYNC VERSION --> - // release all resources - do NOT use the object after this call!! - con.Dispose (); - } - } + con.GetFileAsync(filename, delegate (UInt32 invokeId, object parameter, IedClientError err, UInt32 originalInvokeId, byte[] buffer, bool moreFollows) + { + if (err == IedClientError.IED_ERROR_OK) + { + Console.WriteLine("Received new file segment with " + buffer.Length.ToString() + " bytes, more-follows: " + moreFollows.ToString()); + + w.Write(buffer); + + if (moreFollows == false) + fileDownloadFinished = true; + } + else + { + Console.WriteLine("File download error: " + err.ToString()); + fileDownloadFinished = true; + } + + return true; + }, w); + + while (fileDownloadFinished == false) + { + Thread.Sleep(500); + } + + /// <-- COMMENT SECTION WHEN USING SYNC VERSION + + fs.Close(); + + con.Abort(); + } + catch (IedConnectionException e) + { + Console.WriteLine(e.Message); + } + + // release all resources - do NOT use the object after this call!! + con.Dispose(); + } + } } diff --git a/src/iec61850/inc/iec61850_client.h b/src/iec61850/inc/iec61850_client.h index dd1b1848..852f2192 100644 --- a/src/iec61850/inc/iec61850_client.h +++ b/src/iec61850/inc/iec61850_client.h @@ -2969,6 +2969,8 @@ IedConnection_getFile(IedConnection self, IedClientError* error, const char* fil * \param buffer the buffer that contains the received file data * \param bytesRead the number of bytes read into the buffer * \param moreFollows indicates that more file data is following + * + * \return true, continue the file download when moreFollows is true, false, stop file download */ typedef bool (*IedConnection_GetFileAsyncHandler) (uint32_t invokeId, void* parameter, IedClientError err, uint32_t originalInvokeId,