Reputation: 5784
How do I go about making a socket policy file server in C#. All it has to do is listen on port 843 for the string "<policy-file-request/>" followed by a NULL byte and then return an XML string (which is the socket policy file).
I haven't coded this sort of thing before and am unsure of where to start. Do I create it in a windows service? Any tips or links are welcome.
Background:
To contact a web service from flash I am using the 'as3httpclient' library instead of the URLRequest/URLLoader. This is because it gives me the ability to send custom headers with GET requests. This library uses low-level sockets to do its stuff.
When flash uses low-level sockets to connect to a server it looks for a socket policy file - and this needs to be served up by a socket policy file server.
Socket Policy File Article from Adobe
Upvotes: 0
Views: 4726
Reputation: 1659
I had to to this task with both Java and C#, they are quite similar.
You can have a look at java policy file.
Some issue can see at this answer: https://stackoverflow.com/a/12854204/1343667
Upvotes: 0
Reputation: 120420
A few things to be aware of using your suggested architecture:
Trying to send an HTTP request over sockets
Principally, you need to be aware that even though you can chat http at a lower level using sockets, there are a large number of cases where communication in this fashion will fail. Mainly these failures will occur if the user has a proxy server enabled in their browser, as there is no effective means of discovering and subsequently using the proxy when connecting via a socket.
In order to make a policy server, you can use the TcpListener class. You would start listening as follows:
var tcpListener = new TcpListener(IPAddress.Any, 843 );
tcpListener.start();
tcpListener.BeginAcceptTcpClient(new AsyncCallback(NewClientHandler), null);
The method NewClientHandler would have the form:
private void NewClientHandler(IAsyncResult ar)
{
TcpClient tcpClient = tcpListener.EndAcceptTcpClient(ar);
...
At which point you might want to supply the tcpClient object to a class of your own creation to handle the validation of the data coming from the socket. I'm going to call it RemoteClient.
In RemoteClient, you'd have something like this:
var buffer=new byte[BUFFER_SIZE];
tcpClient.GetStream().BeginRead(buffer, 0, buffer.Length, Receive, null);
and a Receive method:
private void Receive(IAsyncResult ar)
{
int bytesRead;
try
{
bytesRead = tcpClient.GetStream().EndRead(ar);
}
catch (Exception e)
{
//something bad happened. Cleanup required
return;
}
if (bytesRead != 0)
{
char[] charBuffer = utf8Encoding.GetChars(buffer, 0, bytesRead);
try
{
tcpClient.GetStream().BeginRead(buffer, 0, buffer.Length, Receive, null);
}
catch (Exception e)
{
//something bad happened. Cleanup required
}
}
else
{
//socket closed, I think?
return;
}
}
and some send methods:
public void Send(XmlDocument doc)
{
Send(doc.OuterXml);
}
private void Send(String str)
{
Byte[] sendBuf = utf8Encoding.GetBytes(str);
Send(sendBuf);
}
private void Send(Byte[] sendBuf)
{
try
{
tcpClient.GetStream().Write(sendBuf, 0, sendBuf.Length);
tcpClient.GetStream().WriteByte(0);
tcpClient.GetStream().WriteByte(13); //very important to terminate XmlSocket data in this way, otherwise Flash can't read it.
}
catch (Exception e)
{
//something bad happened. cleanup?
return;
}
}
That's all the important details I think. I wrote this some time ago... the Receive method looks like it could do with a rework, but it should be enough to get you started.
Upvotes: 8
Reputation: 108975
Create a listening socket.
When a connection is opened, perform a receive and wait for the expected string. When received send the file content and then close the socket.
Wrap this in a service (running as a low privilege account).
Most of the work is done with the System.Net.Sockets.Socket class, the documentation contains a sample, The API is very similar to the BSD socket API overall (largely there is a 1:1 mapping from BSD API to Socket (or help type) method) so any background should be easily translatable.
Upvotes: 1