Imported Upstream version 3.6.0

Former-commit-id: da6be194a6b1221998fc28233f2503bd61dd9d14
This commit is contained in:
Jo Shields
2014-08-13 10:39:27 +01:00
commit a575963da9
50588 changed files with 8155799 additions and 0 deletions

View File

@@ -0,0 +1,50 @@
2006-12-18 Lluis Sanchez Gual <lluis@novell.com>
* UnixBinaryCore.cs: Added some null checks.
* UnixServerChannel.cs: Remoting does not call StartListening anymore
(for MS.NET compatibility), so it has to be explicitely called here.
2006-09-15 Lluis Sanchez Gual <lluis@novell.com>
* UnixServerTransportSink.cs, UnixServerChannel.cs:
When sending an async call response, don't use the original request
stream because it may have been used by another call.
2005-11-02 Jonathan Pryor <jonpryor@vt.edu>
* UnixServerChannel.cs: Use Mono.Unix.Native.Syscall. Mono.Unix.Syscall is
obsolete, and will eventually disappear.
2005-10-18 Robert Jordan <robertj@gmx.net>
* UnixChannel.cs: fixed ParseUnixURL to support channel URLs (those
w/out an objectUri).
2005-09-11 Robert Jordan <robertj@gmx.net>
* UnixChannel.cs: fixed default ctor.
* UnixServerChannel.cs: fixed GetUrlsForUri to return properly
formatted unix URIs (the "?" was missing).
2005-08-24 Lluis Sanchez Gual <lluis@novell.com>
* UnixServerChannel.cs:
* UnixClientChannel.cs: Use the internal binary formatter sink.
* UnixBinaryServerFormatterSink.cs:
* UnixBinaryClientFormatterSinkProvider.cs:
* UnixBinaryClientFormatterSink.cs:
* UnixBinaryCore.cs:
* UnixBinaryServerFormatterSinkProvider.cs: New internal formatter sink,
to avoid dependency with System.Runtime.Remoting.dll.
* UnixClientTransportSink.cs:
* UnixMessageIO.cs: Don't use CommonTransportKeys.
2005-07-28 Lluis Sanchez Gual <lluis@novell.com>
* UnixChannel.cs, UnixClientChannel.cs, UnixClientTransportSink.cs,
UnixClientTransportSinkProvider.cs, UnixMessageIO.cs,
UnixServerChannel.cs, UnixServerTransportSink.cs,
UnixConnectionPool.cs: The new Unix socket remoting channel.

View File

@@ -0,0 +1,167 @@
//
// Mono.Remoting.Channels.Unix.UnixBinaryClientFormatterSink.cs
//
// Author: Rodrigo Moya (rodrigo@ximian.com)
// Dietmar Maurer (dietmar@ximian.com)
// Lluis Sanchez Gual (lluis@ideary.com)
//
// 2002 (C) Copyright, Ximian, Inc.
//
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System;
using System.Collections;
using System.IO;
using System.Runtime.Remoting.Messaging;
using System.Runtime.Remoting.Channels;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
namespace Mono.Remoting.Channels.Unix
{
internal class UnixBinaryClientFormatterSink : IClientFormatterSink, IMessageSink, IClientChannelSink, IChannelSinkBase
{
UnixBinaryCore _binaryCore = UnixBinaryCore.DefaultInstance;
IClientChannelSink _nextInChain;
public UnixBinaryClientFormatterSink (IClientChannelSink nextSink)
{
_nextInChain = nextSink;
}
internal UnixBinaryCore BinaryCore
{
get { return _binaryCore; }
set { _binaryCore = value; }
}
public IClientChannelSink NextChannelSink
{
get {
return _nextInChain;
}
}
public IMessageSink NextSink
{
get {
// This is the last sink in the IMessageSink sink chain
return null;
}
}
public IDictionary Properties
{
get {
return null;
}
}
public void AsyncProcessRequest (IClientChannelSinkStack sinkStack,
IMessage msg,
ITransportHeaders headers,
Stream stream)
{
// never called because the formatter sink is
// always the first in the chain
throw new NotSupportedException("UnixBinaryClientFormatterSink must be the first sink in the IClientChannelSink chain");
}
public void AsyncProcessResponse (IClientResponseChannelSinkStack sinkStack,
object state,
ITransportHeaders headers,
Stream stream)
{
IMessage replyMessage = (IMessage)_binaryCore.Deserializer.DeserializeMethodResponse (stream, null, (IMethodCallMessage)state);
sinkStack.DispatchReplyMessage (replyMessage);
}
public Stream GetRequestStream (IMessage msg,
ITransportHeaders headers)
{
// never called
throw new NotSupportedException ();
}
public void ProcessMessage (IMessage msg,
ITransportHeaders requestHeaders,
Stream requestStream,
out ITransportHeaders responseHeaders,
out Stream responseStream)
{
// never called because the formatter sink is
// always the first in the chain
throw new NotSupportedException ();
}
public IMessageCtrl AsyncProcessMessage (IMessage msg,
IMessageSink replySink)
{
ITransportHeaders transportHeaders = new TransportHeaders();
Stream stream = _nextInChain.GetRequestStream(msg, transportHeaders);
if (stream == null) stream = new MemoryStream ();
_binaryCore.Serializer.Serialize (stream, msg, null);
if (stream is MemoryStream) stream.Position = 0;
ClientChannelSinkStack stack = new ClientChannelSinkStack(replySink);
stack.Push (this, msg);
_nextInChain.AsyncProcessRequest (stack, msg, transportHeaders, stream);
// FIXME: No idea about how to implement IMessageCtrl
return null;
}
public IMessage SyncProcessMessage (IMessage msg)
{
try {
ITransportHeaders call_headers = new TransportHeaders();
call_headers["__RequestUri"] = ((IMethodCallMessage)msg).Uri;
call_headers["Content-Type"] = "application/octet-stream";
Stream call_stream = _nextInChain.GetRequestStream(msg, call_headers);
if (call_stream == null) call_stream = new MemoryStream ();
// Serialize msg to the stream
_binaryCore.Serializer.Serialize (call_stream, msg, null);
if (call_stream is MemoryStream) call_stream.Position = 0;
Stream response_stream;
ITransportHeaders response_headers;
_nextInChain.ProcessMessage (msg, call_headers, call_stream, out response_headers,
out response_stream);
// Deserialize response_stream
return (IMessage) _binaryCore.Deserializer.DeserializeMethodResponse (response_stream, null, (IMethodCallMessage)msg);
} catch (Exception e) {
return new ReturnMessage (e, (IMethodCallMessage)msg);
}
}
}
}

