facd522f99ad55cd855f78a55ef6ef6454a82588
[mono.git] / mcs / class / System.Runtime.Remoting / System.Runtime.Remoting.Channels.Http / HttpChannel.cs
1 //
2 // HttpChannel.cs
3 // 
4 // Author:
5 //   Michael Hutchinson <mhutchinson@novell.com>
6 // 
7 // Copyright (C) 2008 Novell, Inc (http://www.novell.com)
8 // 
9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions:
16 // 
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
19 // 
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 //
28
29 using System.Collections;
30 using System.Runtime.Remoting.Messaging;
31
32 namespace System.Runtime.Remoting.Channels.Http
33 {
34
35         public class HttpChannel : BaseChannelWithProperties,
36                 IChannel, IChannelReceiver, IChannelReceiverHook, IChannelSender
37 #if NET_2_0
38                 , ISecurableChannel
39 #endif
40         {
41                 HttpClientChannel client;
42                 HttpServerChannel server;
43                 string name = "http";
44
45                 #region Constructors
46
47                 public HttpChannel ()
48                 {
49                         client = new HttpClientChannel ();
50                         server = new HttpServerChannel ();
51                 }
52
53                 public HttpChannel (int port)
54                 {
55                         client = new HttpClientChannel ();
56                         server = new HttpServerChannel (port);
57                 }
58
59                 public HttpChannel (IDictionary properties,
60                         IClientChannelSinkProvider clientSinkProvider,
61                         IServerChannelSinkProvider serverSinkProvider)
62                 {
63                         if (properties != null && properties.Contains ("name")) {
64                                 this.name = (string)properties["name"];
65                         }
66
67                         client = new HttpClientChannel (properties, clientSinkProvider);
68                         server = new HttpServerChannel (properties, serverSinkProvider);
69                 }
70
71                 #endregion
72
73                 #region BaseChannelWithProperties overrides
74
75                 public override object this[object key]
76                 {
77                         get { return Properties[key]; }
78                         set { Properties[key] = value; }
79                 }
80
81                 public override ICollection Keys
82                 {
83                         get { return Properties.Keys; }
84                 }
85
86                 public override IDictionary Properties
87                 {
88                         get
89                         {
90                                 return new AggregateDictionary (new IDictionary[] {
91                                         client.Properties,
92                                         server.Properties
93                                 });
94                         }
95                 }
96
97                 #endregion
98
99                 #region IChannel
100
101                 public string ChannelName
102                 {
103                         get { return name; }
104                 }
105
106                 public int ChannelPriority
107                 {
108                         get { return server.ChannelPriority; }
109                 }
110
111                 public string Parse (string url, out string objectURI)
112                 {
113                         return ParseInternal (url, out objectURI);
114                 }
115
116                 internal static string ParseInternal (string url, out string objectURI)
117                 {
118                         if (url == null)
119                                 throw new ArgumentNullException ("url");
120                         
121                         // format: "http://host:port/path/to/object"
122                         objectURI = null;
123                         
124                         // url needs to be at least "http:" or "https:"
125                         if (url.Length < 5 ||
126                             (url[0] != 'H' && url[0] != 'h') ||
127                             (url[1] != 'T' && url[1] != 't') ||
128                             (url[2] != 'T' && url[2] != 't') ||
129                             (url[3] != 'P' && url[3] != 'p'))
130                                 return null;
131                         
132                         int protolen;
133                         if (url[4] == 'S' || url[4] == 's') {
134                                 if (url.Length < 6)
135                                         return null;
136                                 
137                                 protolen = 5;
138                         } else {
139                                 protolen = 4;
140                         }
141                         
142                         if (url[protolen] != ':')
143                                 return null;
144                         
145                         // "http:" and "https:" are acceptable inputs
146                         if (url.Length == protolen + 1)
147                                 return url;
148                         
149                         // protocol must be followed by "//"
150                         if (url.Length < protolen + 3 || url[protolen + 1] != '/' || url[protolen + 2] != '/')
151                                 return null;
152                         
153                         // "http://" and "https://" are acceptable inputs
154                         if (url.Length == protolen + 3)
155                                 return url;
156                         
157                         int slash = url.IndexOf ('/', protolen + 3);
158                         if (slash == -1)
159                                 return url;
160                                 
161                         objectURI = url.Substring (slash);
162
163                         return url.Substring (0, slash);
164                 }
165
166                 #endregion
167
168                 #region IChannelReceiver (: IChannel)
169
170                 public object ChannelData
171                 {
172                         get { return server.ChannelData; }
173                 }
174
175                 public string[] GetUrlsForUri (string objectURI)
176                 {
177                         return server.GetUrlsForUri (objectURI);
178                 }
179
180                 public void StartListening (object data)
181                 {
182                         server.StartListening (data);
183                 }
184
185                 public void StopListening (object data)
186                 {
187                         server.StopListening (data);
188                 }
189
190                 #endregion
191
192                 #region IChannelReceiverHook
193
194                 public void AddHookChannelUri (string channelUri)
195                 {
196                         server.AddHookChannelUri (channelUri);
197                 }
198
199                 public string ChannelScheme
200                 {
201                         get { return server.ChannelScheme; }
202                 }
203
204                 public IServerChannelSink ChannelSinkChain
205                 {
206                         get { return server.ChannelSinkChain; }
207                 }
208
209                 public bool WantsToListen
210                 {
211                         get { return server.WantsToListen; }
212                         set { server.WantsToListen = value; }
213                 }
214
215                 #endregion
216
217                 #region IChannelSender (: IChannel)
218
219                 public IMessageSink CreateMessageSink (string url, object remoteChannelData, out string objectURI)
220                 {
221                         return client.CreateMessageSink (url, remoteChannelData, out objectURI);
222                 }
223
224                 #endregion
225
226 #if NET_2_0
227                 #region ISecurableChannel
228
229                 public bool IsSecured
230                 {
231                         get { return client.IsSecured; }
232                         set { client.IsSecured = value; }
233                 }
234
235                 #endregion
236 #endif
237         }
238 }