コード例 #1
0
ファイル: Messages.cs プロジェクト: tenor/p2pStateServer
        /// <summary>
        /// Sends a SetTransferRequest message to a specified ServiceSocket
        /// </summary>
        /// <param name="connectedMsg">AsyncMessageTracker holding connected socket</param>
        /// <param name="Service">The state server instance</param>
        /// <param name="Resource">The URI associated with the message</param>
        /// <param name="SessionInfo">The Session information used to populate fields in the message</param>
        /// <param name="Data">The message data</param>
        /// <param name="SuccessAction">The Action to call if the message was accepted</param>
        /// <param name="FailAction">The Action to call if the message transmission failed or was refused</param>
        /// <param name="AlreadyExistsAction">The Action to call if the recipient peer already has the URI</param>
        /// <param name="PeerShuttingDownAction">The Action to call if the recipient peer is shutting down</param>
        /// <param name="TimeoutAction">The Action to call if the transfer timed out. This Action's processing time should be very short because a long list of Timeout actions can be daisy-chained and called one after the other</param>
        /// <param name="Timeout">The timeout time span</param>
        public static void Send(AsyncMessageTracker connectedMsg, StateServer Service, string Resource, ISessionResponseInfo SessionInfo,
            byte[] Data, Action<AsyncMessageTracker> SuccessAction, Action<AsyncMessageTracker> FailAction, Action<AsyncMessageTracker> AlreadyExistsAction, Action<AsyncMessageTracker> PeerShuttingDownAction, System.Threading.WaitCallback TimeoutAction, TimeSpan Timeout)
        {
            StringBuilder headers = new StringBuilder();

            headers.AppendFormat("PUT {0} HTTP/1.1\r\nHost: {1}\r\nX-ID: {2}\r\n", Resource, Service.ServerIP ?? connectedMsg.Socket.LocalIP,  connectedMsg.ID.ToString("N"));

            if (SessionInfo.LockDateInTicks != DateTime.MinValue.Ticks)
            {
                headers.AppendFormat("LockDate: {0}\r\nLockAge: {1}\r\nLockCookie: {2}\r\n", SessionInfo.LockDateInTicks, SessionInfo.LockAgeInSeconds, SessionInfo.LockCookie);
            }

            headers.AppendFormat("X-If-None-Exists: true\r\nExclusive: transfer\r\nTimeout: {0}\r\nExtraFlags: {1}\r\nLast-Modified: {2}\r\n", SessionInfo.Timeout, SessionInfo.ActionFlags, SessionInfo.UpdateDateInTicks);

            ResponseData rdata = new ResponseData(
                MergeResponseData(headers, Data, true, Service.Settings.EncryptPeerData, Service.Authenticator, connectedMsg.Socket.SessionKey),
                typeof(SetTransferRequest)
            );

            //Create new AsyncResultActions object to hold delegates for actions based on the outcome of the call
            AsyncResultActions<AsyncMessageTracker> asyncResults = new AsyncResultActions<AsyncMessageTracker>(connectedMsg);
            asyncResults.Result1Action = SuccessAction;
            asyncResults.Result2Action = FailAction;
            asyncResults.Result3Action = AlreadyExistsAction;
            asyncResults.Result4Action = PeerShuttingDownAction;
            asyncResults.TimeoutAction = TimeoutAction;

            Service.AsyncMessageRequests.Add(DateTime.UtcNow + Timeout, connectedMsg.ID, asyncResults);

            connectedMsg.Socket.Send(rdata);

            Diags.LogSend(connectedMsg.Socket, rdata);
        }
コード例 #2
0
ファイル: Messages.cs プロジェクト: tenor/p2pStateServer
        /// <summary>
        /// Ends a failed Session Transfer
        /// </summary>
        /// <param name="transferredMessage">The AsyncMessageTracker representing the transfer.</param>
        private void TransferFailure(AsyncMessageTracker transferredMessage)
        {
            List<AsyncResultActions<string>> calls = service.RemoveActiveExport(Resource);
            service.SessionTable.EndExport(Resource, false);

            if (transferredMessage.Socket.IsConnected)
            {
                Diags.LogDisconnectingPeer(transferredMessage.Socket.RemoteIP);
                transferredMessage.Socket.Close();

            }

            if (calls != null) CallExportEndedActions(calls);
        }
コード例 #3
0
ファイル: Messages.cs プロジェクト: tenor/p2pStateServer
        /// <summary>
        /// Ends a successful session transfer
        /// </summary>
        /// <param name="transferredMessage">The AsyncMessageTracker representing the transfer.</param>
        private void TransferSuccess(AsyncMessageTracker transferredMessage)
        {
            List<AsyncResultActions<string>> calls = service.RemoveActiveExport(Resource);
            service.SessionTable.EndExport(Resource, true);

            if (calls != null) CallExportEndedActions(calls);
        }