View File

@@ -0,0 +1,80 @@
//
// Mono.Remoting.Channels.Unix.UnixBinaryClientFormatterSinkProvider.cs
//
// Author: Rodrigo Moya (rodrigo@ximian.com)
// Lluis Sanchez Gual (lluis@ximian.com)
//
// 2002 (C) Copyright, Ximian, Inc.
//
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System.Collections;
using System.Runtime.Remoting.Channels;
namespace Mono.Remoting.Channels.Unix
{
internal class UnixBinaryClientFormatterSinkProvider: IClientFormatterSinkProvider, IClientChannelSinkProvider
{
IClientChannelSinkProvider next = null;
UnixBinaryCore _binaryCore;
static string[] allowedProperties = new string [] { "includeVersions", "strictBinding" };
public UnixBinaryClientFormatterSinkProvider ()
{
_binaryCore = UnixBinaryCore.DefaultInstance;
}
public UnixBinaryClientFormatterSinkProvider (IDictionary properties,
ICollection providerData)
{
_binaryCore = new UnixBinaryCore (this, properties, allowedProperties);
}
public IClientChannelSinkProvider Next
{
get {
return next;
}
set {
next = value;
}
}
public IClientChannelSink CreateSink (IChannelSender channel,
string url,
object remoteChannelData)
{
IClientChannelSink next_sink = null;
UnixBinaryClientFormatterSink result;
if (next != null)
next_sink = next.CreateSink (channel, url, remoteChannelData);
result = new UnixBinaryClientFormatterSink (next_sink);
result.BinaryCore = _binaryCore;
return result;
}
}
}

View File

@@ -0,0 +1,148 @@
//
// Mono.Remoting.Channels.Unix.BinaryCore.cs
//
// Author: Lluis Sanchez Gual (lluis@novell.com)
//
// 2005 (C) Copyright, Novell, Inc.
//
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System;
using System.Reflection;
using System.Collections;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Messaging;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters;
using System.Runtime.Serialization.Formatters.Binary;
namespace Mono.Remoting.Channels.Unix
{
internal class UnixBinaryCore
{
BinaryFormatter _serializationFormatter;
BinaryFormatter _deserializationFormatter;
bool _includeVersions = true;
bool _strictBinding = false;
IDictionary _properties;
public static UnixBinaryCore DefaultInstance = new UnixBinaryCore ();
public UnixBinaryCore (object owner, IDictionary properties, string[] allowedProperties)
{
_properties = properties;
foreach(DictionaryEntry property in properties)
{
string key = (string) property.Key;
if (Array.IndexOf (allowedProperties, key) == -1)
throw new RemotingException (owner.GetType().Name + " does not recognize '" + key + "' configuration property");
switch (key)
{
case "includeVersions":
_includeVersions = Convert.ToBoolean (property.Value);
break;
case "strictBinding":
_strictBinding = Convert.ToBoolean (property.Value);
break;
}
}
Init ();
}
public UnixBinaryCore ()
{
_properties = new Hashtable ();
Init ();
}
public void Init ()
{
RemotingSurrogateSelector surrogateSelector = new RemotingSurrogateSelector ();
StreamingContext context = new StreamingContext (StreamingContextStates.Remoting, null);
_serializationFormatter = new BinaryFormatter (surrogateSelector, context);
_deserializationFormatter = new BinaryFormatter (null, context);
if (!_includeVersions)
{
_serializationFormatter.AssemblyFormat = FormatterAssemblyStyle.Simple;
_deserializationFormatter.AssemblyFormat = FormatterAssemblyStyle.Simple;
}
if (!_strictBinding)
{
_serializationFormatter.Binder = SimpleBinder.Instance;
_deserializationFormatter.Binder = SimpleBinder.Instance;
}
}
public BinaryFormatter Serializer
{
get { return _serializationFormatter; }
}
public BinaryFormatter Deserializer
{
get { return _deserializationFormatter; }
}
public IDictionary Properties
{
get { return _properties; }
}
}
internal class SimpleBinder: SerializationBinder
{
public static SimpleBinder Instance = new SimpleBinder ();
public override Type BindToType (String assemblyName, string typeName)
{
Assembly asm;
if (assemblyName.IndexOf (',') != -1)
{
// Try using the full name
try
{
asm = Assembly.Load (assemblyName);
if (asm == null) return null;
Type t = asm.GetType (typeName);
if (t != null) return t;
}
catch {}
}
// Try using the simple name
asm = Assembly.LoadWithPartialName (assemblyName);
if (asm == null) return null;
return asm.GetType (typeName, true);
}
}
}

View File

