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@436: StephaneLenclud@437: Trace.WriteLine(encoder.GetString(Rc, 0, ReadLength)); StephaneLenclud@436: Trace.WriteLine("Received " + ReadLength + " Bytes: " + encoder.GetString(Rc, 0, ReadLength)); 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@436: StephaneLenclud@436: ASCIIEncoding encoder = new ASCIIEncoding(); StephaneLenclud@436: byte[] messageBuffer = encoder.GetBytes(message); StephaneLenclud@436: StephaneLenclud@437: if (iStreamOutbound != null && iStreamOutbound.CanWrite) StephaneLenclud@436: { StephaneLenclud@436: iStreamOutbound.Write(messageBuffer, 0, messageBuffer.Length); StephaneLenclud@436: iStreamOutbound.Flush(); StephaneLenclud@436: } StephaneLenclud@436: StephaneLenclud@436: StephaneLenclud@436: } StephaneLenclud@436: StephaneLenclud@436: StephaneLenclud@436: } StephaneLenclud@436: }