Пример #1
0
        /// <summary>
        /// Implemented by inheritors to perform the request on the provided web client.
        /// </summary>
        /// <param name="connection"></param>
        protected override async Task OnProcessRequest(IWebChannelConnection connection)
        {
            byte[] requestedHubConfigurationRawData = await connection.DownloadData("/Hub/Configuration.xml").ConfigureAwait(false);

            //and now do it without using XMLSerializer since that doesn't work in the agent.
            Configuration = DataConverter.ByteArrayToHubConfigurationXml(requestedHubConfigurationRawData);
        }
        /// <summary>
        /// Implemented by inheritors to perform the request on the provided web client.
        /// </summary>
        /// <param name="connection"></param>
        protected override async Task OnProcessRequest(IWebChannelConnection connection)
        {
            byte[] requestedSessionsRawData = await connection.DownloadData(string.Format("/Hub/Hosts/{0}/RequestedSessions.xml", ClientId)).ConfigureAwait(false);

            //even though it's a session list we can't actually deserialize it directly - because we cant use XmlSerializer
            //since the types will not necessarily be public.
            RequestedSessions = DataConverter.ByteArrayToSessionsListXml(requestedSessionsRawData);
        }
Пример #3
0
        /// <summary>
        /// Implemented by inheritors to perform the request on the provided web client.
        /// </summary>
        /// <param name="connection"></param>
        protected override async Task OnProcessRequest(IWebChannelConnection connection)
        {
            string strRequestUrl = string.Format("/Hub/Hosts/{0}/Sessions/{1}/session.xml", ClientId, SessionHeader.id);

            Debug.Assert(SessionHeader.sessionDetail.status != SessionStatusXml.running);
            Debug.Assert(SessionHeader.sessionDetail.status != SessionStatusXml.unknown);

            //we can't encode using XmlSerializer because it will only work with public types, and we
            //aren't public if we get ILMerged into something.
            byte[] encodedXml = DataConverter.SessionXmlToByteArray(SessionHeader);

            await connection.UploadData(strRequestUrl, HttpMethod.Post, "text/xml", encodedXml).ConfigureAwait(false);
        }
        private void PerformCleanup(IWebChannelConnection connection)
        {
            try
            {
                //we're going to upload zero bytes as a delete to the right URL.
                connection.UploadData(GenerateResourceUri(), HttpMethod.Delete, BinaryContentType, new byte[] { });
            }
            catch (Exception ex)
            {
                GC.KeepAlive(ex);
#if DEBUG
                Log.RecordException(0, ex, null, RepositoryPublishClient.LogCategory, true);
#endif
            }
        }
Пример #5
0
        /// <summary>
        /// Implemented by inheritors to perform the request on the provided web client.
        /// </summary>
        /// <param name="connection"></param>
        protected override async Task OnProcessRequest(IWebChannelConnection connection)
        {
            string strRequestUrl = string.Format("/Hub/Hosts/{0}/Sessions/{1}/session.xml", ClientId, SessionId);

            SessionXml sessionHeaderXml = new SessionXml();

            sessionHeaderXml.id                  = SessionId.ToString();
            sessionHeaderXml.isComplete          = true;
            sessionHeaderXml.isCompleteSpecified = true;

            //we can't encode using XmlSerializer because it will only work with public types, and we
            //aren't public if we get ILMerged into something.
            byte[] encodedXml = DataConverter.SessionXmlToByteArray(sessionHeaderXml);

            await connection.UploadData(strRequestUrl, HttpMethod.Post, "text/xml", encodedXml).ConfigureAwait(false);
        }
        /// <summary>
        /// Implemented by inheritors to perform the request on the provided web client.
        /// </summary>
        /// <param name="connection"></param>
        protected override async Task OnProcessRequest(IWebChannelConnection connection)
        {
            string url;

            if (ClientId.HasValue)
            {
                url = string.Format("/Hub/Hosts/{0}/{1}", ClientId, GenerateResourceUri());
            }
            else
            {
                url = string.Format("/Hub/{0}", GenerateResourceUri());
            }

            byte[] sessionFilesListRawData = await connection.DownloadData(url).ConfigureAwait(false);

            //even though it's a session list we can't actually deserialize it directly - because we cant use XmlSerializer
            //since the types will not necessarily be public.
            Files = DataConverter.ByteArrayToSessionFilesListXml(sessionFilesListRawData);
        }