@@ -0,0 +1,163 @@
//
// Mono.Remoting.Channels.Unix.UnixBinaryServerFormatterSink.cs
//
// Author: Duncan Mak (duncan@ximian.com)
// Lluis Sanchez Gual (lluis@ideary.com)
//
// 2002 (C) Copyright, Ximian, Inc.
//
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System;
using System.Collections;
using System.IO;
using System.Runtime.Remoting.Messaging;
using System.Runtime.Remoting.Channels;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters;
using System.Runtime.Serialization.Formatters.Binary;
using System.Runtime.InteropServices;
namespace Mono.Remoting.Channels.Unix {
internal class UnixBinaryServerFormatterSink : IServerChannelSink, IChannelSinkBase
{
UnixBinaryCore _binaryCore = UnixBinaryCore.DefaultInstance;
IServerChannelSink next_sink;
IChannelReceiver receiver;
public UnixBinaryServerFormatterSink (IServerChannelSink nextSink, IChannelReceiver receiver)
{
this.next_sink = nextSink;
this.receiver = receiver;
}
internal UnixBinaryCore BinaryCore
{
get { return _binaryCore; }
set { _binaryCore = value; }
}
public IServerChannelSink NextChannelSink {
get {
return next_sink;
}
}
public IDictionary Properties {
get {
return null;
}
}
public void AsyncProcessResponse (IServerResponseChannelSinkStack sinkStack, object state,
IMessage message, ITransportHeaders headers, Stream stream)
{
ITransportHeaders responseHeaders = new TransportHeaders();
if (sinkStack != null) stream = sinkStack.GetResponseStream (message, responseHeaders);
if (stream == null) stream = new MemoryStream();
_binaryCore.Serializer.Serialize (stream, message, null);
if (stream is MemoryStream) stream.Position = 0;
sinkStack.AsyncProcessResponse (message, responseHeaders, stream);
}
public Stream GetResponseStream (IServerResponseChannelSinkStack sinkStack, object state,
IMessage msg, ITransportHeaders headers)
{
return null;
}
public ServerProcessing ProcessMessage (IServerChannelSinkStack sinkStack,
IMessage requestMsg, ITransportHeaders requestHeaders, Stream requestStream,
out IMessage responseMsg, out ITransportHeaders responseHeaders, out Stream responseStream)
{
sinkStack.Push (this, null);
ServerProcessing res;
try
{
string url = (string)requestHeaders["__RequestUri"];
string uri;
receiver.Parse (url, out uri);
if (uri == null) uri = url;
MethodCallHeaderHandler mhh = new MethodCallHeaderHandler(uri);
requestMsg = (IMessage) _binaryCore.Deserializer.Deserialize (requestStream, new HeaderHandler(mhh.HandleHeaders));
res = next_sink.ProcessMessage (sinkStack, requestMsg, requestHeaders, null, out responseMsg, out responseHeaders, out responseStream);
}
catch (Exception ex)
{
responseMsg = new ReturnMessage (ex, (IMethodCallMessage)requestMsg);
res = ServerProcessing.Complete;
responseHeaders = null;
responseStream = null;
}
if (res == ServerProcessing.Complete)
{
for (int n=0; n<3; n++) {
responseStream = null;
responseHeaders = new TransportHeaders();
if (sinkStack != null) responseStream = sinkStack.GetResponseStream (responseMsg, responseHeaders);
if (responseStream == null) responseStream = new MemoryStream();
try {
_binaryCore.Serializer.Serialize (responseStream, responseMsg);
break;
} catch (Exception ex) {
if (n == 2) throw ex;
else responseMsg = new ReturnMessage (ex, (IMethodCallMessage)requestMsg);
}
}
if (responseStream is MemoryStream) responseStream.Position = 0;
sinkStack.Pop (this);
}
return res;
}
}
internal class MethodCallHeaderHandler
{
string _uri;
public MethodCallHeaderHandler (string uri)
{
_uri = uri;
}
public object HandleHeaders (Header[] headers)
{
return _uri;
}
}
}

View File

@@ -0,0 +1,85 @@
//
// Mono.Remoting.Channels.Unix.UnixBinaryServerFormatterSinkProvider.cs
//
// Author: Rodrigo Moya (rodrigo@ximian.com)
// Lluis Sanchez Gual (lluis@ximian.com)
//
// 2002 (C) Copyright, Ximian, Inc.
//
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System.Collections;
using System.Runtime.Serialization.Formatters;
using System.Runtime.InteropServices;
using System.Runtime.Remoting.Channels;
namespace Mono.Remoting.Channels.Unix
{
internal class UnixBinaryServerFormatterSinkProvider: IServerFormatterSinkProvider, IServerChannelSinkProvider
{
IServerChannelSinkProvider next = null;
UnixBinaryCore _binaryCore;
internal static string[] AllowedProperties = new string [] { "includeVersions", "strictBinding" };
public UnixBinaryServerFormatterSinkProvider ()
{
_binaryCore = UnixBinaryCore.DefaultInstance;
}
public UnixBinaryServerFormatterSinkProvider (IDictionary properties, ICollection providerData)
{
_binaryCore = new UnixBinaryCore (this, properties, AllowedProperties);
}
public IServerChannelSinkProvider Next
{
get {
return next;
}
set {
next = value;
}
}
public IServerChannelSink CreateSink (IChannelReceiver channel)
{
IServerChannelSink next_sink = null;
UnixBinaryServerFormatterSink result;
if (next != null)
next_sink = next.CreateSink (channel);
result = new UnixBinaryServerFormatterSink (next_sink, channel);
result.BinaryCore = _binaryCore;
return result;
}
public void GetChannelData (IChannelDataStore channelData)
{
// Nothing to add here
}
}
}

View File

@@ -0,0 +1,143 @@
//
// Mono.Remoting.Channels.Unix.UnixChannel.cs
//
// Author: Rodrigo Moya (rodrigo@ximian.com)
// Lluis Sanchez Gual (lluis@ideary.com)
//
// Copyright (C) 2005 Novell, Inc (http://www.novell.com)
//
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System;
using System.Collections;
using System.Runtime.Remoting.Messaging;
using System.Runtime.Remoting.Channels;
using System.Text.RegularExpressions;
namespace Mono.Remoting.Channels.Unix
{
public class UnixChannel : IChannelReceiver, IChannel, IChannelSender
{
private UnixClientChannel _clientChannel;
private UnixServerChannel _serverChannel = null;
private string _name = "unix";
private int _priority = 1;
public UnixChannel (): this (null)
{
}
public UnixChannel (string path)
{
Hashtable ht = new Hashtable();
ht["path"] = path;
Init(ht, null, null);
}
void Init (IDictionary properties, IClientChannelSinkProvider clientSink, IServerChannelSinkProvider serverSink)
{
_clientChannel = new UnixClientChannel (properties,clientSink);
if(properties["path"] != null)
_serverChannel = new UnixServerChannel(properties, serverSink);
object val = properties ["name"];
if (val != null) _name = val as string;
val = properties ["priority"];
if (val != null) _priority = Convert.ToInt32 (val);
}
public UnixChannel (IDictionary properties,
IClientChannelSinkProvider clientSinkProvider,
IServerChannelSinkProvider serverSinkProvider)
{
Init (properties, clientSinkProvider, serverSinkProvider);
}
public IMessageSink CreateMessageSink(string url, object remoteChannelData, out string objectURI)
{
return _clientChannel.CreateMessageSink(url, remoteChannelData, out objectURI);
}
public string ChannelName
{
get { return _name; }
}
public int ChannelPriority
{
get { return _priority; }
}
public void StartListening (object data)
{
if (_serverChannel != null) _serverChannel.StartListening (data);
}
public void StopListening (object data)
{
if (_serverChannel != null) _serverChannel.StopListening(data);
}
public string[] GetUrlsForUri (string uri)
{
if (_serverChannel != null) return _serverChannel.GetUrlsForUri(uri);
else return null;
}
public object ChannelData
{
get
{
if (_serverChannel != null) return _serverChannel.ChannelData;
else return null;
}
}
public string Parse (string url, out string objectURI)
{
return UnixChannel.ParseUnixURL (url, out objectURI);
}
internal static string ParseUnixURL (string url, out string objectURI)
{
// format: "unix:///path/to/unix/socket?/path/to/object"
objectURI = null;
if (!url.StartsWith ("unix://")) return null;
int i = url.IndexOf ('?');
if (i == -1) return url.Substring (7);
objectURI = url.Substring (i+1);
if (objectURI.Length == 0)
objectURI = null;
return url.Substring (7, i - 7);
}
}
}

