// Copyright 2012 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
//       notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
//       copyright notice, this list of conditions and the following
//       disclaimer in the documentation and/or other materials provided
//       with the distribution.
//     * Neither the name of Google Inc. nor the names of its
//       contributors may be used to endorse or promote products derived
//       from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#ifdef ENABLE_DEBUGGER_SUPPORT

#include "v8.h"
#include "debug.h"
#include "debug-agent.h"
#include "platform/socket.h"

namespace v8 {
namespace internal {

// Public V8 debugger API message handler function. This function just delegates
// to the debugger agent through it's data parameter.
void DebuggerAgentMessageHandler(const v8::Debug::Message& message) {
  Isolate* isolate = reinterpret_cast<Isolate*>(message.GetIsolate());
  DebuggerAgent* agent = isolate->debugger_agent_instance();
  ASSERT(agent != NULL);
  agent->DebuggerMessage(message);
}


DebuggerAgent::DebuggerAgent(Isolate* isolate, const char* name, int port)
  : Thread(name),
    isolate_(isolate),
    name_(StrDup(name)),
    port_(port),
    server_(new Socket),
    terminate_(false),
    session_(NULL),
    terminate_now_(0),
    listening_(0) {
  ASSERT(isolate_->debugger_agent_instance() == NULL);
  isolate_->set_debugger_agent_instance(this);
}


DebuggerAgent::~DebuggerAgent() {
  isolate_->set_debugger_agent_instance(NULL);
  delete server_;
}


// Debugger agent main thread.
void DebuggerAgent::Run() {
  // Allow this socket to reuse port even if still in TIME_WAIT.
  server_->SetReuseAddress(true);

  // First bind the socket to the requested port.
  bool bound = false;
  while (!bound && !terminate_) {
    bound = server_->Bind(port_);

    // If an error occurred wait a bit before retrying. The most common error
    // would be that the port is already in use so this avoids a busy loop and
    // make the agent take over the port when it becomes free.
    if (!bound) {
      const TimeDelta kTimeout = TimeDelta::FromSeconds(1);
      PrintF("Failed to open socket on port %d, "
          "waiting %d ms before retrying\n", port_,
          static_cast<int>(kTimeout.InMilliseconds()));
      if (!terminate_now_.WaitFor(kTimeout)) {
        if (terminate_) return;
      }
    }
  }

  // Accept connections on the bound port.
  while (!terminate_) {
    bool ok = server_->Listen(1);
    listening_.Signal();
    if (ok) {
      // Accept the new connection.
      Socket* client = server_->Accept();
      ok = client != NULL;
      if (ok) {
        // Create and start a new session.
        CreateSession(client);
      }
    }
  }
}


void DebuggerAgent::Shutdown() {
  // Set the termination flag.
  terminate_ = true;

  // Signal termination and make the server exit either its listen call or its
  // binding loop. This makes sure that no new sessions can be established.
  terminate_now_.Signal();
  server_->Shutdown();
  Join();

  // Close existing session if any.
  CloseSession();
}


void DebuggerAgent::WaitUntilListening() {
  listening_.Wait();
}

static const char* kCreateSessionMessage =
    "Remote debugging session already active\r\n";

void DebuggerAgent::CreateSession(Socket* client) {
  LockGuard<RecursiveMutex> session_access_guard(&session_access_);

  // If another session is already established terminate this one.
  if (session_ != NULL) {
    int len = StrLength(kCreateSessionMessage);
    int res = client->Send(kCreateSessionMessage, len);
    delete client;
    USE(res);
    return;
  }

  // Create a new session and hook up the debug message handler.
  session_ = new DebuggerAgentSession(this, client);
  isolate_->debugger()->SetMessageHandler(DebuggerAgentMessageHandler);
  session_->Start();
}


void DebuggerAgent::CloseSession() {
  LockGuard<RecursiveMutex> session_access_guard(&session_access_);

  // Terminate the session.
  if (session_ != NULL) {
    session_->Shutdown();
    session_->Join();
    delete session_;
    session_ = NULL;
  }
}


void DebuggerAgent::DebuggerMessage(const v8::Debug::Message& message) {
  LockGuard<RecursiveMutex> session_access_guard(&session_access_);

  // Forward the message handling to the session.
  if (session_ != NULL) {
    v8::String::Value val(message.GetJSON());
    session_->DebuggerMessage(Vector<uint16_t>(const_cast<uint16_t*>(*val),
                              val.length()));
  }
}


DebuggerAgentSession::~DebuggerAgentSession() {
  delete client_;
}


void DebuggerAgent::OnSessionClosed(DebuggerAgentSession* session) {
  // Don't do anything during termination.
  if (terminate_) {
    return;
  }

  // Terminate the session.
  LockGuard<RecursiveMutex> session_access_guard(&session_access_);
  ASSERT(session == session_);
  if (session == session_) {
    session_->Shutdown();
    delete session_;
    session_ = NULL;
  }
}


void DebuggerAgentSession::Run() {
  // Send the hello message.
  bool ok = DebuggerAgentUtil::SendConnectMessage(client_, agent_->name_.get());
  if (!ok) return;

  while (true) {
    // Read data from the debugger front end.
    SmartArrayPointer<char> message =
        DebuggerAgentUtil::ReceiveMessage(client_);

    const char* msg = message.get();
    bool is_closing_session = (msg == NULL);

    if (msg == NULL) {
      // If we lost the connection, then simulate a disconnect msg:
      msg = "{\"seq\":1,\"type\":\"request\",\"command\":\"disconnect\"}";

    } else {
      // Check if we're getting a disconnect request:
      const char* disconnectRequestStr =
          "\"type\":\"request\",\"command\":\"disconnect\"}";
      const char* result = strstr(msg, disconnectRequestStr);
      if (result != NULL) {
        is_closing_session = true;
      }
    }

    // Convert UTF-8 to UTF-16.
    unibrow::Utf8Decoder<128> decoder(msg, StrLength(msg));
    int utf16_length = decoder.Utf16Length();
    ScopedVector<uint16_t> temp(utf16_length + 1);
    decoder.WriteUtf16(temp.start(), utf16_length);

    // Send the request received to the debugger.
    v8::Debug::SendCommand(temp.start(),
                           utf16_length,
                           NULL,
                           reinterpret_cast<v8::Isolate*>(agent_->isolate()));

    if (is_closing_session) {
      // Session is closed.
      agent_->OnSessionClosed(this);
      return;
    }
  }
}


void DebuggerAgentSession::DebuggerMessage(Vector<uint16_t> message) {
  DebuggerAgentUtil::SendMessage(client_, message);
}


void DebuggerAgentSession::Shutdown() {
  // Shutdown the socket to end the blocking receive.
  client_->Shutdown();
}


const char* const DebuggerAgentUtil::kContentLength = "Content-Length";


SmartArrayPointer<char> DebuggerAgentUtil::ReceiveMessage(Socket* conn) {
  int received;

  // Read header.
  int content_length = 0;
  while (true) {
    const int kHeaderBufferSize = 80;
    char header_buffer[kHeaderBufferSize];
    int header_buffer_position = 0;
    char c = '\0';  // One character receive buffer.
    char prev_c = '\0';  // Previous character.

    // Read until CRLF.
    while (!(c == '\n' && prev_c == '\r')) {
      prev_c = c;
      received = conn->Receive(&c, 1);
      if (received == 0) {
        PrintF("Error %d\n", Socket::GetLastError());
        return SmartArrayPointer<char>();
      }

      // Add character to header buffer.
      if (header_buffer_position < kHeaderBufferSize) {
        header_buffer[header_buffer_position++] = c;
      }
    }

    // Check for end of header (empty header line).
    if (header_buffer_position == 2) {  // Receive buffer contains CRLF.
      break;
    }

    // Terminate header.
    ASSERT(header_buffer_position > 1);  // At least CRLF is received.
    ASSERT(header_buffer_position <= kHeaderBufferSize);
    header_buffer[header_buffer_position - 2] = '\0';

    // Split header.
    char* key = header_buffer;
    char* value = NULL;
    for (int i = 0; header_buffer[i] != '\0'; i++) {
      if (header_buffer[i] == ':') {
        header_buffer[i] = '\0';
        value = header_buffer + i + 1;
        while (*value == ' ') {
          value++;
        }
        break;
      }
    }

    // Check that key is Content-Length.
    if (strcmp(key, kContentLength) == 0) {
      // Get the content length value if present and within a sensible range.
      if (value == NULL || strlen(value) > 7) {
        return SmartArrayPointer<char>();
      }
      for (int i = 0; value[i] != '\0'; i++) {
        // Bail out if illegal data.
        if (value[i] < '0' || value[i] > '9') {
          return SmartArrayPointer<char>();
        }
        content_length = 10 * content_length + (value[i] - '0');
      }
    } else {
      // For now just print all other headers than Content-Length.
      PrintF("%s: %s\n", key, value != NULL ? value : "(no value)");
    }
  }

  // Return now if no body.
  if (content_length == 0) {
    return SmartArrayPointer<char>();
  }

  // Read body.
  char* buffer = NewArray<char>(content_length + 1);
  received = ReceiveAll(conn, buffer, content_length);
  if (received < content_length) {
    PrintF("Error %d\n", Socket::GetLastError());
    return SmartArrayPointer<char>();
  }
  buffer[content_length] = '\0';

  return SmartArrayPointer<char>(buffer);
}


bool DebuggerAgentUtil::SendConnectMessage(Socket* conn,
                                           const char* embedding_host) {
  static const int kBufferSize = 80;
  char buffer[kBufferSize];  // Sending buffer.
  bool ok;
  int len;

  // Send the header.
  len = OS::SNPrintF(Vector<char>(buffer, kBufferSize),
                     "Type: connect\r\n");
  ok = conn->Send(buffer, len);
  if (!ok) return false;

  len = OS::SNPrintF(Vector<char>(buffer, kBufferSize),
                     "V8-Version: %s\r\n", v8::V8::GetVersion());
  ok = conn->Send(buffer, len);
  if (!ok) return false;

  len = OS::SNPrintF(Vector<char>(buffer, kBufferSize),
                     "Protocol-Version: 1\r\n");
  ok = conn->Send(buffer, len);
  if (!ok) return false;

  if (embedding_host != NULL) {
    len = OS::SNPrintF(Vector<char>(buffer, kBufferSize),
                       "Embedding-Host: %s\r\n", embedding_host);
    ok = conn->Send(buffer, len);
    if (!ok) return false;
  }

  len = OS::SNPrintF(Vector<char>(buffer, kBufferSize),
                     "%s: 0\r\n", kContentLength);
  ok = conn->Send(buffer, len);
  if (!ok) return false;

  // Terminate header with empty line.
  len = OS::SNPrintF(Vector<char>(buffer, kBufferSize), "\r\n");
  ok = conn->Send(buffer, len);
  if (!ok) return false;

  // No body for connect message.

  return true;
}


bool DebuggerAgentUtil::SendMessage(Socket* conn,
                                    const Vector<uint16_t> message) {
  static const int kBufferSize = 80;
  char buffer[kBufferSize];  // Sending buffer both for header and body.

  // Calculate the message size in UTF-8 encoding.
  int utf8_len = 0;
  int previous = unibrow::Utf16::kNoPreviousCharacter;
  for (int i = 0; i < message.length(); i++) {
    uint16_t character = message[i];
    utf8_len += unibrow::Utf8::Length(character, previous);
    previous = character;
  }

  // Send the header.
  int len = OS::SNPrintF(Vector<char>(buffer, kBufferSize),
                         "%s: %d\r\n", kContentLength, utf8_len);
  if (conn->Send(buffer, len) < len) {
    return false;
  }

  // Terminate header with empty line.
  len = OS::SNPrintF(Vector<char>(buffer, kBufferSize), "\r\n");
  if (conn->Send(buffer, len) < len) {
    return false;
  }

  // Send message body as UTF-8.
  int buffer_position = 0;  // Current buffer position.
  previous = unibrow::Utf16::kNoPreviousCharacter;
  for (int i = 0; i < message.length(); i++) {
    // Write next UTF-8 encoded character to buffer.
    uint16_t character = message[i];
    buffer_position +=
        unibrow::Utf8::Encode(buffer + buffer_position, character, previous);
    ASSERT(buffer_position <= kBufferSize);

    // Send buffer if full or last character is encoded.
    if (kBufferSize - buffer_position <
          unibrow::Utf16::kMaxExtraUtf8BytesForOneUtf16CodeUnit ||
        i == message.length() - 1) {
      if (unibrow::Utf16::IsLeadSurrogate(character)) {
        const int kEncodedSurrogateLength =
            unibrow::Utf16::kUtf8BytesToCodeASurrogate;
        ASSERT(buffer_position >= kEncodedSurrogateLength);
        len = buffer_position - kEncodedSurrogateLength;
        if (conn->Send(buffer, len) < len) {
          return false;
        }
        for (int i = 0; i < kEncodedSurrogateLength; i++) {
          buffer[i] = buffer[buffer_position + i];
        }
        buffer_position = kEncodedSurrogateLength;
      } else {
        len = buffer_position;
        if (conn->Send(buffer, len) < len) {
          return false;
        }
        buffer_position = 0;
      }
    }
    previous = character;
  }

  return true;
}


bool DebuggerAgentUtil::SendMessage(Socket* conn,
                                    const v8::Handle<v8::String> request) {
  static const int kBufferSize = 80;
  char buffer[kBufferSize];  // Sending buffer both for header and body.

  // Convert the request to UTF-8 encoding.
  v8::String::Utf8Value utf8_request(request);

  // Send the header.
  int len = OS::SNPrintF(Vector<char>(buffer, kBufferSize),
                         "Content-Length: %d\r\n", utf8_request.length());
  if (conn->Send(buffer, len) < len) {
    return false;
  }

  // Terminate header with empty line.
  len = OS::SNPrintF(Vector<char>(buffer, kBufferSize), "\r\n");
  if (conn->Send(buffer, len) < len) {
    return false;
  }

  // Send message body as UTF-8.
  len = utf8_request.length();
  if (conn->Send(*utf8_request, len) < len) {
    return false;
  }

  return true;
}


// Receive the full buffer before returning unless an error occours.
int DebuggerAgentUtil::ReceiveAll(Socket* conn, char* data, int len) {
  int total_received = 0;
  while (total_received < len) {
    int received = conn->Receive(data + total_received, len - total_received);
    if (received == 0) {
      return total_received;
    }
    total_received += received;
  }
  return total_received;
}

} }  // namespace v8::internal

#endif  // ENABLE_DEBUGGER_SUPPORT
