text: /***
  * Copyright (C) Microsoft. All rights reserved.
  * Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
  *
  * =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
  *
  * HTTP Library: Request and reply message definitions (server side).
  *
  * =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  ****/
  #include "stdafx.h"
  
  #include "../common/internal_http_helpers.h"
  using namespace web;
  using namespace utility;
  
  namespace web { namespace http
  {
  
  // Actual initiates sending the response.
  pplx::task<void> details::_http_request::_reply_impl(http_response response)
  {
      // If the user didn't explicitly set a reason phrase then we should have it default
      // if they used one of the standard known status codes.
      if (response.reason_phrase().empty())
      {
          response.set_reason_phrase(get_default_reason_phrase(response.status_code()));
      }
  
      pplx::task<void> response_completed;
  
  #if !defined(__cplusplus_winrt) && _WIN32_WINNT >= _WIN32_WINNT_VISTA
      auto server_api = experimental::details::http_server_api::server_api();
  
      if (m_server_context && server_api)
      {
          // Add a task-based continuation so no exceptions thrown from the task go 'unobserved'.
          response._set_server_context(std::move(m_server_context));
          response_completed = server_api->respond(response);
          response_completed.then([](pplx::task<void> t)
          {
              try { t.wait(); } catch(...) {}
          });
      }
      else
  #endif
      {
          // There's no server context. The message may be replied to locally, as in a HTTP client
          // pipeline stage. There's no sending required, so we can simply consider the reply
          // done and return an already filled-in task.
          response_completed = pplx::task_from_result();
      }
  
      m_response.set(response);
      return response_completed;
  }
  
  pplx::task<void> details::_http_request::_reply_if_not_already(status_code status)
  {
      const long expected = 0;
      const long desired = 1;
      if (pplx::details::atomic_compare_exchange(m_initiated_response, desired, expected) == expected)
      {
          return _reply_impl(http_response(status));
      }
      return pplx::task_from_result();
  }
  
  pplx::task<void> details::_http_request::reply(const http_response &response)
  {
      if(pplx::details::atomic_increment(m_initiated_response) != 1l)
      {
          throw http_exception(U("Error: trying to send multiple responses to an HTTP request"));
      }
      return _reply_impl(response);
  }
  
  }} // namespace web::http
  