View File

@@ -0,0 +1,134 @@
//
// Mono.Remoting.Channels.Unix.UnixClientChannel.cs
//
// Author: Dietmar Maurer (dietmar@ximian.com)
// Lluis Sanchez Gual (lluis@novell.com)
//
// Copyright (C) 2005 Novell, Inc (http://www.novell.com)
//
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System;
using System.Collections;
using System.IO;
using System.Net.Sockets;
using System.Runtime.Remoting.Messaging;
using System.Runtime.Remoting.Channels;
using System.Threading;
namespace Mono.Remoting.Channels.Unix
{
public class UnixClientChannel : IChannelSender, IChannel
{
int priority = 1;
string name = "unix";
IClientChannelSinkProvider _sinkProvider;
public UnixClientChannel ()
{
_sinkProvider = new UnixBinaryClientFormatterSinkProvider ();
_sinkProvider.Next = new UnixClientTransportSinkProvider ();
}
public UnixClientChannel (IDictionary properties, IClientChannelSinkProvider sinkProvider)
{
object val = properties ["name"];
if (val != null) name = val as string;
val = properties ["priority"];
if (val != null) priority = Convert.ToInt32 (val);
if (sinkProvider != null)
{
_sinkProvider = sinkProvider;
// add the unix provider at the end of the chain
IClientChannelSinkProvider prov = sinkProvider;
while (prov.Next != null) prov = prov.Next;
prov.Next = new UnixClientTransportSinkProvider ();
// Note: a default formatter is added only when
// no sink providers are specified in the config file.
}
else
{
_sinkProvider = new UnixBinaryClientFormatterSinkProvider ();
_sinkProvider.Next = new UnixClientTransportSinkProvider ();
}
}
public UnixClientChannel (string name, IClientChannelSinkProvider sinkProvider)
{
this.name = name;
_sinkProvider = sinkProvider;
// add the unix provider at the end of the chain
IClientChannelSinkProvider prov = sinkProvider;
while (prov.Next != null) prov = prov.Next;
prov.Next = new UnixClientTransportSinkProvider ();
}
public string ChannelName
{
get {
return name;
}
}
public int ChannelPriority
{
get {
return priority;
}
}
public IMessageSink CreateMessageSink (string url,
object remoteChannelData,
out string objectURI)
{
if (url != null && Parse (url, out objectURI) != null)
return (IMessageSink) _sinkProvider.CreateSink (this, url, remoteChannelData);
if (remoteChannelData != null) {
IChannelDataStore ds = remoteChannelData as IChannelDataStore;
if (ds != null && ds.ChannelUris.Length > 0)
url = ds.ChannelUris [0];
else {
objectURI = null;
return null;
}
}
if (Parse (url, out objectURI) == null)
return null;
return (IMessageSink) _sinkProvider.CreateSink (this, url, remoteChannelData);
}
public string Parse (string url, out string objectURI)
{
return UnixChannel.ParseUnixURL (url, out objectURI);
}
}
}

View File

@@ -0,0 +1,193 @@
//
// Mono.Remoting.Channels.Unix.UnixClientTransportSink.cs
//
// Author: Dietmar Maurer (dietmar@ximian.com)
// Lluis Sanchez Gual (lluis@novell.com)
//
// Copyright (C) 2005 Novell, Inc (http://www.novell.com)
//
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Messaging;
using System.Collections;
using System.IO;
using System.Threading;
using System.Runtime.Remoting;
namespace Mono.Remoting.Channels.Unix
{
internal class UnixClientTransportSink : IClientChannelSink
{
string _path;
public UnixClientTransportSink (string url)
{
string objectUri;
_path = UnixChannel.ParseUnixURL (url, out objectUri);
}
public IDictionary Properties
{
get
{
return null;
}
}
public IClientChannelSink NextChannelSink
{
get
{
// we are the last one
return null;
}
}
public void AsyncProcessRequest (IClientChannelSinkStack sinkStack, IMessage msg,
ITransportHeaders headers, Stream requestStream)
{
UnixConnection connection = null;
bool isOneWay = RemotingServices.IsOneWay (((IMethodMessage)msg).MethodBase);
try
{
if (headers == null) headers = new TransportHeaders();
headers ["__RequestUri"] = ((IMethodMessage)msg).Uri;
// Sends the stream using a connection from the pool
// and creates a WorkItem that will wait for the
// response of the server
connection = UnixConnectionPool.GetConnection (_path);
UnixMessageIO.SendMessageStream (connection.Stream, requestStream, headers, connection.Buffer);
connection.Stream.Flush ();
if (!isOneWay)
{
sinkStack.Push (this, connection);
ThreadPool.QueueUserWorkItem (new WaitCallback(data => {
try {
ReadAsyncUnixMessage (data);
} catch {}
}), sinkStack);
}
else
connection.Release();
}
catch
{
if (connection != null) connection.Release();
if (!isOneWay) throw;
}
}
private void ReadAsyncUnixMessage(object data)
{
// This method is called by a new thread to asynchronously
// read the response to a request
// The stack was provided as state data in QueueUserWorkItem
IClientChannelSinkStack stack = (IClientChannelSinkStack)data;
// The first sink in the stack is this sink. Pop it and
// get the status data, which is the UnixConnection used to send
// the request
UnixConnection connection = (UnixConnection)stack.Pop(this);
try
{
ITransportHeaders responseHeaders;
// Read the response, blocking if necessary
MessageStatus status = UnixMessageIO.ReceiveMessageStatus (connection.Stream, connection.Buffer);
if (status != MessageStatus.MethodMessage)
throw new RemotingException ("Unknown response message from server");
Stream responseStream = UnixMessageIO.ReceiveMessageStream (connection.Stream, out responseHeaders, connection.Buffer);
// Free the connection, so it can be reused
connection.Release();
connection = null;
// Ok, proceed with the other sinks
stack.AsyncProcessResponse (responseHeaders, responseStream);
}
catch
{
if (connection != null) connection.Release();
throw;
}
}
public void AsyncProcessResponse (IClientResponseChannelSinkStack sinkStack,
object state, ITransportHeaders headers,
Stream stream)
{
// Should never be called
throw new NotSupportedException();
}
public Stream GetRequestStream (IMessage msg, ITransportHeaders headers)
{
return null;
}
public void ProcessMessage (IMessage msg,
ITransportHeaders requestHeaders,
Stream requestStream,
out ITransportHeaders responseHeaders,
out Stream responseStream)
{
UnixConnection connection = null;
try
{
if (requestHeaders == null) requestHeaders = new TransportHeaders();
requestHeaders ["__RequestUri"] = ((IMethodMessage)msg).Uri;
// Sends the message
connection = UnixConnectionPool.GetConnection (_path);
UnixMessageIO.SendMessageStream (connection.Stream, requestStream, requestHeaders, connection.Buffer);
connection.Stream.Flush ();
// Reads the response
MessageStatus status = UnixMessageIO.ReceiveMessageStatus (connection.Stream, connection.Buffer);
if (status != MessageStatus.MethodMessage)
throw new RemotingException ("Unknown response message from server");
responseStream = UnixMessageIO.ReceiveMessageStream (connection.Stream, out responseHeaders, connection.Buffer);
}
finally
{
if (connection != null)
connection.Release();
}
}
}
}

