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