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