View File

@@ -0,0 +1,62 @@
//
// Mono.Remoting.Channels.Unix.UnixClientTransportSinkProvider.cs
//
// Author: Dietmar Maurer (dietmar@ximian.com)
// Lluis Sanchez (lluis@novell.com)
//
// Copyright (C) 2005 Novell, Inc (http://www.novell.com)
//
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System;
using System.Runtime.Remoting.Channels;
namespace Mono.Remoting.Channels.Unix
{
internal class UnixClientTransportSinkProvider : IClientChannelSinkProvider
{
public UnixClientTransportSinkProvider ()
{
// what should we do here ?
}
public IClientChannelSinkProvider Next
{
get
{
return null;
}
set
{
// ignore, we are always the last in the chain
}
}
public IClientChannelSink CreateSink (IChannelSender channel, string url,
object remoteChannelData)
{
return new UnixClientTransportSink (url);
}
}
}

View File

@@ -0,0 +1,311 @@
//
// Mono.Remoting.Channels.Unix.UnixConnectionPool.cs
//
// Author: Lluis Sanchez Gual (lluis@ideary.com)
//
// Copyright (C) 2005 Novell, Inc (http://www.novell.com)
//
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System;
using System.Collections;
using System.Threading;
using System.IO;
using System.Net.Sockets;
using System.Runtime.Remoting;
using Mono.Unix;
namespace Mono.Remoting.Channels.Unix
{
// This is a pool of Unix connections. Connections requested
// by the TCP channel are pooled after their use, and can
// be reused later. Connections are automaticaly closed
// if not used after some time, specified in KeepAliveSeconds.
// The number of allowed open connections can also be specified
// in MaxOpenConnections. The limit is per host.
// If a thread requests a connection and the limit has been
// reached, the thread is suspended until one is released.
internal class UnixConnectionPool
{
// Table of pools. There is a HostConnectionPool
// instance for each host
static Hashtable _pools = new Hashtable();
static int _maxOpenConnections = int.MaxValue;
static int _keepAliveSeconds = 15;
static Thread _poolThread;
static UnixConnectionPool()
{
// This thread will close unused connections
_poolThread = new Thread (new ThreadStart (ConnectionCollector));
_poolThread.Start();
_poolThread.IsBackground = true;
}
public static void Shutdown ()
{
if (_poolThread != null)
_poolThread.Abort();
}
public static int MaxOpenConnections
{
get { return _maxOpenConnections; }
set
{
if (value < 1) throw new RemotingException ("MaxOpenConnections must be greater than zero");
_maxOpenConnections = value;
}
}
public static int KeepAliveSeconds
{
get { return _keepAliveSeconds; }
set { _keepAliveSeconds = value; }
}
public static UnixConnection GetConnection (string path)
{
HostConnectionPool hostPool;
lock (_pools)
{
hostPool = (HostConnectionPool) _pools[path];
if (hostPool == null)
{
hostPool = new HostConnectionPool(path);
_pools[path] = hostPool;
}
}
return hostPool.GetConnection();
}
private static void ConnectionCollector ()
{
while (true)
{
Thread.Sleep(3000);
lock (_pools)
{
ICollection values = _pools.Values;
foreach (HostConnectionPool pool in values)
pool.PurgeConnections();
}
}
}
}
internal class ReusableUnixClient : UnixClient
{
public ReusableUnixClient (string path): base (path)
{
}
public bool IsAlive
{
get
{
// This Poll will return true if there is data pending to
// be read. It prob. means that a client object using this
// connection got an exception and did not finish to read
// the data. It can also mean that the connection has been
// closed in the server. In both cases, the connection cannot
// be reused.
return !Client.Poll (0, SelectMode.SelectRead);
}
}
}
internal class UnixConnection
{
DateTime _controlTime;
Stream _stream;
ReusableUnixClient _client;
HostConnectionPool _pool;
byte[] _buffer;
public UnixConnection (HostConnectionPool pool, ReusableUnixClient client)
{
_pool = pool;
_client = client;
_stream = new BufferedStream (client.GetStream());
_controlTime = DateTime.Now;
_buffer = new byte[UnixMessageIO.DefaultStreamBufferSize];
}
public Stream Stream
{
get { return _stream; }
}
public DateTime ControlTime
{
get { return _controlTime; }
set { _controlTime = value; }
}
public bool IsAlive
{
get { return _client.IsAlive; }
}
// This is a "thread safe" buffer that can be used by
// UnixClientTransportSink to read or send data to the stream.
// The buffer is "thread safe" since only one thread can
// use a connection at a given time.
public byte[] Buffer
{
get { return _buffer; }
}
// Returns the connection to the pool
public void Release()
{
_pool.ReleaseConnection (this);
}
public void Close()
{
_client.Close();
}
}
internal class HostConnectionPool
{
ArrayList _pool = new ArrayList();
int _activeConnections = 0;
string _path;
public HostConnectionPool (string path)
{
_path = path;
}
public UnixConnection GetConnection ()
{
UnixConnection connection = null;
lock (_pool)
{
do
{
if (_pool.Count > 0)
{
// There are available connections
connection = (UnixConnection)_pool[_pool.Count - 1];
_pool.RemoveAt(_pool.Count - 1);
if (!connection.IsAlive) {
CancelConnection (connection);
connection = null;
continue;
}
}
if (connection == null && _activeConnections < UnixConnectionPool.MaxOpenConnections)
{
// No connections available, but the max connections
// has not been reached yet, so a new one can be created
// Create the connection outside the lock
break;
}
// No available connections in the pool
// Wait for somewone to release one.
if (connection == null)
{
Monitor.Wait(_pool);
}
}
while (connection == null);
}
if (connection == null)
return CreateConnection ();
else
return connection;
}
private UnixConnection CreateConnection()
{
try
{
ReusableUnixClient client = new ReusableUnixClient (_path);
UnixConnection entry = new UnixConnection(this, client);
_activeConnections++;
return entry;
}
catch (Exception ex)
{
throw new RemotingException (ex.Message);
}
}
public void ReleaseConnection (UnixConnection entry)
{
lock (_pool)
{
entry.ControlTime = DateTime.Now; // Initialize timeout
_pool.Add (entry);
Monitor.Pulse (_pool);
}
}
private void CancelConnection(UnixConnection entry)
{
try
{
entry.Stream.Close();
_activeConnections--;
}
catch
{
}
}
public void PurgeConnections()
{
lock (_pool)
{
for (int n=0; n < _pool.Count; n++)
{
UnixConnection entry = (UnixConnection)_pool[n];
if ( (DateTime.Now - entry.ControlTime).TotalSeconds > UnixConnectionPool.KeepAliveSeconds)
{
CancelConnection (entry);
_pool.RemoveAt(n);
n--;
}
}
}
}
}
}

