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