Пример #7
0
        /// <summary>
        /// Implemented by inheritors to perform the request on the provided web client.
        /// </summary>
        /// <param name="connection"></param>
        protected override async Task OnProcessRequest(IWebChannelConnection connection)
        {
            byte[] requestedRepositoryRawData = await connection.UploadData(GenerateResourceUri(), HttpMethod.Put, XmlContentType, ConvertXmlToByteArray(InputRepository)).ConfigureAwait(false);

            //now we deserialize the response which is the new state of the document.

            //now, this is supposed to be a sessions list...
            using (var inputStream = new MemoryStream(requestedRepositoryRawData))
            {
                XmlSerializerNamespaces xmlNsEmpty = new XmlSerializerNamespaces();
                xmlNsEmpty.Add("", "http://www.gibraltarsoftware.com/Gibraltar/Repository.xsd"); //gets rid of the default namespaces we'd otherwise generate

                var           xmlReader     = XmlReader.Create(inputStream);
                XmlSerializer xmlSerializer = new XmlSerializer(typeof(ClientRepositoryXml), "http://www.gibraltarsoftware.com/Gibraltar/Repository.xsd");

                ClientRepositoryXml repositoryXml = (ClientRepositoryXml)xmlSerializer.Deserialize(xmlReader);
                ResponseRepository = repositoryXml;
            }
        }
        /// <summary>
        /// Implemented by inheritors to perform the request on the provided web client.
        /// </summary>
        /// <param name="connection"></param>
        protected override async Task OnProcessRequest(IWebChannelConnection connection)
        {
            if (m_Initialized == false)
            {
                Initialize();
            }

            if (m_SessionTransportLock == null)
            {
                throw new InvalidOperationException("The session is currently being transported by another process.");
            }

            //if we might have left a file fragment on the server we need to send a delete call to remove any partial file
            if (m_PerformCleanup)
            {
                m_PerformCleanup = false; //even if we fail, don't try again.
                PerformCleanup(connection);
            }

            var resourceUri       = GenerateResourceUri();
            var additionalHeaders = new List <NameValuePair <string> >();

            if (string.IsNullOrEmpty(m_SessionFileHash) == false)
            {
                additionalHeaders.Add(new NameValuePair <string>(HubConnection.SHA1HashHeader, m_SessionFileHash));
            }

            //if it's SMALL we just put the whole thing up as a single action.
            if (m_SessionFileStream.Length < SinglePassCutoffBytes)
            {
                var sessionData = new byte[m_SessionFileStream.Length];
                await m_SessionFileStream.ReadAsync(sessionData, 0, sessionData.Length).ConfigureAwait(false);

                await connection.UploadData(resourceUri, HttpMethod.Put, BinaryContentType, sessionData, additionalHeaders).ConfigureAwait(false);
            }
            else
            {
                //we need to do a segmented post operation.  Note that we may be restarting a request after an error, so don't reset
                //our bytes written.
                m_SessionFileStream.Position = m_BytesWritten;
                var restartCount = 0;
                var sessionData  = new byte[DefaultSegmentSizeBytes];
                while (m_BytesWritten < m_SessionFileStream.Length)
                {
                    //Read the next segment which is either our segment size or the last fragment of the file, exactly sized.
                    if ((m_SessionFileStream.Length - m_SessionFileStream.Position) < sessionData.Length)
                    {
                        //we're at the last block - resize our buffer down.
                        sessionData = new byte[(m_SessionFileStream.Length - m_SessionFileStream.Position)];
                    }

                    await m_SessionFileStream.ReadAsync(sessionData, 0, sessionData.Length).ConfigureAwait(false);

                    var isComplete = (m_SessionFileStream.Position == m_SessionFileStream.Length);
                    var requestUrl =
                        $"{resourceUri}?Start={m_BytesWritten}&Complete={isComplete}&FileSize={m_SessionFileStream.Length}";

                    try
                    {
                        await connection.UploadData(requestUrl, HttpMethod.Post, BinaryContentType, sessionData, additionalHeaders).ConfigureAwait(false);

                        //and now that we've written the bytes and not gotten an exception we can mark these bytes as done!
                        m_BytesWritten = (int)m_SessionFileStream.Position;
                        UpdateProgressTrackingFile();
                    }
                    catch (WebChannelBadRequestException ex)
                    {
                        if (!Log.SilentMode)
                        {
                            Log.Write(LogMessageSeverity.Error, LogWriteMode.Queued, ex, RepositoryPublishClient.LogCategory, "Server exchange error, we will assume client and server are out of sync.",
                                      "The server returned a Bad Request Error (400) which generally means there is either a session-specific transfer problem that may be resolved by restarting the transfer from zero or an internal server problem.\r\nException: {0}", ex);
                        }

                        if (restartCount < 4)
                        {
                            //if we experience this type of Server-level transport error, assume there's some out of sync condition and start again.
                            restartCount++;
                            PerformCleanup(connection);
                            m_SessionFileStream.Position = 0;
                            m_BytesWritten = 0;
                            UpdateProgressTrackingFile();
                        }
                        else
                        {
                            //we didn't find a reason to restart the transfer, we need to let the exception fly.
                            throw;
                        }
                    }
                }
            }

            //and since we're now good & done...  clean up our temp stuff.
            SafeDeleteTemporaryData();

            //finally, if we are supposed to purge a session once we sent we need to give that a shot.
            if (PurgeSessionOnSuccess)
            {
                SafePurgeSession();
            }
        }
        /// <summary>
        /// Implemented by inheritors to perform the request on the provided web client.
        /// </summary>
        /// <param name="connection"></param>
        protected override async Task OnProcessRequest(IWebChannelConnection connection)
        {
            if (m_Initialized == false)
            {
                Initialize();
            }

            if (m_SessionTransportLock == null)
            {
                throw new InvalidOperationException("The session is currently being transported by another process.");
            }

            //if we might have left a file fragment on the server we need to send a delete call to remove any partial file
            if (m_PerformCleanup)
            {
                m_PerformCleanup = false; //even if we fail, don't try again.
                PerformCleanup(connection);
            }

            //find the prepared session file
            using (var sessionStream = Repository.LoadSessionFileStream(SessionId, FileId.Value))
            {
                //calculate our SHA1 Hash...
                var additionalHeaders = new List <NameValuePair <string> >();
                if (sessionStream.CanSeek)
                {
                    try
                    {
                        using (var csp = SHA1.Create())
                        {
                            string hash = BitConverter.ToString(csp.ComputeHash(sessionStream));
                            additionalHeaders.Add(new NameValuePair <string>(HubConnection.SHA1HashHeader, hash));
                        }

                        //now back up the stream to the beginning so we can send the actual data.
                        sessionStream.Position = 0;
                    }
                    catch (Exception ex)
                    {
                        if (!Log.SilentMode)
                        {
                            Log.Write(LogMessageSeverity.Error, LogWriteMode.Queued, ex, RepositoryPublishClient.LogCategory, "Unable to calculate hash for session file due to " + ex.GetType() + " exception.", "The upload will proceed but without the hash to check the accuracy of the upload.\r\nException: {0}\r\n{1}\r\n", ex.GetType(), ex.Message);
                        }
                    }
                }

                //if it's SMALL we just put the whole thing up as a single action.
                if (sessionStream.Length < SinglePassCutoffBytes)
                {
                    byte[] sessionData = new byte[sessionStream.Length];
                    sessionStream.Read(sessionData, 0, sessionData.Length);
                    await connection.UploadData(GenerateResourceUri(), HttpMethod.Put, BinaryContentType, sessionData, additionalHeaders).ConfigureAwait(false);
                }
                else
                {
                    //we need to do a segmented post operation.  Note that we may be restarting a request after an error, so don't reset
                    //our bytes written.
                    sessionStream.Position = m_BytesWritten;
                    int    restartCount = 0;
                    byte[] sessionData  = new byte[DefaultSegmentSizeBytes];
                    while (m_BytesWritten < sessionStream.Length)
                    {
                        //Read the next segment which is either our segment size or the last fragment of the file, exactly sized.
                        if ((sessionStream.Length - sessionStream.Position) < sessionData.Length)
                        {
                            //we're at the last block - resize our buffer down.
                            sessionData = new byte[(sessionStream.Length - sessionStream.Position)];
                        }
                        sessionStream.Read(sessionData, 0, sessionData.Length);

                        bool   isComplete = (sessionStream.Position == sessionStream.Length);
                        string requestUrl = string.Format("{0}?Start={1}&Complete={2}&FileSize={3}",
                                                          GenerateResourceUri(), m_BytesWritten, isComplete, sessionStream.Length);

                        bool restartTransfer = false;
                        try
                        {
                            await connection.UploadData(requestUrl, HttpMethod.Post, BinaryContentType, sessionData, additionalHeaders).ConfigureAwait(false);
                        }
                        catch (WebException ex)
                        {
                            //is this an access denied error?
                            if (ex.Status == WebExceptionStatus.ProtocolError)
                            {
                                //get the inner web response to figure out exactly what the deal is.
                                HttpWebResponse response = (HttpWebResponse)ex.Response;
                                if (response.StatusCode == HttpStatusCode.BadRequest)
                                {
                                    if (!Log.SilentMode)
                                    {
                                        Log.Write(LogMessageSeverity.Error, LogWriteMode.Queued, ex, RepositoryPublishClient.LogCategory, "Server exchange error, we will assume client and server are out of sync.",
                                                  "The server returned a Bad Request Error (400) which generally means there is either a session-specific transfer problem that may be resolved by restarting the transfer from zero or an internal server problem.\r\nException: {0}", ex);
                                    }

                                    if (restartCount < 4)
                                    {
                                        restartTransfer = true;
                                        restartCount++;
                                    }
                                }
                            }

                            if (restartTransfer == false)
                            {
                                //we didn't find a reason to restart the transfer, we need to let the exception fly.
                                throw;
                            }
                        }

                        if (restartTransfer)
                        {
                            //if we experience this type of Server-level transport error, assume there's some out of sync condition and start again.
                            PerformCleanup(connection);
                            sessionStream.Position = 0;
                            m_BytesWritten         = 0;
                        }
                        else
                        {
                            //and now that we've written the bytes and not gotten an exception we can mark these bytes as done!
                            m_BytesWritten = (int)sessionStream.Position;
                            UpdateProgressTrackingFile();
                        }
                    }
                }
            }

            //and since we're now good & done...  clean up our temp stuff.
            SafeDeleteTemporaryData();

            //finally, if we are supposed to purge a session once we sent we need to give that a shot.
            if (PurgeSessionOnSuccess)
            {
                SafePurgeSession();
            }
        }
 /// <summary>
 /// Implemented by inheritors to perform the request on the provided web client.
 /// </summary>
 /// <param name="connection"></param>
 protected abstract Task OnProcessRequest(IWebChannelConnection connection);
 /// <summary>
 /// Perform the request against the specified web client connection.
 /// </summary>
 /// <param name="connection"></param>
 public async Task ProcessRequest(IWebChannelConnection connection)
 {
     await OnProcessRequest(connection).ConfigureAwait(false);
 }