View File

@@ -0,0 +1,283 @@
//
// Mono.Remoting.Channels.Unix.UnixMessageIO.cs
//
// Author: Lluis Sanchez Gual (lluis@ideary.com)
//
// Copyright (C) 2005 Novell, Inc (http://www.novell.com)
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using System.Collections;
using System.IO;
using System.Text;
using System.Net.Sockets;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting;
namespace Mono.Remoting.Channels.Unix
{
enum MessageStatus { MethodMessage = 0, CancelSignal = 1, Unknown = 10}
internal class UnixMessageIO
{
static byte[][] _msgHeaders =
{
new byte[] { (byte)'.', (byte)'N', (byte)'E', (byte)'T', 1, 0 },
new byte[] { 255, 255, 255, 255, 255, 255 }
};
public static int DefaultStreamBufferSize = 1000;
// Identifies an incoming message
public static MessageStatus ReceiveMessageStatus (Stream networkStream, byte[] buffer)
{
try {
StreamRead (networkStream, buffer, 6);
} catch (Exception ex) {
throw new RemotingException ("Unix transport error.", ex);
}
try
{
bool[] isOnTrack = new bool[_msgHeaders.Length];
bool atLeastOneOnTrack = true;
int i = 0;
while (atLeastOneOnTrack)
{
atLeastOneOnTrack = false;
byte c = buffer [i];
for (int n = 0; n<_msgHeaders.Length; n++)
{
if (i > 0 && !isOnTrack[n]) continue;
isOnTrack[n] = (c == _msgHeaders[n][i]);
if (isOnTrack[n] && (i == _msgHeaders[n].Length-1)) return (MessageStatus) n;
atLeastOneOnTrack = atLeastOneOnTrack || isOnTrack[n];
}
i++;
}
return MessageStatus.Unknown;
}
catch (Exception ex) {
throw new RemotingException ("Unix transport error.", ex);
}
}
static bool StreamRead (Stream networkStream, byte[] buffer, int count)
{
int nr = 0;
do {
int pr = networkStream.Read (buffer, nr, count - nr);
if (pr == 0)
throw new RemotingException ("Connection closed");
nr += pr;
} while (nr < count);
return true;
}
public static void SendMessageStream (Stream networkStream, Stream data, ITransportHeaders requestHeaders, byte[] buffer)
{
if (buffer == null) buffer = new byte[DefaultStreamBufferSize];
// Writes the message start header
byte[] dotnetHeader = _msgHeaders[(int) MessageStatus.MethodMessage];
networkStream.Write(dotnetHeader, 0, dotnetHeader.Length);
// Writes header tag (0x0000 if request stream, 0x0002 if response stream)
if(requestHeaders["__RequestUri"]!=null) buffer [0] = (byte) 0;
else buffer[0] = (byte) 2;
buffer [1] = (byte) 0 ;
// Writes ID
buffer [2] = (byte) 0;
// Writes assemblyID????
buffer [3] = (byte) 0;
// Writes the length of the stream being sent (not including the headers)
int num = (int)data.Length;
buffer [4] = (byte) num;
buffer [5] = (byte) (num >> 8);
buffer [6] = (byte) (num >> 16);
buffer [7] = (byte) (num >> 24);
networkStream.Write(buffer, 0, 8);
// Writes the message headers
SendHeaders (networkStream, requestHeaders, buffer);
// Writes the stream
if (data is MemoryStream)
{
// The copy of the stream can be optimized. The internal
// buffer of MemoryStream can be used.
MemoryStream memStream = (MemoryStream)data;
networkStream.Write (memStream.GetBuffer(), 0, (int)memStream.Length);
}
else
{
int nread = data.Read (buffer, 0, buffer.Length);
while (nread > 0)
{
networkStream.Write (buffer, 0, nread);
nread = data.Read (buffer, 0, buffer.Length);
}
}
}
static byte[] msgUriTransportKey = new byte[] { 4, 0, 1, 1 };
static byte[] msgContentTypeTransportKey = new byte[] { 6, 0, 1, 1 };
static byte[] msgDefaultTransportKey = new byte[] { 1, 0, 1 };
static byte[] msgHeaderTerminator = new byte[] { 0, 0 };
private static void SendHeaders(Stream networkStream, ITransportHeaders requestHeaders, byte[] buffer)
{
// Writes the headers as a sequence of strings
if (networkStream != null)
{
IEnumerator e = requestHeaders.GetEnumerator();
while (e.MoveNext())
{
DictionaryEntry hdr = (DictionaryEntry)e.Current;
switch (hdr.Key.ToString())
{
case "__RequestUri":
networkStream.Write (msgUriTransportKey, 0, 4);
break;
case "Content-Type":
networkStream.Write (msgContentTypeTransportKey, 0, 4);
break;
default:
networkStream.Write (msgDefaultTransportKey, 0, 3);
SendString (networkStream, hdr.Key.ToString(), buffer);
networkStream.WriteByte (1);
break;
}
SendString (networkStream, hdr.Value.ToString(), buffer);
}
}
networkStream.Write (msgHeaderTerminator, 0, 2); // End of headers
}
public static ITransportHeaders ReceiveHeaders (Stream networkStream, byte[] buffer)
{
StreamRead (networkStream, buffer, 2);
byte headerType = buffer [0];
TransportHeaders headers = new TransportHeaders ();
while (headerType != 0)
{
string key;
StreamRead (networkStream, buffer, 1); // byte 1
switch (headerType)
{
case 4: key = "__RequestUri"; break;
case 6: key = "Content-Type"; break;
case 1: key = ReceiveString (networkStream, buffer); break;
default: throw new NotSupportedException ("Unknown header code: " + headerType);
}
StreamRead (networkStream, buffer, 1); // byte 1
headers[key] = ReceiveString (networkStream, buffer);
StreamRead (networkStream, buffer, 2);
headerType = buffer [0];
}
return headers;
}
public static Stream ReceiveMessageStream (Stream networkStream, out ITransportHeaders headers, byte[] buffer)
{
headers = null;
if (buffer == null) buffer = new byte[DefaultStreamBufferSize];
// Reads header tag: 0 -> Stream with headers or 2 -> Response Stream
// +
// Gets the length of the data stream
StreamRead (networkStream, buffer, 8);
int byteCount = (buffer [4] | (buffer [5] << 8) |
(buffer [6] << 16) | (buffer [7] << 24));
// Reads the headers
headers = ReceiveHeaders (networkStream, buffer);
byte[] resultBuffer = new byte[byteCount];
StreamRead (networkStream, resultBuffer, byteCount);
return new MemoryStream (resultBuffer);
}
private static void SendString (Stream networkStream, string str, byte[] buffer)
{
// Allocates a buffer. Use the internal buffer if it is
// big enough. If not, create a new one.
int maxBytes = Encoding.UTF8.GetMaxByteCount(str.Length)+4; //+4 bytes for storing the string length
if (maxBytes > buffer.Length)
buffer = new byte[maxBytes];
int num = Encoding.UTF8.GetBytes (str, 0, str.Length, buffer, 4);
// store number of bytes (not number of chars!)
buffer [0] = (byte) num;
buffer [1] = (byte) (num >> 8);
buffer [2] = (byte) (num >> 16);
buffer [3] = (byte) (num >> 24);
// Write the string bytes
networkStream.Write (buffer, 0, num + 4);
}
private static string ReceiveString (Stream networkStream, byte[] buffer)
{
StreamRead (networkStream, buffer, 4);
// Reads the number of bytes (not chars!)
int byteCount = (buffer [0] | (buffer [1] << 8) |
(buffer [2] << 16) | (buffer [3] << 24));
if (byteCount == 0) return string.Empty;
// Allocates a buffer of the correct size. Use the
// internal buffer if it is big enough
if (byteCount > buffer.Length)
buffer = new byte[byteCount];
// Reads the string
StreamRead (networkStream, buffer, byteCount);
char[] chars = Encoding.UTF8.GetChars (buffer, 0, byteCount);
return new string (chars);
}
}
}

