Exemplo n.º 1
0
        /// <summary>
        /// A method is used to perform the WOPI discovery process for the WOPI server.
        /// </summary>
        /// <param name="hostNameOfDiscoveryListener">A parameter represents the machine name which is hosting the discovery listener feature. It should be the test client name which is running the test suite.</param>
        /// <param name="sutControllerInstance">A parameter represents the IMS_WOPISUTControlAdapter instance which is used to make the WOPI server perform sending discovery request to the discovery listener.</param>
        public static void PerformDiscoveryProcess(string hostNameOfDiscoveryListener, IMS_WOPISUTControlAdapter sutControllerInstance)
        {
            if (HasPerformDiscoveryProcessSucceed)
            {
                return;
            }

            if (null == sutControllerInstance)
            {
                throw new ArgumentNullException("sutControllerInstance");
            }

            if (string.IsNullOrEmpty(hostNameOfDiscoveryListener))
            {
                throw new ArgumentNullException("hostNameOfDiscoveryListener");
            }

            // Call the "TriggerWOPIDiscovery" method of IMS_WOPISUTControlAdapter interface
            bool isDiscoverySuccessful = sutControllerInstance.TriggerWOPIDiscovery(hostNameOfDiscoveryListener);

            if (!isDiscoverySuccessful)
            {
                throw new InvalidOperationException("Could not perform the discovery process successfully.");
            }

            lock (lockObjectOfVisitDiscoveryProcessStatus)
            {
                hasPerformDiscoveryProcessSucceed = true;
            }

            DiscoveryProcessHelper.AppendLogs(typeof(DiscoveryProcessHelper), DateTime.Now, "Perform the trigger WOPI discovery process successfully.");
        }
        /// <summary>
        /// A method is used to restart the HTTP listener. It will dispose the original HTTP listener and then re-generate a HTTP listen instance to listen request.
        /// </summary>
        protected void RestartListener()
        {
            lock (threadLockObjectForAppendLog)
            {
                DiscoveryProcessHelper.AppendLogs(currentHelperType, DateTime.Now, "Try to restart the Httplistener.");
            }

            // If it is not in "stop" status, try to restart the Httplistener.
            if (ListenInstance.IsListening)
            {
                ListenInstance.Stop();
            }

            while (ListenInstance.IsListening)
            {
                // sleep zero, so that other thread can get the CPU timespan in a valid
                Thread.Sleep(0);
            }

            // Release the original HttpListener resource.
            ListenInstance.Abort();
            ((IDisposable)ListenInstance).Dispose();
            ListenInstance = null;

            // Restart a new HttpListener instance.
            ListenInstance = new HttpListener();
            this.SetPrefixForListener(ListenInstance);
        }
        /// <summary>
        /// A method is used to set the prefix for listener.
        /// </summary>
        /// <param name="listenerInstance">A parameter represents the HttpListener instance which will be set the listened prefix.</param>
        protected void SetPrefixForListener(HttpListener listenerInstance)
        {
            if (null == listenerInstance)
            {
                throw new ArgumentNullException("listenerInstance");
            }

            if (listenerInstance.IsListening)
            {
                throw new InvalidOperationException("The listener has been started, could not set listened prefix for it when it is in started status.");
            }

            // The discovery request must send to "http://{0}/hosting/discovery" URL, and the listener's prefix should append the "/" after the url.
            string listenedprefix = string.Format(@"http://{0}/hosting/discovery/", this.HostNameOfDiscoveryService);
            Uri    uri            = new Uri(listenedprefix);

            listenedprefix = uri.GetComponents(UriComponents.SchemeAndServer, UriFormat.SafeUnescaped);
            ListenInstance.Prefixes.Add(listenedprefix + "/");
            ListenInstance.Start();

            lock (threadLockObjectForAppendLog)
            {
                DiscoveryProcessHelper.AppendLogs(currentHelperType, DateTime.Now, string.Format("Start the HttpListener [{0}] succeed.", Thread.CurrentThread.ManagedThreadId));
            }
        }
