GUI/SoundGraphServer.cs
author StephaneLenclud
Mon, 02 Feb 2015 13:28:41 +0100
branchMiniDisplay
changeset 437 38e7b78cf732
parent 436 e9aefd454d1e
child 439 06369ace500d
permissions -rw-r--r--
Reverting client/server communication around our pipes to fix access denied err.
Now simply opening files for pipes created by SoundGraphAccess server.
StephaneLenclud@436
     1
using System;
StephaneLenclud@436
     2
using Microsoft.Win32.SafeHandles;
StephaneLenclud@436
     3
using System.Text;
StephaneLenclud@436
     4
using System.Runtime.InteropServices;
StephaneLenclud@436
     5
using System.Threading;
StephaneLenclud@436
     6
using System.IO;
StephaneLenclud@436
     7
using System.Diagnostics;
StephaneLenclud@436
     8
StephaneLenclud@436
     9
namespace SoundGraph
StephaneLenclud@436
    10
{
StephaneLenclud@436
    11
    public class Server
StephaneLenclud@436
    12
    {
StephaneLenclud@437
    13
        [Flags]
StephaneLenclud@437
    14
        public enum EFileAccess : uint
StephaneLenclud@437
    15
        {
StephaneLenclud@437
    16
            //
StephaneLenclud@437
    17
            // Standart Section
StephaneLenclud@437
    18
            //
StephaneLenclud@437
    19
StephaneLenclud@437
    20
            AccessSystemSecurity = 0x1000000,   // AccessSystemAcl access type
StephaneLenclud@437
    21
            MaximumAllowed = 0x2000000,     // MaximumAllowed access type
StephaneLenclud@437
    22
StephaneLenclud@437
    23
            Delete = 0x10000,
StephaneLenclud@437
    24
            ReadControl = 0x20000,
StephaneLenclud@437
    25
            WriteDAC = 0x40000,
StephaneLenclud@437
    26
            WriteOwner = 0x80000,
StephaneLenclud@437
    27
            Synchronize = 0x100000,
StephaneLenclud@437
    28
StephaneLenclud@437
    29
            StandardRightsRequired = 0xF0000,
StephaneLenclud@437
    30
            StandardRightsRead = ReadControl,
StephaneLenclud@437
    31
            StandardRightsWrite = ReadControl,
StephaneLenclud@437
    32
            StandardRightsExecute = ReadControl,
StephaneLenclud@437
    33
            StandardRightsAll = 0x1F0000,
StephaneLenclud@437
    34
            SpecificRightsAll = 0xFFFF,
StephaneLenclud@437
    35
StephaneLenclud@437
    36
            FILE_READ_DATA = 0x0001,        // file & pipe
StephaneLenclud@437
    37
            FILE_LIST_DIRECTORY = 0x0001,       // directory
StephaneLenclud@437
    38
            FILE_WRITE_DATA = 0x0002,       // file & pipe
StephaneLenclud@437
    39
            FILE_ADD_FILE = 0x0002,         // directory
StephaneLenclud@437
    40
            FILE_APPEND_DATA = 0x0004,      // file
StephaneLenclud@437
    41
            FILE_ADD_SUBDIRECTORY = 0x0004,     // directory
StephaneLenclud@437
    42
            FILE_CREATE_PIPE_INSTANCE = 0x0004, // named pipe
StephaneLenclud@437
    43
            FILE_READ_EA = 0x0008,          // file & directory
StephaneLenclud@437
    44
            FILE_WRITE_EA = 0x0010,         // file & directory
StephaneLenclud@437
    45
            FILE_EXECUTE = 0x0020,          // file
StephaneLenclud@437
    46
            FILE_TRAVERSE = 0x0020,         // directory
StephaneLenclud@437
    47
            FILE_DELETE_CHILD = 0x0040,     // directory
StephaneLenclud@437
    48
            FILE_READ_ATTRIBUTES = 0x0080,      // all
StephaneLenclud@437
    49
            FILE_WRITE_ATTRIBUTES = 0x0100,     // all
StephaneLenclud@437
    50
StephaneLenclud@437
    51
            //
StephaneLenclud@437
    52
            // Generic Section
StephaneLenclud@437
    53
            //
StephaneLenclud@437
    54
StephaneLenclud@437
    55
            GenericRead = 0x80000000,
StephaneLenclud@437
    56
            GenericWrite = 0x40000000,
StephaneLenclud@437
    57
            GenericExecute = 0x20000000,
StephaneLenclud@437
    58
            GenericAll = 0x10000000,
StephaneLenclud@437
    59
StephaneLenclud@437
    60
            SPECIFIC_RIGHTS_ALL = 0x00FFFF,
StephaneLenclud@437
    61
            FILE_ALL_ACCESS =
StephaneLenclud@437
    62
            StandardRightsRequired |
StephaneLenclud@437
    63
            Synchronize |
StephaneLenclud@437
    64
            0x1FF,
StephaneLenclud@437
    65
StephaneLenclud@437
    66
            FILE_GENERIC_READ =
StephaneLenclud@437
    67
            StandardRightsRead |
StephaneLenclud@437
    68
            FILE_READ_DATA |
StephaneLenclud@437
    69
            FILE_READ_ATTRIBUTES |
StephaneLenclud@437
    70
            FILE_READ_EA |
StephaneLenclud@437
    71
            Synchronize,
StephaneLenclud@437
    72
StephaneLenclud@437
    73
            FILE_GENERIC_WRITE =
StephaneLenclud@437
    74
            StandardRightsWrite |
StephaneLenclud@437
    75
            FILE_WRITE_DATA |
StephaneLenclud@437
    76
            FILE_WRITE_ATTRIBUTES |
StephaneLenclud@437
    77
            FILE_WRITE_EA |
StephaneLenclud@437
    78
            FILE_APPEND_DATA |
StephaneLenclud@437
    79
            Synchronize,
StephaneLenclud@437
    80
StephaneLenclud@437
    81
            FILE_GENERIC_EXECUTE =
StephaneLenclud@437
    82
            StandardRightsExecute |
StephaneLenclud@437
    83
              FILE_READ_ATTRIBUTES |
StephaneLenclud@437
    84
              FILE_EXECUTE |
StephaneLenclud@437
    85
              Synchronize
StephaneLenclud@437
    86
        }
StephaneLenclud@437
    87
StephaneLenclud@437
    88
        [Flags]
StephaneLenclud@437
    89
        public enum EFileShare : uint
StephaneLenclud@437
    90
        {
StephaneLenclud@437
    91
            /// <summary>
StephaneLenclud@437
    92
            /// 
StephaneLenclud@437
    93
            /// </summary>
StephaneLenclud@437
    94
            None = 0x00000000,
StephaneLenclud@437
    95
            /// <summary>
StephaneLenclud@437
    96
            /// Enables subsequent open operations on an object to request read access. 
StephaneLenclud@437
    97
            /// Otherwise, other processes cannot open the object if they request read access. 
StephaneLenclud@437
    98
            /// If this flag is not specified, but the object has been opened for read access, the function fails.
StephaneLenclud@437
    99
            /// </summary>
StephaneLenclud@437
   100
            Read = 0x00000001,
StephaneLenclud@437
   101
            /// <summary>
StephaneLenclud@437
   102
            /// Enables subsequent open operations on an object to request write access. 
StephaneLenclud@437
   103
            /// Otherwise, other processes cannot open the object if they request write access. 
StephaneLenclud@437
   104
            /// If this flag is not specified, but the object has been opened for write access, the function fails.
StephaneLenclud@437
   105
            /// </summary>
StephaneLenclud@437
   106
            Write = 0x00000002,
StephaneLenclud@437
   107
            /// <summary>
StephaneLenclud@437
   108
            /// Enables subsequent open operations on an object to request delete access. 
StephaneLenclud@437
   109
            /// Otherwise, other processes cannot open the object if they request delete access.
StephaneLenclud@437
   110
            /// If this flag is not specified, but the object has been opened for delete access, the function fails.
StephaneLenclud@437
   111
            /// </summary>
StephaneLenclud@437
   112
            Delete = 0x00000004
StephaneLenclud@437
   113
        }
StephaneLenclud@437
   114
StephaneLenclud@437
   115
        public enum ECreationDisposition : uint
StephaneLenclud@437
   116
        {
StephaneLenclud@437
   117
            /// <summary>
StephaneLenclud@437
   118
            /// Creates a new file. The function fails if a specified file exists.
StephaneLenclud@437
   119
            /// </summary>
StephaneLenclud@437
   120
            New = 1,
StephaneLenclud@437
   121
            /// <summary>
StephaneLenclud@437
   122
            /// Creates a new file, always. 
StephaneLenclud@437
   123
            /// If a file exists, the function overwrites the file, clears the existing attributes, combines the specified file attributes, 
StephaneLenclud@437
   124
            /// and flags with FILE_ATTRIBUTE_ARCHIVE, but does not set the security descriptor that the SECURITY_ATTRIBUTES structure specifies.
StephaneLenclud@437
   125
            /// </summary>
StephaneLenclud@437
   126
            CreateAlways = 2,
StephaneLenclud@437
   127
            /// <summary>
StephaneLenclud@437
   128
            /// Opens a file. The function fails if the file does not exist. 
StephaneLenclud@437
   129
            /// </summary>
StephaneLenclud@437
   130
            OpenExisting = 3,
StephaneLenclud@437
   131
            /// <summary>
StephaneLenclud@437
   132
            /// Opens a file, always. 
StephaneLenclud@437
   133
            /// If a file does not exist, the function creates a file as if dwCreationDisposition is CREATE_NEW.
StephaneLenclud@437
   134
            /// </summary>
StephaneLenclud@437
   135
            OpenAlways = 4,
StephaneLenclud@437
   136
            /// <summary>
StephaneLenclud@437
   137
            /// Opens a file and truncates it so that its size is 0 (zero) bytes. The function fails if the file does not exist.
StephaneLenclud@437
   138
            /// The calling process must open the file with the GENERIC_WRITE access right. 
StephaneLenclud@437
   139
            /// </summary>
StephaneLenclud@437
   140
            TruncateExisting = 5
StephaneLenclud@437
   141
        }
StephaneLenclud@437
   142
StephaneLenclud@437
   143
        [Flags]
StephaneLenclud@437
   144
        public enum EFileAttributes : uint
StephaneLenclud@437
   145
        {
StephaneLenclud@437
   146
            None = 0x00000000,
StephaneLenclud@437
   147
            Readonly = 0x00000001,
StephaneLenclud@437
   148
            Hidden = 0x00000002,
StephaneLenclud@437
   149
            System = 0x00000004,
StephaneLenclud@437
   150
            Directory = 0x00000010,
StephaneLenclud@437
   151
            Archive = 0x00000020,
StephaneLenclud@437
   152
            Device = 0x00000040,
StephaneLenclud@437
   153
            Normal = 0x00000080,
StephaneLenclud@437
   154
            Temporary = 0x00000100,
StephaneLenclud@437
   155
            SparseFile = 0x00000200,
StephaneLenclud@437
   156
            ReparsePoint = 0x00000400,
StephaneLenclud@437
   157
            Compressed = 0x00000800,
StephaneLenclud@437
   158
            Offline = 0x00001000,
StephaneLenclud@437
   159
            NotContentIndexed = 0x00002000,
StephaneLenclud@437
   160
            Encrypted = 0x00004000,
StephaneLenclud@437
   161
            Write_Through = 0x80000000,
StephaneLenclud@437
   162
            Overlapped = 0x40000000,
StephaneLenclud@437
   163
            NoBuffering = 0x20000000,
StephaneLenclud@437
   164
            RandomAccess = 0x10000000,
StephaneLenclud@437
   165
            SequentialScan = 0x08000000,
StephaneLenclud@437
   166
            DeleteOnClose = 0x04000000,
StephaneLenclud@437
   167
            BackupSemantics = 0x02000000,
StephaneLenclud@437
   168
            PosixSemantics = 0x01000000,
StephaneLenclud@437
   169
            OpenReparsePoint = 0x00200000,
StephaneLenclud@437
   170
            OpenNoRecall = 0x00100000,
StephaneLenclud@437
   171
            FirstPipeInstance = 0x00080000
StephaneLenclud@437
   172
        }
StephaneLenclud@437
   173
StephaneLenclud@436
   174
        [DllImport("kernel32.dll", SetLastError = true)]
StephaneLenclud@436
   175
        public static extern SafeFileHandle CreateNamedPipe(
StephaneLenclud@436
   176
           String pipeName,
StephaneLenclud@436
   177
           uint dwOpenMode,
StephaneLenclud@436
   178
           uint dwPipeMode,
StephaneLenclud@436
   179
           uint nMaxInstances,
StephaneLenclud@436
   180
           uint nOutBufferSize,
StephaneLenclud@436
   181
           uint nInBufferSize,
StephaneLenclud@436
   182
           uint nDefaultTimeOut,
StephaneLenclud@436
   183
           IntPtr lpSecurityAttributes);
StephaneLenclud@436
   184
StephaneLenclud@436
   185
        [DllImport("kernel32.dll", SetLastError = true)]
StephaneLenclud@436
   186
        public static extern int ConnectNamedPipe(
StephaneLenclud@436
   187
           SafeFileHandle hNamedPipe,
StephaneLenclud@436
   188
           IntPtr lpOverlapped);
StephaneLenclud@436
   189
StephaneLenclud@436
   190
        [DllImport("kernel32.dll", SetLastError = true)]
StephaneLenclud@436
   191
        public static extern int DisconnectNamedPipe(
StephaneLenclud@436
   192
           SafeFileHandle hNamedPipe);
StephaneLenclud@436
   193
StephaneLenclud@437
   194
        [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
StephaneLenclud@437
   195
        public static extern SafeFileHandle CreateFile(
StephaneLenclud@437
   196
           string lpFileName,
StephaneLenclud@437
   197
           EFileAccess dwDesiredAccess,
StephaneLenclud@437
   198
           EFileShare dwShareMode,
StephaneLenclud@437
   199
           IntPtr lpSecurityAttributes,
StephaneLenclud@437
   200
           ECreationDisposition dwCreationDisposition,
StephaneLenclud@437
   201
           EFileAttributes dwFlagsAndAttributes,
StephaneLenclud@437
   202
           IntPtr hTemplateFile);
StephaneLenclud@437
   203
StephaneLenclud@437
   204
        //[DllImport("kernel32.dll", SetLastError = true)]
StephaneLenclud@437
   205
        //static extern bool CloseHandle(IntPtr hHandle);
StephaneLenclud@437
   206
StephaneLenclud@436
   207
        public const uint PIPE_ACCESS_DUPLEX = (0x00000003);
StephaneLenclud@436
   208
        public const uint FILE_FLAG_OVERLAPPED = (0x40000000);
StephaneLenclud@436
   209
        public const uint PIPE_ACCESS_OUTBOUND = (0x00000002);
StephaneLenclud@436
   210
        public const uint PIPE_ACCESS_INBOUND = (0x00000001);
StephaneLenclud@436
   211
        public const uint PIPE_TYPE_BYTE = (0x00000000);
StephaneLenclud@436
   212
        public const uint PIPE_UNLIMITED_INSTANCES = 255;
StephaneLenclud@436
   213
          
StephaneLenclud@436
   214
        
StephaneLenclud@436
   215
StephaneLenclud@436
   216
StephaneLenclud@436
   217
        public const int BUFFER_SIZE = 256;
StephaneLenclud@436
   218
StephaneLenclud@436
   219
        //
StephaneLenclud@436
   220
        public string iPipeNameOutbound;
StephaneLenclud@436
   221
        SafeFileHandle iPipeOutbound;
StephaneLenclud@436
   222
        public FileStream iStreamOutbound;
StephaneLenclud@436
   223
        //
StephaneLenclud@436
   224
        public string iPipeNameInbound;
StephaneLenclud@436
   225
        Thread iThreadInbound;
StephaneLenclud@436
   226
        SafeFileHandle iPipeInbound;
StephaneLenclud@436
   227
        public FileStream iStreamInbound;
StephaneLenclud@436
   228
StephaneLenclud@437
   229
        private bool iQuit = false;
StephaneLenclud@437
   230
StephaneLenclud@436
   231
StephaneLenclud@436
   232
        public Server(string aPipeNameOutbound, string aPipeNameInbound)
StephaneLenclud@436
   233
        {
StephaneLenclud@436
   234
            iPipeNameOutbound = aPipeNameOutbound;
StephaneLenclud@436
   235
            iPipeNameInbound = aPipeNameInbound;
StephaneLenclud@436
   236
        }
StephaneLenclud@436
   237
       
StephaneLenclud@436
   238
        /**
StephaneLenclud@436
   239
         * Start our services.
StephaneLenclud@436
   240
         */
StephaneLenclud@436
   241
        public void Start()
StephaneLenclud@436
   242
        {
StephaneLenclud@436
   243
            //Start inbound thread to receive messages
StephaneLenclud@436
   244
            this.iThreadInbound = new Thread(new ThreadStart(ThreadInbound));
StephaneLenclud@436
   245
            this.iThreadInbound.Start();
StephaneLenclud@436
   246
        }
StephaneLenclud@436
   247
StephaneLenclud@436
   248
        /**
StephaneLenclud@437
   249
         * Stop our services.
StephaneLenclud@436
   250
         */
StephaneLenclud@437
   251
        public void Stop()
StephaneLenclud@436
   252
        {
StephaneLenclud@437
   253
            iQuit = true;
StephaneLenclud@437
   254
        }
StephaneLenclud@436
   255
StephaneLenclud@436
   256
StephaneLenclud@436
   257
        /**
StephaneLenclud@436
   258
         * Inbound thread is receiving messages from our client
StephaneLenclud@436
   259
         */
StephaneLenclud@436
   260
        private void ThreadInbound()
StephaneLenclud@436
   261
        {
StephaneLenclud@436
   262
StephaneLenclud@437
   263
            //Keep on trying to connect on our read pipe
StephaneLenclud@437
   264
            while ((iPipeInbound == null || iPipeInbound.IsInvalid) && !iQuit)
StephaneLenclud@437
   265
            {
StephaneLenclud@437
   266
                Trace.WriteLine("Trying to connect to inbound pipe...");
StephaneLenclud@437
   267
                iPipeInbound = CreateFile(iPipeNameInbound, EFileAccess.GenericRead, EFileShare.None, IntPtr.Zero, ECreationDisposition.OpenExisting, EFileAttributes.None, IntPtr.Zero);
StephaneLenclud@437
   268
                System.Threading.Thread.Sleep(1000);
StephaneLenclud@437
   269
            }
StephaneLenclud@437
   270
            
StephaneLenclud@436
   271
StephaneLenclud@436
   272
            //Client now connected create our inbound stream
StephaneLenclud@437
   273
            if (iPipeInbound!=null && !iPipeInbound.IsInvalid)
StephaneLenclud@437
   274
            {
StephaneLenclud@437
   275
                iStreamInbound = new FileStream(iPipeInbound, FileAccess.Read, BUFFER_SIZE, false);
StephaneLenclud@437
   276
                if (iStreamInbound.CanRead)
StephaneLenclud@437
   277
                {
StephaneLenclud@437
   278
                    Trace.WriteLine("Inbound stream ready!");
StephaneLenclud@437
   279
                }
StephaneLenclud@437
   280
            }
StephaneLenclud@436
   281
StephaneLenclud@436
   282
StephaneLenclud@437
   283
            //Keep on trying to connect to our write pipe
StephaneLenclud@437
   284
            while ((iPipeOutbound == null || iPipeOutbound.IsInvalid) && !iQuit)
StephaneLenclud@437
   285
            {
StephaneLenclud@437
   286
                Trace.WriteLine("Trying to connect to outbound pipe...");
StephaneLenclud@437
   287
                iPipeOutbound = CreateFile(iPipeNameOutbound, EFileAccess.GenericWrite, EFileShare.None, IntPtr.Zero, ECreationDisposition.OpenExisting, EFileAttributes.None, IntPtr.Zero);
StephaneLenclud@437
   288
                System.Threading.Thread.Sleep(1000);
StephaneLenclud@437
   289
            }
StephaneLenclud@437
   290
            
StephaneLenclud@437
   291
StephaneLenclud@437
   292
            //Client now connected create our stream
StephaneLenclud@437
   293
            if (iPipeOutbound!=null && !iPipeOutbound.IsInvalid)
StephaneLenclud@437
   294
            {
StephaneLenclud@437
   295
                iStreamOutbound = new FileStream(iPipeOutbound, FileAccess.Write, BUFFER_SIZE, false);
StephaneLenclud@437
   296
StephaneLenclud@437
   297
                if (iStreamOutbound.CanWrite)
StephaneLenclud@437
   298
                {
StephaneLenclud@437
   299
                    Trace.WriteLine("Outbound stream ready!");
StephaneLenclud@437
   300
                }
StephaneLenclud@437
   301
            }
StephaneLenclud@437
   302
StephaneLenclud@437
   303
StephaneLenclud@437
   304
            //Listening loop
StephaneLenclud@436
   305
            byte[] buffer = null;
StephaneLenclud@436
   306
            ASCIIEncoding encoder = new ASCIIEncoding();
StephaneLenclud@436
   307
StephaneLenclud@437
   308
            while (!iQuit)
StephaneLenclud@436
   309
            {                
StephaneLenclud@436
   310
                int bytesRead = 0;
StephaneLenclud@436
   311
StephaneLenclud@436
   312
                try
StephaneLenclud@436
   313
                {
StephaneLenclud@436
   314
                    buffer = new byte[BUFFER_SIZE];
StephaneLenclud@436
   315
                    bytesRead = iStreamInbound.Read(buffer, 0, BUFFER_SIZE);
StephaneLenclud@436
   316
                }
StephaneLenclud@436
   317
                catch
StephaneLenclud@436
   318
                {
StephaneLenclud@436
   319
                    //read error has occurred
StephaneLenclud@436
   320
                    break;
StephaneLenclud@436
   321
                }
StephaneLenclud@436
   322
StephaneLenclud@436
   323
                //client has disconnected
StephaneLenclud@436
   324
                if (bytesRead == 0)
StephaneLenclud@436
   325
                    break;
StephaneLenclud@436
   326
StephaneLenclud@436
   327
                //fire message received event
StephaneLenclud@436
   328
                //if (this.MessageReceived != null)
StephaneLenclud@436
   329
                //    this.MessageReceived(clientse, encoder.GetString(buffer, 0, bytesRead));
StephaneLenclud@436
   330
StephaneLenclud@436
   331
                int ReadLength = 0;
StephaneLenclud@436
   332
                for (int i = 0; i < BUFFER_SIZE; i++)
StephaneLenclud@436
   333
                {
StephaneLenclud@436
   334
                    //if (buffer[i].ToString("x2") != "cc")
StephaneLenclud@436
   335
                    if (buffer[i] != 0)
StephaneLenclud@436
   336
                    {
StephaneLenclud@436
   337
                        ReadLength++;
StephaneLenclud@436
   338
                    }
StephaneLenclud@436
   339
                    else
StephaneLenclud@436
   340
                        break;
StephaneLenclud@436
   341
                }
StephaneLenclud@436
   342
                if (ReadLength > 0)
StephaneLenclud@436
   343
                {
StephaneLenclud@436
   344
                    byte[] Rc = new byte[ReadLength];
StephaneLenclud@436
   345
                    Buffer.BlockCopy(buffer, 0, Rc, 0, ReadLength);
StephaneLenclud@436
   346
StephaneLenclud@437
   347
                    Trace.WriteLine(encoder.GetString(Rc, 0, ReadLength));
StephaneLenclud@436
   348
                    Trace.WriteLine("Received " + ReadLength + " Bytes: " + encoder.GetString(Rc, 0, ReadLength));
StephaneLenclud@436
   349
                    buffer.Initialize();
StephaneLenclud@436
   350
                }
StephaneLenclud@436
   351
               
StephaneLenclud@436
   352
            }
StephaneLenclud@436
   353
StephaneLenclud@437
   354
 
StephaneLenclud@436
   355
            //clean up resources
StephaneLenclud@437
   356
            if (iStreamInbound!=null) iStreamInbound.Close();
StephaneLenclud@437
   357
            if (iPipeInbound != null) iPipeInbound.Close();
StephaneLenclud@437
   358
            //
StephaneLenclud@437
   359
            if (iStreamOutbound != null) iStreamOutbound.Close();
StephaneLenclud@437
   360
            if (iPipeOutbound != null) iPipeOutbound.Close();
StephaneLenclud@436
   361
        }
StephaneLenclud@436
   362
StephaneLenclud@436
   363
        /**
StephaneLenclud@436
   364
         * Send a message to our client.
StephaneLenclud@436
   365
         */
StephaneLenclud@436
   366
        public void SendMessage(string message)
StephaneLenclud@436
   367
        {
StephaneLenclud@436
   368
StephaneLenclud@436
   369
                ASCIIEncoding encoder = new ASCIIEncoding();
StephaneLenclud@436
   370
                byte[] messageBuffer = encoder.GetBytes(message);
StephaneLenclud@436
   371
StephaneLenclud@437
   372
                if (iStreamOutbound != null && iStreamOutbound.CanWrite)
StephaneLenclud@436
   373
                {
StephaneLenclud@436
   374
                    iStreamOutbound.Write(messageBuffer, 0, messageBuffer.Length);
StephaneLenclud@436
   375
                    iStreamOutbound.Flush();
StephaneLenclud@436
   376
                }
StephaneLenclud@436
   377
StephaneLenclud@436
   378
StephaneLenclud@436
   379
        }
StephaneLenclud@436
   380
StephaneLenclud@436
   381
StephaneLenclud@436
   382
    }
StephaneLenclud@436
   383
}