1 //------------------------------------------------------------ 2 // Copyright (c) Microsoft Corporation. All rights reserved. 3 //------------------------------------------------------------ 4 namespace System.ServiceModel.Channels 5 { 6 using System.Globalization; 7 using System.Net; 8 using System.ServiceModel; 9 using System.Text; 10 11 static class MsmqUri 12 { 13 static IAddressTranslator netMsmqAddressTranslator; 14 static IAddressTranslator activeDirectoryAddressTranslator; 15 static IAddressTranslator deadLetterQueueAddressTranslator; 16 static IAddressTranslator srmpAddressTranslator; 17 static IAddressTranslator srmpsAddressTranslator; 18 static IAddressTranslator formatnameAddressTranslator; 19 20 public static IAddressTranslator NetMsmqAddressTranslator 21 { 22 get 23 { 24 if (null == netMsmqAddressTranslator) 25 netMsmqAddressTranslator = new MsmqUri.NetMsmq(); 26 return netMsmqAddressTranslator; 27 } 28 } 29 30 public static IAddressTranslator ActiveDirectoryAddressTranslator 31 { 32 get 33 { 34 if (null == activeDirectoryAddressTranslator) 35 activeDirectoryAddressTranslator = new MsmqUri.ActiveDirectory(); 36 return activeDirectoryAddressTranslator; 37 } 38 } 39 40 public static IAddressTranslator DeadLetterQueueAddressTranslator 41 { 42 get 43 { 44 if (null == deadLetterQueueAddressTranslator) 45 deadLetterQueueAddressTranslator = new MsmqUri.Dlq(); 46 return deadLetterQueueAddressTranslator; 47 } 48 } 49 50 public static IAddressTranslator SrmpAddressTranslator 51 { 52 get 53 { 54 if (null == srmpAddressTranslator) 55 srmpAddressTranslator = new MsmqUri.Srmp(); 56 return srmpAddressTranslator; 57 } 58 } 59 60 public static IAddressTranslator SrmpsAddressTranslator 61 { 62 get 63 { 64 if (null == srmpsAddressTranslator) 65 srmpsAddressTranslator = new MsmqUri.SrmpSecure(); 66 return srmpsAddressTranslator; 67 } 68 } 69 70 public static IAddressTranslator FormatNameAddressTranslator 71 { 72 get 73 { 74 if (null == formatnameAddressTranslator) 75 formatnameAddressTranslator = new MsmqUri.FormatName(); 76 return formatnameAddressTranslator; 77 } 78 } 79 UriToFormatNameByScheme(Uri uri)80 public static string UriToFormatNameByScheme(Uri uri) 81 { 82 if (uri.Scheme == NetMsmqAddressTranslator.Scheme) 83 { 84 return NetMsmqAddressTranslator.UriToFormatName(uri); 85 } 86 else if (uri.Scheme == FormatNameAddressTranslator.Scheme) 87 { 88 return FormatNameAddressTranslator.UriToFormatName(uri); 89 } 90 else 91 { 92 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("uri"); 93 } 94 } 95 AppendQueueName(StringBuilder builder, string relativePath, string slash)96 static void AppendQueueName(StringBuilder builder, string relativePath, string slash) 97 { 98 const string privatePart = "/private"; 99 100 if (relativePath.StartsWith("/private$", StringComparison.OrdinalIgnoreCase)) 101 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.MsmqWrongPrivateQueueSyntax))); 102 103 if (relativePath.StartsWith(privatePart, StringComparison.OrdinalIgnoreCase)) 104 { 105 if (privatePart.Length == relativePath.Length) 106 { 107 builder.Append("private$"); 108 builder.Append(slash); 109 relativePath = "/"; 110 } 111 else if ('/' == relativePath[privatePart.Length]) 112 { 113 builder.Append("private$"); 114 builder.Append(slash); 115 relativePath = relativePath.Substring(privatePart.Length); 116 } 117 } 118 builder.Append(relativePath.Substring(1)); 119 } 120 121 internal interface IAddressTranslator 122 { 123 string Scheme { get; } UriToFormatName(Uri uri)124 string UriToFormatName(Uri uri); CreateUri(string host, string name, bool isPrivate)125 Uri CreateUri(string host, string name, bool isPrivate); 126 } 127 128 class NetMsmq : IAddressTranslator 129 { 130 public string Scheme 131 { 132 get { return "net.msmq"; } 133 } 134 UriToFormatName(Uri uri)135 public string UriToFormatName(Uri uri) 136 { 137 if (null == uri) 138 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("uri")); 139 if (uri.Scheme != this.Scheme) 140 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(SR.GetString(SR.MsmqInvalidScheme), "uri")); 141 if (String.IsNullOrEmpty(uri.Host)) 142 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument(SR.GetString(SR.MsmqWrongUri)); 143 if (-1 != uri.Port) 144 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument(SR.GetString(SR.MsmqUnexpectedPort)); 145 146 StringBuilder builder = new StringBuilder(); 147 builder.Append("DIRECT="); 148 if (0 == String.Compare(uri.Host, "localhost", StringComparison.OrdinalIgnoreCase)) 149 builder.Append("OS:."); 150 else 151 { 152 IPAddress address = null; 153 if (IPAddress.TryParse(uri.Host, out address)) 154 builder.Append("TCP:"); 155 else 156 builder.Append("OS:"); 157 158 builder.Append(uri.Host); 159 } 160 builder.Append("\\"); 161 MsmqUri.AppendQueueName(builder, Uri.UnescapeDataString(uri.PathAndQuery), "\\"); 162 163 return builder.ToString(); 164 } 165 CreateUri(string host, string name, bool isPrivate)166 public Uri CreateUri(string host, string name, bool isPrivate) 167 { 168 string path = "/" + name; 169 if (isPrivate) 170 { 171 path = "/private" + path; 172 } 173 174 return (new UriBuilder(Scheme, host, -1, path)).Uri; 175 } 176 } 177 178 class PathName : IAddressTranslator 179 { 180 public string Scheme 181 { 182 get { return "net.msmq"; } 183 } 184 UriToFormatName(Uri uri)185 public virtual string UriToFormatName(Uri uri) 186 { 187 if (null == uri) 188 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("uri")); 189 if (uri.Scheme != this.Scheme) 190 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(SR.GetString(SR.MsmqInvalidScheme), "uri")); 191 if (String.IsNullOrEmpty(uri.Host)) 192 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument(SR.GetString(SR.MsmqWrongUri)); 193 if (-1 != uri.Port) 194 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument(SR.GetString(SR.MsmqUnexpectedPort)); 195 196 uri = PostVerify(uri); 197 198 StringBuilder builder = new StringBuilder(); 199 if (0 == String.Compare(uri.Host, "localhost", StringComparison.OrdinalIgnoreCase)) 200 builder.Append("."); 201 else 202 builder.Append(uri.Host); 203 204 builder.Append("\\"); 205 MsmqUri.AppendQueueName(builder, Uri.UnescapeDataString(uri.PathAndQuery), "\\"); 206 207 return builder.ToString(); 208 } 209 CreateUri(string host, string name, bool isPrivate)210 public Uri CreateUri(string host, string name, bool isPrivate) 211 { 212 string path = "/" + name; 213 if (isPrivate) 214 { 215 path = "/private" + path; 216 } 217 218 return (new UriBuilder(Scheme, host, -1, path)).Uri; 219 } 220 PostVerify(Uri uri)221 protected virtual Uri PostVerify(Uri uri) 222 { 223 return uri; 224 } 225 } 226 227 class ActiveDirectory : PathName 228 { UriToFormatName(Uri uri)229 public override string UriToFormatName(Uri uri) 230 { 231 return MsmqFormatName.FromQueuePath(base.UriToFormatName(uri)); 232 } 233 } 234 235 class Dlq : PathName 236 { PostVerify(Uri uri)237 protected override Uri PostVerify(Uri uri) 238 { 239 if (0 == String.Compare(uri.Host, "localhost", StringComparison.OrdinalIgnoreCase)) 240 return uri; 241 try 242 { 243 if (0 == String.Compare(DnsCache.MachineName, DnsCache.Resolve(uri).HostName, StringComparison.OrdinalIgnoreCase)) 244 { 245 return new UriBuilder(Scheme, "localhost", -1, uri.PathAndQuery).Uri; 246 } 247 } 248 catch (EndpointNotFoundException ex) 249 { 250 MsmqDiagnostics.ExpectedException(ex); 251 } 252 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(SR.GetString(SR.MsmqDLQNotLocal), "uri")); 253 } 254 } 255 256 abstract class SrmpBase : IAddressTranslator 257 { 258 const string msmqPart = "/msmq/"; 259 260 public string Scheme 261 { 262 get { return "net.msmq"; } 263 } 264 UriToFormatName(Uri uri)265 public string UriToFormatName(Uri uri) 266 { 267 if (null == uri) 268 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("uri")); 269 if (uri.Scheme != this.Scheme) 270 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(SR.GetString(SR.MsmqInvalidScheme), "uri")); 271 if (String.IsNullOrEmpty(uri.Host)) 272 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument(SR.GetString(SR.MsmqWrongUri)); 273 274 StringBuilder builder = new StringBuilder(); 275 builder.Append("DIRECT="); 276 builder.Append(this.DirectScheme); 277 builder.Append(uri.Host); 278 if (-1 != uri.Port) 279 { 280 builder.Append(":"); 281 builder.Append(uri.Port.ToString(CultureInfo.InvariantCulture)); 282 } 283 284 string relativePath = Uri.UnescapeDataString(uri.PathAndQuery); 285 builder.Append(msmqPart); 286 MsmqUri.AppendQueueName(builder, relativePath, "/"); 287 288 return builder.ToString(); 289 } 290 291 abstract protected string DirectScheme { get; } 292 CreateUri(string host, string name, bool isPrivate)293 public Uri CreateUri(string host, string name, bool isPrivate) 294 { 295 string path = "/" + name; 296 if (isPrivate) 297 { 298 path = "/private" + path; 299 } 300 301 return (new UriBuilder(Scheme, host, -1, path)).Uri; 302 } 303 } 304 305 class Srmp : SrmpBase 306 { 307 protected override string DirectScheme 308 { 309 get { return "http://"; } 310 } 311 } 312 313 class SrmpSecure : SrmpBase 314 { 315 protected override string DirectScheme 316 { 317 get { return "https://"; } 318 } 319 } 320 321 class FormatName : IAddressTranslator 322 { 323 public string Scheme 324 { 325 get { return "msmq.formatname"; } 326 } 327 UriToFormatName(Uri uri)328 public string UriToFormatName(Uri uri) 329 { 330 if (null == uri) 331 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("uri")); 332 if (uri.Scheme != this.Scheme) 333 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(SR.GetString(SR.MsmqInvalidScheme), "uri")); 334 return Uri.UnescapeDataString(uri.AbsoluteUri.Substring(this.Scheme.Length + 1)); 335 } 336 CreateUri(string host, string name, bool isPrivate)337 public Uri CreateUri(string host, string name, bool isPrivate) 338 { 339 string path; 340 if (isPrivate) 341 { 342 path = "PRIVATE$\\" + name; 343 } 344 else 345 { 346 path = name; 347 } 348 349 path = "DIRECT=OS:" + host + "\\" + path; 350 351 return new Uri(Scheme + ":" + path); 352 } 353 } 354 } 355 } 356