Exemplo n.º 4
0
        /// <summary>
        /// A method used to read bytes data from the stream of the HTTP response.
        /// </summary>
        /// <param name="bodyBinaries">A parameter represents the stream which contain the body binaries data.</param>
        /// <param name="contentLengthValue">A parameter represents the length of the body binaries.</param>
        /// <returns>A return value represents the raw body content. If the body length is larger than (int.MaxValue) bytes, the body contents will be chunked by 1024 bytes. The max length of this method is (1024 * int.MaxValue) bytes.</returns>
        private static List <byte[]> ReadBytesFromHttpBodyStream(Stream bodyBinaries, long contentLengthValue)
        {
            if (null == bodyBinaries)
            {
                throw new ArgumentNullException("bodyBinaries");
            }

            long maxKBSize = (long)int.MaxValue;
            long totalSize = contentLengthValue;

            if (contentLengthValue > maxKBSize * 1024)
            {
                throw new InvalidOperationException(string.Format("The test suite only support [{0}]KB size content in a HTTP response.", maxKBSize));
            }

            List <byte[]> bytesOfResponseBody = new List <byte[]>();
            bool          isuseChunk          = false;

            using (BinaryReader binReader = new BinaryReader(bodyBinaries))
            {
                if (contentLengthValue < int.MaxValue && contentLengthValue > 0)
                {
                    byte[] bytesBlob = binReader.ReadBytes((int)contentLengthValue);
                    bytesOfResponseBody.Add(bytesBlob);
                }
                else
                {
                    isuseChunk = true;
                    totalSize  = 0;

                    // set chunk size to 1KB per reading.
                    int    chunkSize      = 1024;
                    byte[] bytesBlockTemp = null;

                    do
                    {
                        bytesBlockTemp = binReader.ReadBytes(chunkSize);
                        if (bytesBlockTemp.Length > 0)
                        {
                            bytesOfResponseBody.Add(bytesBlockTemp);
                            totalSize += bytesBlockTemp.Length;
                        }
                    }while (bytesBlockTemp.Length > 0);
                }
            }

            string chunkProcessLogs = string.Format(
                "Read [{0}] KB size data from response body.{1}",
                (totalSize / 1024.0).ToString("f2"),
                isuseChunk ? "Use the chunk reading mode." : string.Empty);

            DiscoveryProcessHelper.AppendLogs(typeof(WOPIResponseHelper), chunkProcessLogs);

            return(bytesOfResponseBody);
        }
        /// <summary>
        /// A method is used to stop listen process. This method will abort the thread which is listening discovery request and release all resource are used by the thread.
        /// </summary>
        public void StopListen()
        {
            lock (threadLockStaticObjectForVisitThread)
            {
                // If the listen thread has not been start, skip the stop operation.
                if (!hasStartListenThread)
                {
                    return;
                }

                this.IsRequiredStop = true;

                lock (threadLockObjectForAppendLog)
                {
                    DiscoveryProcessHelper.AppendLogs(currentHelperType, DateTime.Now, string.Format("Stop the listening thread.The listening thread managed Id[{0}]", listenThreadHandle.ManagedThreadId));
                }

                if (listenThreadHandle != null && listenThreadHandle.ThreadState != ThreadState.Unstarted &&
                    ListenInstance != null)
                {
                    lock (threadLockObjectForAppendLog)
                    {
                        // Close the http listener and release the resource used by listener. This might cause the thread generate exception and then the thread will be expected to end and join to the main thread.
                        ListenInstance.Abort();
                        ((IDisposable)ListenInstance).Dispose();
                        DiscoveryProcessHelper.AppendLogs(currentHelperType, DateTime.Now, string.Format("Release the Httplistener resource. The listening thread managed Id[{0}]", listenThreadHandle.ManagedThreadId));
                    }

                    // Wait the thread join to the main caller thread.
                    TimeSpan listenThreadJoinTimeOut = new TimeSpan(0, 0, 1);
                    bool     isthreadEnd             = listenThreadHandle.Join(listenThreadJoinTimeOut);

                    // If the thread could not end as expected, abort this thread.
                    if (!isthreadEnd)
                    {
                        if ((listenThreadHandle.ThreadState & (ThreadState.Stopped | ThreadState.Unstarted)) == 0)
                        {
                            listenThreadHandle.Abort();
                            lock (threadLockObjectForAppendLog)
                            {
                                DiscoveryProcessHelper.AppendLogs(currentHelperType, DateTime.Now, string.Format("Abort the listening thread. The listening thread managed Id[{0}]", listenThreadHandle.ManagedThreadId));
                            }
                        }
                    }

                    // Set the static status to tell other instance, the listen thread has been abort.
                    hasStartListenThread = false;
                    listenThreadHandle   = null;
                }
            }
        }