コード例 #4
0
ファイル: Messages.cs プロジェクト: tenor/p2pStateServer
        /// <summary>
        /// Called by the SessionDictionary.BeginExport method to complete processing the request, 
        /// if the requested session was found and read
        /// </summary>
        /// <param name="Session">The read session</param>
        /// <param name="StateObject">The state object passed from the SessionDictionary.BeginExport method</param>
        private void CompleteTransferRequest(ISessionObject Session, object StateObject)
        {
            ISessionResponseInfo response = Session.CreateResponseInfo();

            //Get the endpoint for the host to connect to
            string remoteHost;
            int? remotePort;
            ServerSettings.HostEndPoint.Parse(Host,out remoteHost,out remotePort);
            if(!remotePort.HasValue) remotePort = service.Settings.PeerPort;
            ServerSettings.HostEndPoint endPoint = new ServerSettings.HostEndPoint(remoteHost.Trim(),remotePort.Value);

            const int sentTransferExpiryTime = 2; // 2 seconds is sufficient for a broadcast to traverse half a reasonable network

            #region Callback Delegate declarations

            //SuccessAction
            Action<AsyncMessageTracker> successAction =
                delegate(AsyncMessageTracker asyncMsg)
                {
                    //Add this transfer to list of recently transferred sessions and have it expire in 15 seconds
                    service.SentTransfers.Add(DateTime.UtcNow + new TimeSpan(0, 0, sentTransferExpiryTime), Resource, null);

                    TransferSuccess(asyncMsg);
                    Diags.LogTransferSuccess(Resource);
                };

            //FailedAction
            Action<AsyncMessageTracker> failureAction =
                delegate(AsyncMessageTracker asyncMsg)
                {
                    TransferFailure(asyncMsg);
                    Diags.LogTransferFailed(Resource, string.Empty);

                };

            //AlreadyExistsAction
            Action<AsyncMessageTracker> alreadyExistsAction =
                delegate(AsyncMessageTracker asyncMsg)
                {
                    //Add this transfer to list of recently transferred sessions and have it expire in 15 seconds
                    service.SentTransfers.Add(DateTime.UtcNow + new TimeSpan(0, 0, sentTransferExpiryTime), Resource, null);

                    TransferSuccess(asyncMsg);
                    Diags.LogTransferFailed(Resource, "Resource already exists in remote peer -- deleted local copy");
                };

            //PeerShuttingDownAction
            Action<AsyncMessageTracker> peerShuttingDownAction =
                delegate(AsyncMessageTracker asyncMsg)
                {
                    TransferFailure(asyncMsg);
                    Diags.LogTransferFailed(Resource, "Peer is shutting down");
                };

            //TimeoutAction
            System.Threading.WaitCallback timeoutAction =
                delegate(object asyncMsg)
                {
                    //This anonymous method can be called directly from a background thread so make sure it's exception-safe
                    try
                    {
                        TransferFailure((AsyncMessageTracker)asyncMsg);
                        Diags.LogTransferFailed(Resource, "Timed out");
                    }
                    catch (Exception ex)
                    {
                        Diags.LogApplicationError( "TimeoutAction delegate error in CompleteTransferRequest", ex);
                    }
                };

            //FailedActionForExistingLink
            Action<AsyncMessageTracker> failureActionForExistingLink =
                delegate(AsyncMessageTracker asyncMsg)
                {
                    Diags.LogTransferFailed(Resource, "Existing link, trying again on new link");
                    //Try again by reconnecting
                    service.TransferSession(endPoint, Resource, response, Session.Data,
                        successAction, failureAction, alreadyExistsAction, peerShuttingDownAction, timeoutAction);

                };

            #endregion

            service.NewActiveExport(Resource); //create an entry in the exports list for this export

            //Look for standing link
            ServiceSocket linkSocket;
            if(service.TryGetLinkTo(endPoint, out linkSocket))
            {
                //There is a standing link to this peer so send transfer through it
                AsyncMessageTracker msg = new AsyncMessageTracker(AsyncMessageOperation.SetTransferOperation, Guid.NewGuid(), linkSocket);
                service.TransferSession(msg, Resource, response, Session.Data,
                    successAction, failureActionForExistingLink, alreadyExistsAction, peerShuttingDownAction, timeoutAction);
            }
            else
            {
                //Initiate a brand new connection
                service.TransferSession(endPoint, Resource, response, Session.Data,
                    successAction,failureAction,alreadyExistsAction,peerShuttingDownAction,timeoutAction);

            }
        }