View File

@@ -0,0 +1,330 @@
//
// Mono.Remoting.Channels.Unix.UnixServerChannel.cs
//
// Author: Rodrigo Moya (rodrigo@ximian.com)
// Lluis Sanchez Gual (lluis@ideary.com)
//
// Copyright (C) 2005 Novell, Inc (http://www.novell.com)
//
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System;
using System.Collections;
using System.Runtime.Remoting.Messaging;
using System.Text.RegularExpressions;
using System.Net.Sockets;
using System.Net;
using System.Threading;
using System.IO;
using System.Runtime.Remoting.Channels;
using Mono.Unix;
namespace Mono.Remoting.Channels.Unix
{
public class UnixServerChannel : IChannelReceiver, IChannel
{
string path = null;
string name = "unix";
int priority = 1;
bool supressChannelData = false;
Thread server_thread = null;
UnixListener listener;
UnixServerTransportSink sink;
ChannelDataStore channel_data;
int _maxConcurrentConnections = 100;
ArrayList _activeConnections = new ArrayList();
void Init (IServerChannelSinkProvider serverSinkProvider)
{
if (serverSinkProvider == null)
{
serverSinkProvider = new UnixBinaryServerFormatterSinkProvider ();
}
// Gets channel data from the chain of channel providers
channel_data = new ChannelDataStore (null);
IServerChannelSinkProvider provider = serverSinkProvider;
while (provider != null)
{
provider.GetChannelData(channel_data);
provider = provider.Next;
}
// Creates the sink chain that will process all incoming messages
IServerChannelSink next_sink = ChannelServices.CreateServerChannelSinkChain (serverSinkProvider, this);
sink = new UnixServerTransportSink (next_sink);
StartListening (null);
}
public UnixServerChannel (string path)
{
this.path = path;
Init (null);
}
public UnixServerChannel (IDictionary properties,
IServerChannelSinkProvider serverSinkProvider)
{
foreach(DictionaryEntry property in properties)
{
switch((string)property.Key)
{
case "path":
path = property.Value as string;
break;
case "priority":
priority = Convert.ToInt32(property.Value);
break;
case "supressChannelData":
supressChannelData = Convert.ToBoolean (property.Value);
break;
}
}
Init (serverSinkProvider);
}
public UnixServerChannel (string name, string path,
IServerChannelSinkProvider serverSinkProvider)
{
this.name = name;
this.path = path;
Init (serverSinkProvider);
}
public UnixServerChannel (string name, string path)
{
this.name = name;
this.path = path;
Init (null);
}
public object ChannelData
{
get {
if (supressChannelData) return null;
else return channel_data;
}
}
public string ChannelName
{
get {
return name;
}
}
public int ChannelPriority
{
get {
return priority;
}
}
public string GetChannelUri ()
{
return "unix://" + path;
}
public string[] GetUrlsForUri (string uri)
{
if (!uri.StartsWith ("/")) uri = "/" + uri;
string [] chnl_uris = channel_data.ChannelUris;
string [] result = new String [chnl_uris.Length];
for (int i = 0; i < chnl_uris.Length; i++)
result [i] = chnl_uris [i] + "?" + uri;
return result;
}
public string Parse (string url, out string objectURI)
{
return UnixChannel.ParseUnixURL (url, out objectURI);
}
void WaitForConnections ()
{
try
{
while (true)
{
Socket client = listener.AcceptSocket ();
CreateListenerConnection (client);
}
}
catch
{}
}
internal void CreateListenerConnection (Socket client)
{
lock (_activeConnections)
{
if (_activeConnections.Count >= _maxConcurrentConnections)
Monitor.Wait (_activeConnections);
if (server_thread == null) return; // Server was stopped while waiting
ClientConnection reader = new ClientConnection (this, client, sink);
Thread thread = new Thread (new ThreadStart (reader.ProcessMessages));
thread.Start();
thread.IsBackground = true;
_activeConnections.Add (thread);
}
}
internal void ReleaseConnection (Thread thread)
{
lock (_activeConnections)
{
_activeConnections.Remove (thread);
Monitor.Pulse (_activeConnections);
}
}
public void StartListening (object data)
{
listener = new UnixListener (path);
Mono.Unix.Native.Syscall.chmod (path,
Mono.Unix.Native.FilePermissions.S_IRUSR |
Mono.Unix.Native.FilePermissions.S_IWUSR |
Mono.Unix.Native.FilePermissions.S_IRGRP |
Mono.Unix.Native.FilePermissions.S_IWGRP |
Mono.Unix.Native.FilePermissions.S_IROTH |
Mono.Unix.Native.FilePermissions.S_IWOTH);
if (server_thread == null)
{
listener.Start ();
string[] uris = new String [1];
uris = new String [1];
uris [0] = GetChannelUri ();
channel_data.ChannelUris = uris;
server_thread = new Thread (new ThreadStart (WaitForConnections));
server_thread.IsBackground = true;
server_thread.Start ();
}
}
public void StopListening (object data)
{
if (server_thread == null) return;
lock (_activeConnections)
{
server_thread.Abort ();
server_thread = null;
listener.Stop ();
foreach (Thread thread in _activeConnections)
thread.Abort();
_activeConnections.Clear();
Monitor.PulseAll (_activeConnections);
}
}
}
class ClientConnection
{
Socket _client;
UnixServerTransportSink _sink;
Stream _stream;
UnixServerChannel _serverChannel;
byte[] _buffer = new byte[UnixMessageIO.DefaultStreamBufferSize];
public ClientConnection (UnixServerChannel serverChannel, Socket client, UnixServerTransportSink sink)
{
_serverChannel = serverChannel;
_client = client;
_sink = sink;
}
public Socket Client {
get { return _client; }
}
public byte[] Buffer
{
get { return _buffer; }
}
public void ProcessMessages()
{
byte[] buffer = new byte[256];
_stream = new BufferedStream (new NetworkStream (_client));
try
{
bool end = false;
while (!end)
{
MessageStatus type = UnixMessageIO.ReceiveMessageStatus (_stream, buffer);
switch (type)
{
case MessageStatus.MethodMessage:
_sink.InternalProcessMessage (this, _stream);
break;
case MessageStatus.Unknown:
case MessageStatus.CancelSignal:
end = true;
break;
}
}
}
catch (Exception)
{
// Console.WriteLine (ex);
}
finally
{
try {
_serverChannel.ReleaseConnection (Thread.CurrentThread);
_stream.Close();
_client.Close ();
} catch {
}
}
}
public bool IsLocal
{
get
{
return true;
}
}
}
}

