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@436
|
13 |
[DllImport("kernel32.dll", SetLastError = true)]
|
StephaneLenclud@436
|
14 |
public static extern SafeFileHandle CreateNamedPipe(
|
StephaneLenclud@436
|
15 |
String pipeName,
|
StephaneLenclud@436
|
16 |
uint dwOpenMode,
|
StephaneLenclud@436
|
17 |
uint dwPipeMode,
|
StephaneLenclud@436
|
18 |
uint nMaxInstances,
|
StephaneLenclud@436
|
19 |
uint nOutBufferSize,
|
StephaneLenclud@436
|
20 |
uint nInBufferSize,
|
StephaneLenclud@436
|
21 |
uint nDefaultTimeOut,
|
StephaneLenclud@436
|
22 |
IntPtr lpSecurityAttributes);
|
StephaneLenclud@436
|
23 |
|
StephaneLenclud@436
|
24 |
[DllImport("kernel32.dll", SetLastError = true)]
|
StephaneLenclud@436
|
25 |
public static extern int ConnectNamedPipe(
|
StephaneLenclud@436
|
26 |
SafeFileHandle hNamedPipe,
|
StephaneLenclud@436
|
27 |
IntPtr lpOverlapped);
|
StephaneLenclud@436
|
28 |
|
StephaneLenclud@436
|
29 |
[DllImport("kernel32.dll", SetLastError = true)]
|
StephaneLenclud@436
|
30 |
public static extern int DisconnectNamedPipe(
|
StephaneLenclud@436
|
31 |
SafeFileHandle hNamedPipe);
|
StephaneLenclud@436
|
32 |
|
StephaneLenclud@436
|
33 |
public const uint PIPE_ACCESS_DUPLEX = (0x00000003);
|
StephaneLenclud@436
|
34 |
public const uint FILE_FLAG_OVERLAPPED = (0x40000000);
|
StephaneLenclud@436
|
35 |
public const uint PIPE_ACCESS_OUTBOUND = (0x00000002);
|
StephaneLenclud@436
|
36 |
public const uint PIPE_ACCESS_INBOUND = (0x00000001);
|
StephaneLenclud@436
|
37 |
public const uint PIPE_TYPE_BYTE = (0x00000000);
|
StephaneLenclud@436
|
38 |
public const uint PIPE_UNLIMITED_INSTANCES = 255;
|
StephaneLenclud@436
|
39 |
|
StephaneLenclud@436
|
40 |
|
StephaneLenclud@436
|
41 |
|
StephaneLenclud@436
|
42 |
|
StephaneLenclud@436
|
43 |
public const int BUFFER_SIZE = 256;
|
StephaneLenclud@436
|
44 |
|
StephaneLenclud@436
|
45 |
//
|
StephaneLenclud@436
|
46 |
public string iPipeNameOutbound;
|
StephaneLenclud@436
|
47 |
Thread iThreadOutbound;
|
StephaneLenclud@436
|
48 |
SafeFileHandle iPipeOutbound;
|
StephaneLenclud@436
|
49 |
public FileStream iStreamOutbound;
|
StephaneLenclud@436
|
50 |
//
|
StephaneLenclud@436
|
51 |
public string iPipeNameInbound;
|
StephaneLenclud@436
|
52 |
Thread iThreadInbound;
|
StephaneLenclud@436
|
53 |
SafeFileHandle iPipeInbound;
|
StephaneLenclud@436
|
54 |
public FileStream iStreamInbound;
|
StephaneLenclud@436
|
55 |
|
StephaneLenclud@436
|
56 |
|
StephaneLenclud@436
|
57 |
public Server(string aPipeNameOutbound, string aPipeNameInbound)
|
StephaneLenclud@436
|
58 |
{
|
StephaneLenclud@436
|
59 |
iPipeNameOutbound = aPipeNameOutbound;
|
StephaneLenclud@436
|
60 |
iPipeNameInbound = aPipeNameInbound;
|
StephaneLenclud@436
|
61 |
}
|
StephaneLenclud@436
|
62 |
|
StephaneLenclud@436
|
63 |
/**
|
StephaneLenclud@436
|
64 |
* Start our services.
|
StephaneLenclud@436
|
65 |
*/
|
StephaneLenclud@436
|
66 |
public void Start()
|
StephaneLenclud@436
|
67 |
{
|
StephaneLenclud@436
|
68 |
//Start outbound thread to send messages
|
StephaneLenclud@436
|
69 |
this.iThreadOutbound = new Thread(new ThreadStart(ThreadOutbound));
|
StephaneLenclud@436
|
70 |
this.iThreadOutbound.Start();
|
StephaneLenclud@436
|
71 |
//Start inbound thread to receive messages
|
StephaneLenclud@436
|
72 |
this.iThreadInbound = new Thread(new ThreadStart(ThreadInbound));
|
StephaneLenclud@436
|
73 |
this.iThreadInbound.Start();
|
StephaneLenclud@436
|
74 |
}
|
StephaneLenclud@436
|
75 |
|
StephaneLenclud@436
|
76 |
/**
|
StephaneLenclud@436
|
77 |
* Outbound thread is sending messages to our client.
|
StephaneLenclud@436
|
78 |
*/
|
StephaneLenclud@436
|
79 |
private void ThreadOutbound()
|
StephaneLenclud@436
|
80 |
{
|
StephaneLenclud@436
|
81 |
|
StephaneLenclud@436
|
82 |
//Create our outbound named pipe
|
StephaneLenclud@436
|
83 |
iPipeOutbound = CreateNamedPipe(this.iPipeNameOutbound, PIPE_ACCESS_OUTBOUND /*| FILE_FLAG_OVERLAPPED*/, PIPE_TYPE_BYTE, PIPE_UNLIMITED_INSTANCES, BUFFER_SIZE, BUFFER_SIZE, 0, IntPtr.Zero);
|
StephaneLenclud@436
|
84 |
|
StephaneLenclud@436
|
85 |
//Could not create named pipe
|
StephaneLenclud@436
|
86 |
if (iPipeOutbound.IsInvalid)
|
StephaneLenclud@436
|
87 |
{
|
StephaneLenclud@436
|
88 |
//TODO: error handling
|
StephaneLenclud@436
|
89 |
return;
|
StephaneLenclud@436
|
90 |
}
|
StephaneLenclud@436
|
91 |
|
StephaneLenclud@436
|
92 |
//Will complete once our client connects
|
StephaneLenclud@436
|
93 |
int success = ConnectNamedPipe(iPipeOutbound, IntPtr.Zero);
|
StephaneLenclud@436
|
94 |
|
StephaneLenclud@436
|
95 |
//could not connect client
|
StephaneLenclud@436
|
96 |
if (success == 0)
|
StephaneLenclud@436
|
97 |
{
|
StephaneLenclud@436
|
98 |
//TODO: error handling
|
StephaneLenclud@436
|
99 |
return;
|
StephaneLenclud@436
|
100 |
}
|
StephaneLenclud@436
|
101 |
|
StephaneLenclud@436
|
102 |
//Client now connected create our stream
|
StephaneLenclud@436
|
103 |
iStreamOutbound = new FileStream(iPipeOutbound, FileAccess.Write, BUFFER_SIZE, false);
|
StephaneLenclud@436
|
104 |
|
StephaneLenclud@436
|
105 |
}
|
StephaneLenclud@436
|
106 |
|
StephaneLenclud@436
|
107 |
/**
|
StephaneLenclud@436
|
108 |
* Inbound thread is receiving messages from our client
|
StephaneLenclud@436
|
109 |
*/
|
StephaneLenclud@436
|
110 |
private void ThreadInbound()
|
StephaneLenclud@436
|
111 |
{
|
StephaneLenclud@436
|
112 |
//Client client = (Client)clientObj;
|
StephaneLenclud@436
|
113 |
//clientse.stream = new FileStream(clientse.handle, FileAccess.ReadWrite, BUFFER_SIZE, true);
|
StephaneLenclud@436
|
114 |
|
StephaneLenclud@436
|
115 |
iPipeInbound = CreateNamedPipe(this.iPipeNameInbound, PIPE_ACCESS_INBOUND, PIPE_TYPE_BYTE, PIPE_UNLIMITED_INSTANCES, BUFFER_SIZE, BUFFER_SIZE, 0, IntPtr.Zero);
|
StephaneLenclud@436
|
116 |
|
StephaneLenclud@436
|
117 |
//could not create named pipe
|
StephaneLenclud@436
|
118 |
if (iPipeInbound.IsInvalid)
|
StephaneLenclud@436
|
119 |
return;
|
StephaneLenclud@436
|
120 |
|
StephaneLenclud@436
|
121 |
//Will complete once a client connects
|
StephaneLenclud@436
|
122 |
int success = ConnectNamedPipe(iPipeInbound, IntPtr.Zero);
|
StephaneLenclud@436
|
123 |
|
StephaneLenclud@436
|
124 |
//could not connect client
|
StephaneLenclud@436
|
125 |
if (success == 0)
|
StephaneLenclud@436
|
126 |
return;
|
StephaneLenclud@436
|
127 |
|
StephaneLenclud@436
|
128 |
//Client now connected create our inbound stream
|
StephaneLenclud@436
|
129 |
iStreamInbound = new FileStream(iPipeInbound, FileAccess.Read, BUFFER_SIZE, false);
|
StephaneLenclud@436
|
130 |
|
StephaneLenclud@436
|
131 |
|
StephaneLenclud@436
|
132 |
byte[] buffer = null;
|
StephaneLenclud@436
|
133 |
ASCIIEncoding encoder = new ASCIIEncoding();
|
StephaneLenclud@436
|
134 |
|
StephaneLenclud@436
|
135 |
while (true)
|
StephaneLenclud@436
|
136 |
{
|
StephaneLenclud@436
|
137 |
int bytesRead = 0;
|
StephaneLenclud@436
|
138 |
|
StephaneLenclud@436
|
139 |
try
|
StephaneLenclud@436
|
140 |
{
|
StephaneLenclud@436
|
141 |
buffer = new byte[BUFFER_SIZE];
|
StephaneLenclud@436
|
142 |
bytesRead = iStreamInbound.Read(buffer, 0, BUFFER_SIZE);
|
StephaneLenclud@436
|
143 |
}
|
StephaneLenclud@436
|
144 |
catch
|
StephaneLenclud@436
|
145 |
{
|
StephaneLenclud@436
|
146 |
//read error has occurred
|
StephaneLenclud@436
|
147 |
break;
|
StephaneLenclud@436
|
148 |
}
|
StephaneLenclud@436
|
149 |
|
StephaneLenclud@436
|
150 |
//client has disconnected
|
StephaneLenclud@436
|
151 |
if (bytesRead == 0)
|
StephaneLenclud@436
|
152 |
break;
|
StephaneLenclud@436
|
153 |
|
StephaneLenclud@436
|
154 |
//fire message received event
|
StephaneLenclud@436
|
155 |
//if (this.MessageReceived != null)
|
StephaneLenclud@436
|
156 |
// this.MessageReceived(clientse, encoder.GetString(buffer, 0, bytesRead));
|
StephaneLenclud@436
|
157 |
|
StephaneLenclud@436
|
158 |
int ReadLength = 0;
|
StephaneLenclud@436
|
159 |
for (int i = 0; i < BUFFER_SIZE; i++)
|
StephaneLenclud@436
|
160 |
{
|
StephaneLenclud@436
|
161 |
//if (buffer[i].ToString("x2") != "cc")
|
StephaneLenclud@436
|
162 |
if (buffer[i] != 0)
|
StephaneLenclud@436
|
163 |
{
|
StephaneLenclud@436
|
164 |
ReadLength++;
|
StephaneLenclud@436
|
165 |
}
|
StephaneLenclud@436
|
166 |
else
|
StephaneLenclud@436
|
167 |
break;
|
StephaneLenclud@436
|
168 |
}
|
StephaneLenclud@436
|
169 |
if (ReadLength > 0)
|
StephaneLenclud@436
|
170 |
{
|
StephaneLenclud@436
|
171 |
byte[] Rc = new byte[ReadLength];
|
StephaneLenclud@436
|
172 |
Buffer.BlockCopy(buffer, 0, Rc, 0, ReadLength);
|
StephaneLenclud@436
|
173 |
|
StephaneLenclud@436
|
174 |
Console.WriteLine(encoder.GetString(Rc, 0, ReadLength));
|
StephaneLenclud@436
|
175 |
Trace.WriteLine("Received " + ReadLength + " Bytes: " + encoder.GetString(Rc, 0, ReadLength));
|
StephaneLenclud@436
|
176 |
buffer.Initialize();
|
StephaneLenclud@436
|
177 |
}
|
StephaneLenclud@436
|
178 |
|
StephaneLenclud@436
|
179 |
}
|
StephaneLenclud@436
|
180 |
|
StephaneLenclud@436
|
181 |
//clean up resources
|
StephaneLenclud@436
|
182 |
iStreamInbound.Close();
|
StephaneLenclud@436
|
183 |
iPipeInbound.Close();
|
StephaneLenclud@436
|
184 |
}
|
StephaneLenclud@436
|
185 |
|
StephaneLenclud@436
|
186 |
/**
|
StephaneLenclud@436
|
187 |
* Send a message to our client.
|
StephaneLenclud@436
|
188 |
*/
|
StephaneLenclud@436
|
189 |
public void SendMessage(string message)
|
StephaneLenclud@436
|
190 |
{
|
StephaneLenclud@436
|
191 |
|
StephaneLenclud@436
|
192 |
ASCIIEncoding encoder = new ASCIIEncoding();
|
StephaneLenclud@436
|
193 |
byte[] messageBuffer = encoder.GetBytes(message);
|
StephaneLenclud@436
|
194 |
|
StephaneLenclud@436
|
195 |
if (iStreamOutbound.CanWrite)
|
StephaneLenclud@436
|
196 |
{
|
StephaneLenclud@436
|
197 |
iStreamOutbound.Write(messageBuffer, 0, messageBuffer.Length);
|
StephaneLenclud@436
|
198 |
iStreamOutbound.Flush();
|
StephaneLenclud@436
|
199 |
}
|
StephaneLenclud@436
|
200 |
|
StephaneLenclud@436
|
201 |
|
StephaneLenclud@436
|
202 |
}
|
StephaneLenclud@436
|
203 |
|
StephaneLenclud@436
|
204 |
/**
|
StephaneLenclud@436
|
205 |
*
|
StephaneLenclud@436
|
206 |
*/
|
StephaneLenclud@436
|
207 |
public void Stop()
|
StephaneLenclud@436
|
208 |
{
|
StephaneLenclud@436
|
209 |
//clean up resources
|
StephaneLenclud@436
|
210 |
|
StephaneLenclud@436
|
211 |
DisconnectNamedPipe(this.iPipeOutbound);
|
StephaneLenclud@436
|
212 |
|
StephaneLenclud@436
|
213 |
//TODO: more cleanup
|
StephaneLenclud@436
|
214 |
|
StephaneLenclud@436
|
215 |
|
StephaneLenclud@436
|
216 |
this.iThreadOutbound.Abort();
|
StephaneLenclud@436
|
217 |
}
|
StephaneLenclud@436
|
218 |
|
StephaneLenclud@436
|
219 |
}
|
StephaneLenclud@436
|
220 |
}
|