Exemplo n.º 6
0
        /// <summary>
        /// A method is used to get raw body contents whose length is in 1 to int.MaxValue bytes scope.
        /// </summary>
        /// <param name="wopiHttpResponse">A parameter represents the HTTP response.</param>
        /// <returns>A return value represents the raw body content.</returns>
        public static byte[] GetContentFromResponse(WOPIHttpResponse wopiHttpResponse)
        {
            List <byte[]> rawBytesOfBody = ReadRawHTTPResponseToBytes(wopiHttpResponse);

            byte[] returnContent = rawBytesOfBody.SelectMany(bytes => bytes).ToArray();

            DiscoveryProcessHelper.AppendLogs(
                typeof(WOPIResponseHelper),
                string.Format(
                    "Read normal size(1 to int.MaxValue bytes) data from response. actual size[{0}] bytes",
                    returnContent.Length));

            return(returnContent);
        }
        /// <summary>
        /// A method is used to start the listen thread to listen the discovery request.
        /// </summary>
        /// <returns>A return value represents the thread instance handle, which is processing the listen logic. This thread instance can be used to control the thread's status and clean up.</returns>
        public Thread StartListen()
        {
            // Verify whether the listen thread has been started from a DiscoveryRequestListener type instance.
            lock (threadLockStaticObjectForVisitThread)
            {
                lock (threadLockObjectForAppendLog)
                {
                    DiscoveryProcessHelper.AppendLogs(currentHelperType, DateTime.Now, @"Try to start listener thread from current thread.");
                }

                if (null == ListenInstance)
                {
                    ListenInstance = new HttpListener();
                }

                if (hasStartListenThread)
                {
                    lock (threadLockObjectForAppendLog)
                    {
                        DiscoveryProcessHelper.AppendLogs(currentHelperType, DateTime.Now, string.Format(@"The listen thread [{0}] exists.", listenThreadHandle.ManagedThreadId));
                    }

                    return(listenThreadHandle);
                }

                if (!ListenInstance.IsListening)
                {
                    this.SetPrefixForListener(ListenInstance);
                }

                while (!ListenInstance.IsListening)
                {
                    // Sleep 1 second to wait until the status is stable, and allow other threads get the control to update the status.
                    Thread.Sleep(1000);
                }

                listenThreadHandle      = new Thread(this.ListenToRequest);
                listenThreadHandle.Name = "Listen Discovery request thread";
                listenThreadHandle.Start();

                lock (threadLockObjectForAppendLog)
                {
                    DiscoveryProcessHelper.AppendLogs(currentHelperType, DateTime.Now, string.Format("Start the listening thread. The listening thread managed Id[{0}]", listenThreadHandle.ManagedThreadId));
                }

                // Set the status to indicate there has started a listen thread.
                hasStartListenThread = true;
                return(listenThreadHandle);
            }
        }
        /// <summary>
        /// A method is used to restart the HTTP listener. It will dispose the original HTTP listener and then re-generate a HTTP listen instance to listen request.
        /// </summary>
        protected void RestartListener()
        {
            lock (threadLockObjectForAppendLog)
            {
                DiscoveryProcessHelper.AppendLogs(currentHelperType, DateTime.Now, "Try to restart the Httplistener.");
            }
            // Release the original HttpListener resource.
            ListenInstance.Stop();
            ListenInstance = null;

            // Restart a new TcpListener instance.
            IPAddress  iPAddress = IPAddress.Any;
            IPEndPoint endPoint  = new IPEndPoint(iPAddress, 80);

            ListenInstance = new TcpListener(endPoint);
        }
        /// <summary>
        /// A method is used to start the listen thread to listen the discovery request.
        /// </summary>
        /// <returns>A return value represents the thread instance handle, which is processing the listen logic. This thread instance can be used to control the thread's status and clean up.</returns>
        public Thread StartListen()
        {
            // Verify whether the listen thread has been started from a DiscoveryRequestListener type instance.
            lock (threadLockStaticObjectForVisitThread)
            {
                lock (threadLockObjectForAppendLog)
                {
                    DiscoveryProcessHelper.AppendLogs(currentHelperType, DateTime.Now, @"Try to start listener thread from current thread.");
                }

                if (null == ListenInstance)
                {
                    IPAddress  iPAddress = IPAddress.Any;
                    IPEndPoint endPoint  = new IPEndPoint(iPAddress, 80);
                    ListenInstance = new TcpListener(endPoint);
                }

                if (hasStartListenThread)
                {
                    lock (threadLockObjectForAppendLog)
                    {
                        DiscoveryProcessHelper.AppendLogs(currentHelperType, DateTime.Now, string.Format(@"The listen thread [{0}] exists.", listenThreadHandle.ManagedThreadId));
                    }

                    return(listenThreadHandle);
                }

                listenThreadHandle      = new Thread(this.ListenToRequest);
                listenThreadHandle.Name = "Listen Discovery request thread";
                listenThreadHandle.Start();

                lock (threadLockObjectForAppendLog)
                {
                    DiscoveryProcessHelper.AppendLogs(currentHelperType, DateTime.Now, string.Format("Start the listening thread. The listening thread managed Id[{0}]", listenThreadHandle.ManagedThreadId));
                }

                // Set the status to indicate there has started a listen thread.
                hasStartListenThread = true;
                return(listenThreadHandle);
            }
        }
        /// <summary>
        /// A method is used to listening the discovery request. It will be executed by a thread which is started on ListenThreadInstance method.
        /// </summary>
        protected void ListenToRequest()
        {
            ListenInstance.Start();

            // If the listener is listening, just keep on execute below code.
            while (hasStartListenThread)
            {
                try
                {
                    TcpClient client = ListenInstance.AcceptTcpClient();
                    if (client.Connected == true)
                    {
                        Console.WriteLine("Created connection");
                    }
                    // if the calling thread requires stopping the listening mission, just return and exit the loop. This value of "IsrequireStop" property is managed by "StopListen" method.
                    if (this.IsRequiredStop)
                    {
                        break;
                    }

                    lock (threadLockStaticObjectForVisitThread)
                    {
                        // Double check the "IsrequireStop" status.
                        if (this.IsRequiredStop)
                        {
                            break;
                        }
                    }

                    lock (threadLockObjectForAppendLog)
                    {
                        string logMsg = string.Format("Listening............ The listen thread: managed id[{0}].", Thread.CurrentThread.ManagedThreadId);
                        DiscoveryProcessHelper.AppendLogs(currentHelperType, DateTime.Now, logMsg);
                    }
                    NetworkStream netstream = client.GetStream();
                    try
                    {
                        byte[] buffer = new byte[2048];

                        int    receivelength = netstream.Read(buffer, 0, 2048);
                        string requeststring = Encoding.UTF8.GetString(buffer, 0, receivelength);

                        if (!requeststring.StartsWith(@"GET /hosting/discovery", StringComparison.OrdinalIgnoreCase))
                        {
                            break;
                        }
                    }
                    catch (Exception ex)
                    {
                        lock (threadLockObjectForAppendLog)
                        {
                            DiscoveryProcessHelper.AppendLogs(currentHelperType, DateTime.Now, string.Format("The listen thread catches an [{0}] exception:[{1}].", ex.GetType().Name, ex.Message));
                        }

                        lock (threadLockStaticObjectForVisitThread)
                        {
                            if (this.IsRequiredStop)
                            {
                                lock (threadLockObjectForAppendLog)
                                {
                                    DiscoveryProcessHelper.AppendLogs(currentHelperType, DateTime.Now, "Requires stopping the Httplistener.");
                                }

                                return;
                            }
                            else
                            {
                                this.RestartListener();
                            }
                        }
                    }
                    bool writeResponseSucceed = false;
                    try
                    {
                        string statusLine = "HTTP/1.1 200 OK\r\n";
                        byte[] responseStatusLineBytes = Encoding.UTF8.GetBytes(statusLine);
                        string responseHeader          =
                            string.Format(
                                "Content-Type: text/xml; charset=UTf-8\r\nContent-Length: {0}\r\n", this.ResponseDiscovery.Length);
                        byte[] responseHeaderBytes = Encoding.UTF8.GetBytes(responseHeader);
                        byte[] responseBodyBytes   = Encoding.UTF8.GetBytes(this.ResponseDiscovery);
                        writeResponseSucceed = true;
                        netstream.Write(responseStatusLineBytes, 0, responseStatusLineBytes.Length);
                        netstream.Write(responseHeaderBytes, 0, responseHeaderBytes.Length);
                        netstream.Write(new byte[] { 13, 10 }, 0, 2);
                        netstream.Write(responseBodyBytes, 0, responseBodyBytes.Length);
                        client.Close();
                    }
                    catch (Exception ex)
                    {
                        lock (threadLockObjectForAppendLog)
                        {
                            DiscoveryProcessHelper.AppendLogs(currentHelperType, DateTime.Now, string.Format("The listen thread catches an [{0}] exception:[{1}] on responding.", ex.GetType().Name, ex.Message));
                        }

                        lock (threadLockStaticObjectForVisitThread)
                        {
                            if (this.IsRequiredStop)
                            {
                                lock (threadLockObjectForAppendLog)
                                {
                                    DiscoveryProcessHelper.AppendLogs(currentHelperType, DateTime.Now, string.Format("Catch an exception:[{0}]. Current requires stopping the Httplistener. Thread managed Id[{1}].", ex.Message, Thread.CurrentThread.ManagedThreadId));
                                }

                                return;
                            }
                            else
                            {
                                this.RestartListener();
                            }
                        }
                    }

                    if (writeResponseSucceed)
                    {
                        lock (threadLockStaticObjectForVisitThread)
                        {
                            // Setting the status.
                            if (!hasResponseDiscoveryRequestSucceed)
                            {
                                hasResponseDiscoveryRequestSucceed = true;
                            }
                        }

                        lock (threadLockObjectForAppendLog)
                        {
                            DiscoveryProcessHelper.AppendLogs(
                                currentHelperType,
                                DateTime.Now,
                                string.Format(
                                    "Response the discovery requestsucceed! The listen thread managedId[{0}]",
                                    Thread.CurrentThread.ManagedThreadId));
                        }
                    }
                }
                catch (SocketException ee)
                {
                    DiscoveryProcessHelper.AppendLogs(
                        currentHelperType,
                        DateTime.Now,
                        string.Format("SocketException: {0}", ee.Message));
                }
            }
        }
        /// <summary>
        /// A method is used to listening the discovery request. It will be executed by a thread which is started on ListenThreadInstance method.
        /// </summary>
        protected void ListenToRequest()
        {
            // If the listener is listening, just keep on execute below code.
            while (ListenInstance.IsListening)
            {
                // if the calling thread requires stopping the listening mission, just return and exit the loop. This value of "IsrequireStop" property is managed by "StopListen" method.
                if (this.IsRequiredStop)
                {
                    break;
                }

                lock (threadLockStaticObjectForVisitThread)
                {
                    // Double check the "IsrequireStop" status.
                    if (this.IsRequiredStop)
                    {
                        break;
                    }
                }

                lock (threadLockObjectForAppendLog)
                {
                    string logMsg = string.Format("Listening............ The listen thread: managed id[{0}].", Thread.CurrentThread.ManagedThreadId);
                    DiscoveryProcessHelper.AppendLogs(currentHelperType, DateTime.Now, logMsg);
                }

                // Get an incoming request.
                HttpListenerContext  listenContext            = null;
                HttpListenerResponse responseOfCurrentRequest = null;
                HttpListenerRequest  currentRequest           = null;

                try
                {
                    listenContext            = ListenInstance.GetContext();
                    currentRequest           = listenContext.Request as HttpListenerRequest;
                    responseOfCurrentRequest = listenContext.Response as HttpListenerResponse;

                    if (!currentRequest.RawUrl.Equals(@"/hosting/discovery", StringComparison.OrdinalIgnoreCase))
                    {
                        break;
                    }
                }
                catch (Exception ex)
                {
                    lock (threadLockObjectForAppendLog)
                    {
                        DiscoveryProcessHelper.AppendLogs(currentHelperType, DateTime.Now, string.Format("The listen thread catches an [{0}] exception:[{1}].", ex.GetType().Name, ex.Message));
                    }

                    lock (threadLockStaticObjectForVisitThread)
                    {
                        if (this.IsRequiredStop)
                        {
                            lock (threadLockObjectForAppendLog)
                            {
                                DiscoveryProcessHelper.AppendLogs(currentHelperType, DateTime.Now, "Requires stopping the Httplistener.");
                            }

                            return;
                        }
                        else
                        {
                            this.RestartListener();
                        }
                    }
                }

                if (responseOfCurrentRequest != null)
                {
                    responseOfCurrentRequest.ContentType     = "text/xml";
                    responseOfCurrentRequest.ContentEncoding = Encoding.UTF8;
                    responseOfCurrentRequest.StatusCode      = 200;

                    // Get the xml response.
                    XmlDocument reponseXml = new XmlDocument();
                    reponseXml.LoadXml(this.ResponseDiscovery);
                    bool writeResponseSucceed = false;
                    try
                    {
                        using (XmlTextWriter xmlWriter = new XmlTextWriter(responseOfCurrentRequest.OutputStream, Encoding.UTF8))
                        {
                            reponseXml.Save(xmlWriter);
                            writeResponseSucceed = true;
                        }
                    }
                    catch (Exception ex)
                    {
                        lock (threadLockObjectForAppendLog)
                        {
                            DiscoveryProcessHelper.AppendLogs(currentHelperType, DateTime.Now, string.Format("The listen thread catches an [{0}] exception:[{1}] on responding.", ex.GetType().Name, ex.Message));
                        }

                        lock (threadLockStaticObjectForVisitThread)
                        {
                            if (this.IsRequiredStop)
                            {
                                lock (threadLockObjectForAppendLog)
                                {
                                    DiscoveryProcessHelper.AppendLogs(currentHelperType, DateTime.Now, string.Format("Catch an exception:[{0}]. Current requires stopping the Httplistener. Thread managed Id[{1}].", ex.Message, Thread.CurrentThread.ManagedThreadId));
                                }

                                return;
                            }
                            else
                            {
                                this.RestartListener();
                            }
                        }
                    }

                    if (writeResponseSucceed)
                    {
                        lock (threadLockStaticObjectForVisitThread)
                        {
                            // Setting the status.
                            if (!hasResponseDiscoveryRequestSucceed)
                            {
                                hasResponseDiscoveryRequestSucceed = true;
                            }
                        }

                        lock (threadLockObjectForAppendLog)
                        {
                            DiscoveryProcessHelper.AppendLogs(
                                currentHelperType,
                                DateTime.Now,
                                string.Format(
                                    "Response the discovery request from [{0}] succeed! The listen thread managedId[{1}]",
                                    currentRequest.UserHostName,
                                    Thread.CurrentThread.ManagedThreadId));
                        }
                    }
                }
            }
        }