View File

@@ -0,0 +1,137 @@
//
// Mono.Remoting.Channels.Unix.UnixServerTransportSink.cs
//
// Author: Rodrigo Moya (rodrigo@ximian.com)
// Lluis Sanchez Gual (lsg@ctv.es)
//
// Copyright (C) 2005 Novell, Inc (http://www.novell.com)
//
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System;
using System.Net.Sockets;
using System.Collections;
using System.Runtime.Remoting.Messaging;
using System.IO;
using System.Runtime.Remoting.Channels;
using Mono.Posix;
namespace Mono.Remoting.Channels.Unix
{
internal class UnixServerTransportSink : IServerChannelSink, IChannelSinkBase
{
IServerChannelSink next_sink;
public UnixServerTransportSink (IServerChannelSink next)
{
next_sink = next;
}
public IServerChannelSink NextChannelSink
{
get
{
return next_sink;
}
}
public IDictionary Properties
{
get
{
if (next_sink != null) return next_sink.Properties;
else return null;
}
}
public void AsyncProcessResponse (IServerResponseChannelSinkStack sinkStack, object state,
IMessage msg, ITransportHeaders headers, Stream responseStream)
{
ClientConnection connection = (ClientConnection)state;
NetworkStream stream = new NetworkStream (connection.Client);
UnixMessageIO.SendMessageStream (stream, responseStream, headers, connection.Buffer);
stream.Flush ();
stream.Close ();
}
public Stream GetResponseStream (IServerResponseChannelSinkStack sinkStack, object state,
IMessage msg, ITransportHeaders headers)
{
return null;
}
public ServerProcessing ProcessMessage (IServerChannelSinkStack sinkStack,
IMessage requestMsg,
ITransportHeaders requestHeaders,
Stream requestStream,
out IMessage responseMsg,
out ITransportHeaders responseHeaders,
out Stream responseStream)
{
// this is the first sink, and UnixServerChannel does not call it.
throw new NotSupportedException ();
}
internal void InternalProcessMessage (ClientConnection connection, Stream stream)
{
// Reads the headers and the request stream
Stream requestStream;
ITransportHeaders requestHeaders;
requestStream = UnixMessageIO.ReceiveMessageStream (stream, out requestHeaders, connection.Buffer);
/* try {
PeerCred cred = connection.Client.PeerCredential;
requestHeaders["__uid"] = cred.UserID;
} catch (Exception e) {
Console.WriteLine ("Couldn't get the peer cred: " + e);
}
*/
// Pushes the connection object together with the sink. This information
// will be used for sending the response in an async call.
ServerChannelSinkStack sinkStack = new ServerChannelSinkStack();
sinkStack.Push(this, connection);
ITransportHeaders responseHeaders;
Stream responseStream;
IMessage responseMsg;
ServerProcessing proc = next_sink.ProcessMessage(sinkStack, null, requestHeaders, requestStream, out responseMsg, out responseHeaders, out responseStream);
switch (proc)
{
case ServerProcessing.Complete:
UnixMessageIO.SendMessageStream (stream, responseStream, responseHeaders, connection.Buffer);
stream.Flush ();
break;
case ServerProcessing.Async:
case ServerProcessing.OneWay:
break;
}
}
}
}