/* * Copyright (c) 2009 Craig Sutherland * * 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; using ThoughtWorks.CruiseControl.Remote; using ThoughtWorks.CruiseControl.Remote.Messages; namespace FastForward.WinCore { /// /// A TCP connection to a FastForward.NET cache. /// public class CacheTcpConnection : ServerConnectionBase, IServerConnection, IDisposable { #region Private fields private const string cacheUri = "fastforwardcache.rem"; private readonly Uri serverAddress; private IMessageProcessor client; private bool isBusy; #endregion #region Constructors /// /// Initialises a new to a remote server. /// /// The address of the remote server. public CacheTcpConnection(string serverAddress) : this(new Uri(serverAddress)) { } /// /// Initialises a new to a remote server. /// /// The address of the remote server. public CacheTcpConnection(Uri serverAddress) { UriBuilder builder = new UriBuilder(serverAddress); if (builder.Port == -1) builder.Port = 23571; this.serverAddress = new Uri(builder.Uri, "/" + cacheUri); } #endregion #region Public properties #region Type /// /// The type of connection. /// public string Type { get { return "FastForward.NET Cache (TCP)"; } } #endregion #region ServerName /// /// The name of the server that this connection is for. /// public string ServerName { get { return serverAddress.Host; } } #endregion #region IsBusy /// /// Is this connection busy performing an operation. /// public bool IsBusy { get { return isBusy; } } #endregion #region Address /// /// The address of the client. /// public virtual string Address { get { return serverAddress.AbsoluteUri; } } #endregion #endregion #region Public methods #region SendMessage() /// /// Sends a message via HTTP. /// /// /// /// public virtual Response SendMessage(string action, ServerRequest request) { // Initialise the connection and send the message try { InitialiseRemoting(); FireRequestSending(action, request); var result = client.ProcessMessage(action, request); FireResponseReceived(action, result); return result; } catch (Exception error) { // Replace the original exception with a communications exception throw new CommunicationsException(error.Message); } } #endregion #region SendMessageAsync() /// /// Sends a message to a remote server asychronously. /// /// The action to perform. /// The request to send to the server. public virtual void SendMessageAsync(string action, ServerRequest request) { SendMessageAsync(action, request, null); } /// /// Sends a message to a remote server asychronously. /// /// The action to perform. /// The request to send to the server. /// Any user state data. /// /// This operation will still be done in a synchronous mode. /// public virtual void SendMessageAsync(string action, ServerRequest request, object userState) { if (isBusy) throw new InvalidOperationException(); try { isBusy = true; InitialiseRemoting(); var result = client.ProcessMessage(action, request); if (SendMessageCompleted != null) { var args = new MessageReceivedEventArgs(result, null, false, userState); SendMessageCompleted(this, args); } } catch (Exception error) { if (SendMessageCompleted != null) { var args = new MessageReceivedEventArgs(null, error, false, userState); SendMessageCompleted(this, args); } } finally { isBusy = false; } } #endregion #region CancelAsync() /// /// Cancels an asynchronous operation. /// public virtual void CancelAsync() { CancelAsync(null); } /// /// Cancels an asynchronous operation. /// /// public void CancelAsync(object userState) { // .NET remoting operations are not asynchronous, therefore can't cancel anything } #endregion #region Dispose() /// /// Disposes the .NET remoting client. /// public virtual void Dispose() { client = null; } #endregion #endregion #region Public events #region SendMessageCompleted /// /// A SendMessageAsync has completed. /// public event EventHandler SendMessageCompleted; #endregion #endregion #region Private methods #region InitialiseRemoting() /// /// Initialises the client connection. /// private void InitialiseRemoting() { if (client == null) { // Initialise the actual client client = RemotingServices.Connect(typeof(IMessageProcessor), serverAddress.AbsoluteUri) as IMessageProcessor; } } #endregion #endregion } }