StephaneLenclud@394: using System;
StephaneLenclud@394: using Microsoft.Win32.SafeHandles;
StephaneLenclud@394: using System.Text;
StephaneLenclud@394: using System.Runtime.InteropServices;
StephaneLenclud@394: using System.Threading;
StephaneLenclud@394: using System.IO;
StephaneLenclud@394: using System.Diagnostics;
StephaneLenclud@394:
StephaneLenclud@394: namespace SoundGraph
StephaneLenclud@394: {
StephaneLenclud@394: public class Server
StephaneLenclud@394: {
StephaneLenclud@395: [Flags]
StephaneLenclud@395: public enum EFileAccess : uint
StephaneLenclud@395: {
StephaneLenclud@395: //
StephaneLenclud@395: // Standart Section
StephaneLenclud@395: //
StephaneLenclud@395:
StephaneLenclud@395: AccessSystemSecurity = 0x1000000, // AccessSystemAcl access type
StephaneLenclud@395: MaximumAllowed = 0x2000000, // MaximumAllowed access type
StephaneLenclud@395:
StephaneLenclud@395: Delete = 0x10000,
StephaneLenclud@395: ReadControl = 0x20000,
StephaneLenclud@395: WriteDAC = 0x40000,
StephaneLenclud@395: WriteOwner = 0x80000,
StephaneLenclud@395: Synchronize = 0x100000,
StephaneLenclud@395:
StephaneLenclud@395: StandardRightsRequired = 0xF0000,
StephaneLenclud@395: StandardRightsRead = ReadControl,
StephaneLenclud@395: StandardRightsWrite = ReadControl,
StephaneLenclud@395: StandardRightsExecute = ReadControl,
StephaneLenclud@395: StandardRightsAll = 0x1F0000,
StephaneLenclud@395: SpecificRightsAll = 0xFFFF,
StephaneLenclud@395:
StephaneLenclud@395: FILE_READ_DATA = 0x0001, // file & pipe
StephaneLenclud@395: FILE_LIST_DIRECTORY = 0x0001, // directory
StephaneLenclud@395: FILE_WRITE_DATA = 0x0002, // file & pipe
StephaneLenclud@395: FILE_ADD_FILE = 0x0002, // directory
StephaneLenclud@395: FILE_APPEND_DATA = 0x0004, // file
StephaneLenclud@395: FILE_ADD_SUBDIRECTORY = 0x0004, // directory
StephaneLenclud@395: FILE_CREATE_PIPE_INSTANCE = 0x0004, // named pipe
StephaneLenclud@395: FILE_READ_EA = 0x0008, // file & directory
StephaneLenclud@395: FILE_WRITE_EA = 0x0010, // file & directory
StephaneLenclud@395: FILE_EXECUTE = 0x0020, // file
StephaneLenclud@395: FILE_TRAVERSE = 0x0020, // directory
StephaneLenclud@395: FILE_DELETE_CHILD = 0x0040, // directory
StephaneLenclud@395: FILE_READ_ATTRIBUTES = 0x0080, // all
StephaneLenclud@395: FILE_WRITE_ATTRIBUTES = 0x0100, // all
StephaneLenclud@395:
StephaneLenclud@395: //
StephaneLenclud@395: // Generic Section
StephaneLenclud@395: //
StephaneLenclud@395:
StephaneLenclud@395: GenericRead = 0x80000000,
StephaneLenclud@395: GenericWrite = 0x40000000,
StephaneLenclud@395: GenericExecute = 0x20000000,
StephaneLenclud@395: GenericAll = 0x10000000,
StephaneLenclud@395:
StephaneLenclud@395: SPECIFIC_RIGHTS_ALL = 0x00FFFF,
StephaneLenclud@395: FILE_ALL_ACCESS =
StephaneLenclud@395: StandardRightsRequired |
StephaneLenclud@395: Synchronize |
StephaneLenclud@395: 0x1FF,
StephaneLenclud@395:
StephaneLenclud@395: FILE_GENERIC_READ =
StephaneLenclud@395: StandardRightsRead |
StephaneLenclud@395: FILE_READ_DATA |
StephaneLenclud@395: FILE_READ_ATTRIBUTES |
StephaneLenclud@395: FILE_READ_EA |
StephaneLenclud@395: Synchronize,
StephaneLenclud@395:
StephaneLenclud@395: FILE_GENERIC_WRITE =
StephaneLenclud@395: StandardRightsWrite |
StephaneLenclud@395: FILE_WRITE_DATA |
StephaneLenclud@395: FILE_WRITE_ATTRIBUTES |
StephaneLenclud@395: FILE_WRITE_EA |
StephaneLenclud@395: FILE_APPEND_DATA |
StephaneLenclud@395: Synchronize,
StephaneLenclud@395:
StephaneLenclud@395: FILE_GENERIC_EXECUTE =
StephaneLenclud@395: StandardRightsExecute |
StephaneLenclud@395: FILE_READ_ATTRIBUTES |
StephaneLenclud@395: FILE_EXECUTE |
StephaneLenclud@395: Synchronize
StephaneLenclud@395: }
StephaneLenclud@395:
StephaneLenclud@395: [Flags]
StephaneLenclud@395: public enum EFileShare : uint
StephaneLenclud@395: {
StephaneLenclud@395: ///
StephaneLenclud@395: ///
StephaneLenclud@395: ///
StephaneLenclud@395: None = 0x00000000,
StephaneLenclud@395: ///
StephaneLenclud@395: /// Enables subsequent open operations on an object to request read access.
StephaneLenclud@395: /// Otherwise, other processes cannot open the object if they request read access.
StephaneLenclud@395: /// If this flag is not specified, but the object has been opened for read access, the function fails.
StephaneLenclud@395: ///
StephaneLenclud@395: Read = 0x00000001,
StephaneLenclud@395: ///
StephaneLenclud@395: /// Enables subsequent open operations on an object to request write access.
StephaneLenclud@395: /// Otherwise, other processes cannot open the object if they request write access.
StephaneLenclud@395: /// If this flag is not specified, but the object has been opened for write access, the function fails.
StephaneLenclud@395: ///
StephaneLenclud@395: Write = 0x00000002,
StephaneLenclud@395: ///
StephaneLenclud@395: /// Enables subsequent open operations on an object to request delete access.
StephaneLenclud@395: /// Otherwise, other processes cannot open the object if they request delete access.
StephaneLenclud@395: /// If this flag is not specified, but the object has been opened for delete access, the function fails.
StephaneLenclud@395: ///
StephaneLenclud@395: Delete = 0x00000004
StephaneLenclud@395: }
StephaneLenclud@395:
StephaneLenclud@395: public enum ECreationDisposition : uint
StephaneLenclud@395: {
StephaneLenclud@395: ///
StephaneLenclud@395: /// Creates a new file. The function fails if a specified file exists.
StephaneLenclud@395: ///
StephaneLenclud@395: New = 1,
StephaneLenclud@395: ///
StephaneLenclud@395: /// Creates a new file, always.
StephaneLenclud@395: /// If a file exists, the function overwrites the file, clears the existing attributes, combines the specified file attributes,
StephaneLenclud@395: /// and flags with FILE_ATTRIBUTE_ARCHIVE, but does not set the security descriptor that the SECURITY_ATTRIBUTES structure specifies.
StephaneLenclud@395: ///
StephaneLenclud@395: CreateAlways = 2,
StephaneLenclud@395: ///
StephaneLenclud@395: /// Opens a file. The function fails if the file does not exist.
StephaneLenclud@395: ///
StephaneLenclud@395: OpenExisting = 3,
StephaneLenclud@395: ///
StephaneLenclud@395: /// Opens a file, always.
StephaneLenclud@395: /// If a file does not exist, the function creates a file as if dwCreationDisposition is CREATE_NEW.
StephaneLenclud@395: ///
StephaneLenclud@395: OpenAlways = 4,
StephaneLenclud@395: ///
StephaneLenclud@395: /// Opens a file and truncates it so that its size is 0 (zero) bytes. The function fails if the file does not exist.
StephaneLenclud@395: /// The calling process must open the file with the GENERIC_WRITE access right.
StephaneLenclud@395: ///
StephaneLenclud@395: TruncateExisting = 5
StephaneLenclud@395: }
StephaneLenclud@395:
StephaneLenclud@395: [Flags]
StephaneLenclud@395: public enum EFileAttributes : uint
StephaneLenclud@395: {
StephaneLenclud@395: None = 0x00000000,
StephaneLenclud@395: Readonly = 0x00000001,
StephaneLenclud@395: Hidden = 0x00000002,
StephaneLenclud@395: System = 0x00000004,
StephaneLenclud@395: Directory = 0x00000010,
StephaneLenclud@395: Archive = 0x00000020,
StephaneLenclud@395: Device = 0x00000040,
StephaneLenclud@395: Normal = 0x00000080,
StephaneLenclud@395: Temporary = 0x00000100,
StephaneLenclud@395: SparseFile = 0x00000200,
StephaneLenclud@395: ReparsePoint = 0x00000400,
StephaneLenclud@395: Compressed = 0x00000800,
StephaneLenclud@395: Offline = 0x00001000,
StephaneLenclud@395: NotContentIndexed = 0x00002000,
StephaneLenclud@395: Encrypted = 0x00004000,
StephaneLenclud@395: Write_Through = 0x80000000,
StephaneLenclud@395: Overlapped = 0x40000000,
StephaneLenclud@395: NoBuffering = 0x20000000,
StephaneLenclud@395: RandomAccess = 0x10000000,
StephaneLenclud@395: SequentialScan = 0x08000000,
StephaneLenclud@395: DeleteOnClose = 0x04000000,
StephaneLenclud@395: BackupSemantics = 0x02000000,
StephaneLenclud@395: PosixSemantics = 0x01000000,
StephaneLenclud@395: OpenReparsePoint = 0x00200000,
StephaneLenclud@395: OpenNoRecall = 0x00100000,
StephaneLenclud@395: FirstPipeInstance = 0x00080000
StephaneLenclud@395: }
StephaneLenclud@395:
StephaneLenclud@394: [DllImport("kernel32.dll", SetLastError = true)]
StephaneLenclud@394: public static extern SafeFileHandle CreateNamedPipe(
StephaneLenclud@394: String pipeName,
StephaneLenclud@394: uint dwOpenMode,
StephaneLenclud@394: uint dwPipeMode,
StephaneLenclud@394: uint nMaxInstances,
StephaneLenclud@394: uint nOutBufferSize,
StephaneLenclud@394: uint nInBufferSize,
StephaneLenclud@394: uint nDefaultTimeOut,
StephaneLenclud@394: IntPtr lpSecurityAttributes);
StephaneLenclud@394:
StephaneLenclud@394: [DllImport("kernel32.dll", SetLastError = true)]
StephaneLenclud@394: public static extern int ConnectNamedPipe(
StephaneLenclud@394: SafeFileHandle hNamedPipe,
StephaneLenclud@394: IntPtr lpOverlapped);
StephaneLenclud@394:
StephaneLenclud@394: [DllImport("kernel32.dll", SetLastError = true)]
StephaneLenclud@394: public static extern int DisconnectNamedPipe(
StephaneLenclud@394: SafeFileHandle hNamedPipe);
StephaneLenclud@394:
StephaneLenclud@395: [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
StephaneLenclud@395: public static extern SafeFileHandle CreateFile(
StephaneLenclud@395: string lpFileName,
StephaneLenclud@395: EFileAccess dwDesiredAccess,
StephaneLenclud@395: EFileShare dwShareMode,
StephaneLenclud@395: IntPtr lpSecurityAttributes,
StephaneLenclud@395: ECreationDisposition dwCreationDisposition,
StephaneLenclud@395: EFileAttributes dwFlagsAndAttributes,
StephaneLenclud@395: IntPtr hTemplateFile);
StephaneLenclud@395:
StephaneLenclud@395: //[DllImport("kernel32.dll", SetLastError = true)]
StephaneLenclud@395: //static extern bool CloseHandle(IntPtr hHandle);
StephaneLenclud@395:
StephaneLenclud@394: public const uint PIPE_ACCESS_DUPLEX = (0x00000003);
StephaneLenclud@394: public const uint FILE_FLAG_OVERLAPPED = (0x40000000);
StephaneLenclud@394: public const uint PIPE_ACCESS_OUTBOUND = (0x00000002);
StephaneLenclud@394: public const uint PIPE_ACCESS_INBOUND = (0x00000001);
StephaneLenclud@394: public const uint PIPE_TYPE_BYTE = (0x00000000);
StephaneLenclud@394: public const uint PIPE_UNLIMITED_INSTANCES = 255;
StephaneLenclud@394:
StephaneLenclud@394:
StephaneLenclud@394:
StephaneLenclud@394:
StephaneLenclud@394: public const int BUFFER_SIZE = 256;
StephaneLenclud@394:
StephaneLenclud@394: //
StephaneLenclud@394: public string iPipeNameOutbound;
StephaneLenclud@394: SafeFileHandle iPipeOutbound;
StephaneLenclud@394: public FileStream iStreamOutbound;
StephaneLenclud@394: //
StephaneLenclud@394: public string iPipeNameInbound;
StephaneLenclud@394: Thread iThreadInbound;
StephaneLenclud@394: SafeFileHandle iPipeInbound;
StephaneLenclud@394: public FileStream iStreamInbound;
StephaneLenclud@394:
StephaneLenclud@395: private bool iQuit = false;
StephaneLenclud@395:
StephaneLenclud@394:
StephaneLenclud@394: public Server(string aPipeNameOutbound, string aPipeNameInbound)
StephaneLenclud@394: {
StephaneLenclud@394: iPipeNameOutbound = aPipeNameOutbound;
StephaneLenclud@394: iPipeNameInbound = aPipeNameInbound;
StephaneLenclud@394: }
StephaneLenclud@394:
StephaneLenclud@394: /**
StephaneLenclud@394: * Start our services.
StephaneLenclud@394: */
StephaneLenclud@394: public void Start()
StephaneLenclud@394: {
StephaneLenclud@394: //Start inbound thread to receive messages
StephaneLenclud@394: this.iThreadInbound = new Thread(new ThreadStart(ThreadInbound));
StephaneLenclud@394: this.iThreadInbound.Start();
StephaneLenclud@394: }
StephaneLenclud@394:
StephaneLenclud@394: /**
StephaneLenclud@395: * Stop our services.
StephaneLenclud@394: */
StephaneLenclud@395: public void Stop()
StephaneLenclud@394: {
StephaneLenclud@395: iQuit = true;
StephaneLenclud@395: }
StephaneLenclud@394:
StephaneLenclud@394:
StephaneLenclud@394: /**
StephaneLenclud@394: * Inbound thread is receiving messages from our client
StephaneLenclud@394: */
StephaneLenclud@394: private void ThreadInbound()
StephaneLenclud@394: {
StephaneLenclud@394:
StephaneLenclud@395: //Keep on trying to connect on our read pipe
StephaneLenclud@395: while ((iPipeInbound == null || iPipeInbound.IsInvalid) && !iQuit)
StephaneLenclud@395: {
StephaneLenclud@395: Trace.WriteLine("Trying to connect to inbound pipe...");
StephaneLenclud@395: iPipeInbound = CreateFile(iPipeNameInbound, EFileAccess.GenericRead, EFileShare.None, IntPtr.Zero, ECreationDisposition.OpenExisting, EFileAttributes.None, IntPtr.Zero);
StephaneLenclud@395: System.Threading.Thread.Sleep(1000);
StephaneLenclud@395: }
StephaneLenclud@395:
StephaneLenclud@394:
StephaneLenclud@394: //Client now connected create our inbound stream
StephaneLenclud@395: if (iPipeInbound!=null && !iPipeInbound.IsInvalid)
StephaneLenclud@395: {
StephaneLenclud@395: iStreamInbound = new FileStream(iPipeInbound, FileAccess.Read, BUFFER_SIZE, false);
StephaneLenclud@395: if (iStreamInbound.CanRead)
StephaneLenclud@395: {
StephaneLenclud@395: Trace.WriteLine("Inbound stream ready!");
StephaneLenclud@395: }
StephaneLenclud@395: }
StephaneLenclud@394:
StephaneLenclud@394:
StephaneLenclud@395: //Keep on trying to connect to our write pipe
StephaneLenclud@395: while ((iPipeOutbound == null || iPipeOutbound.IsInvalid) && !iQuit)
StephaneLenclud@395: {
StephaneLenclud@395: Trace.WriteLine("Trying to connect to outbound pipe...");
StephaneLenclud@395: iPipeOutbound = CreateFile(iPipeNameOutbound, EFileAccess.GenericWrite, EFileShare.None, IntPtr.Zero, ECreationDisposition.OpenExisting, EFileAttributes.None, IntPtr.Zero);
StephaneLenclud@395: System.Threading.Thread.Sleep(1000);
StephaneLenclud@395: }
StephaneLenclud@395:
StephaneLenclud@395:
StephaneLenclud@395: //Client now connected create our stream
StephaneLenclud@395: if (iPipeOutbound!=null && !iPipeOutbound.IsInvalid)
StephaneLenclud@395: {
StephaneLenclud@395: iStreamOutbound = new FileStream(iPipeOutbound, FileAccess.Write, BUFFER_SIZE, false);
StephaneLenclud@395:
StephaneLenclud@395: if (iStreamOutbound.CanWrite)
StephaneLenclud@395: {
StephaneLenclud@395: Trace.WriteLine("Outbound stream ready!");
StephaneLenclud@395: }
StephaneLenclud@395: }
StephaneLenclud@395:
StephaneLenclud@395:
StephaneLenclud@395: //Listening loop
StephaneLenclud@394: byte[] buffer = null;
StephaneLenclud@394: ASCIIEncoding encoder = new ASCIIEncoding();
StephaneLenclud@394:
StephaneLenclud@395: while (!iQuit)
StephaneLenclud@394: {
StephaneLenclud@394: int bytesRead = 0;
StephaneLenclud@394:
StephaneLenclud@394: try
StephaneLenclud@394: {
StephaneLenclud@394: buffer = new byte[BUFFER_SIZE];
StephaneLenclud@394: bytesRead = iStreamInbound.Read(buffer, 0, BUFFER_SIZE);
StephaneLenclud@394: }
StephaneLenclud@394: catch
StephaneLenclud@394: {
StephaneLenclud@394: //read error has occurred
StephaneLenclud@394: break;
StephaneLenclud@394: }
StephaneLenclud@394:
StephaneLenclud@394: //client has disconnected
StephaneLenclud@394: if (bytesRead == 0)
StephaneLenclud@394: break;
StephaneLenclud@394:
StephaneLenclud@394: //fire message received event
StephaneLenclud@394: //if (this.MessageReceived != null)
StephaneLenclud@394: // this.MessageReceived(clientse, encoder.GetString(buffer, 0, bytesRead));
StephaneLenclud@394:
StephaneLenclud@394: int ReadLength = 0;
StephaneLenclud@394: for (int i = 0; i < BUFFER_SIZE; i++)
StephaneLenclud@394: {
StephaneLenclud@394: //if (buffer[i].ToString("x2") != "cc")
StephaneLenclud@394: if (buffer[i] != 0)
StephaneLenclud@394: {
StephaneLenclud@394: ReadLength++;
StephaneLenclud@394: }
StephaneLenclud@394: else
StephaneLenclud@394: break;
StephaneLenclud@394: }
StephaneLenclud@394: if (ReadLength > 0)
StephaneLenclud@394: {
StephaneLenclud@394: byte[] Rc = new byte[ReadLength];
StephaneLenclud@394: Buffer.BlockCopy(buffer, 0, Rc, 0, ReadLength);
StephaneLenclud@402: string msg = encoder.GetString(Rc, 0, ReadLength);
StephaneLenclud@402: Trace.WriteLine(msg);
StephaneLenclud@402: Trace.WriteLine("Received " + ReadLength + " Bytes: " + msg);
StephaneLenclud@394: buffer.Initialize();
StephaneLenclud@394: }
StephaneLenclud@394:
StephaneLenclud@394: }
StephaneLenclud@394:
StephaneLenclud@395:
StephaneLenclud@394: //clean up resources
StephaneLenclud@395: if (iStreamInbound!=null) iStreamInbound.Close();
StephaneLenclud@395: if (iPipeInbound != null) iPipeInbound.Close();
StephaneLenclud@395: //
StephaneLenclud@395: if (iStreamOutbound != null) iStreamOutbound.Close();
StephaneLenclud@395: if (iPipeOutbound != null) iPipeOutbound.Close();
StephaneLenclud@394: }
StephaneLenclud@394:
StephaneLenclud@394: /**
StephaneLenclud@394: * Send a message to our client.
StephaneLenclud@394: */
StephaneLenclud@394: public void SendMessage(string message)
StephaneLenclud@394: {
StephaneLenclud@397: byte[] m8 = new byte[message.Length];
StephaneLenclud@397: int i = 0;
StephaneLenclud@397: foreach (char c in message)
StephaneLenclud@397: {
StephaneLenclud@397: m8[i]=System.Convert.ToByte(c);
StephaneLenclud@397: i++;
StephaneLenclud@397: }
StephaneLenclud@394:
StephaneLenclud@397: //ASCIIEncoding encoder = new ASCIIEncoding();
StephaneLenclud@397: //byte[] messageBuffer = encoder.GetBytes(message);
StephaneLenclud@394:
StephaneLenclud@397: if (iStreamOutbound != null && iStreamOutbound.CanWrite)
StephaneLenclud@397: {
StephaneLenclud@397: //iStreamOutbound.Write(messageBuffer, 0, messageBuffer.Length);
StephaneLenclud@397: iStreamOutbound.Write(m8, 0, message.Length);
StephaneLenclud@397: iStreamOutbound.Flush();
StephaneLenclud@397: }
StephaneLenclud@394:
StephaneLenclud@394:
StephaneLenclud@394: }
StephaneLenclud@394:
StephaneLenclud@394:
StephaneLenclud@394: }
StephaneLenclud@394: }